summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/git/env_spec.rb
blob: 03836d49518998836bbceadeccce51013f2ee5d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
require 'spec_helper'

describe Gitlab::Git::Env do
  describe ".set" do
    context 'with RequestStore.store disabled' do
      before do
        allow(RequestStore).to receive(:active?).and_return(false)
      end

      it 'does not store anything' do
        described_class.set(GIT_OBJECT_DIRECTORY: 'foo')

        expect(described_class.all).to be_empty
      end
    end

    context 'with RequestStore.store enabled' do
      before do
        allow(RequestStore).to receive(:active?).and_return(true)
      end

      it 'whitelist some `GIT_*` variables and stores them using RequestStore' do
        described_class.set(
          GIT_OBJECT_DIRECTORY: 'foo',
          GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar',
          GIT_EXEC_PATH: 'baz',
          PATH: '~/.bin:/bin')

        expect(described_class[:GIT_OBJECT_DIRECTORY]).to eq('foo')
        expect(described_class[:GIT_ALTERNATE_OBJECT_DIRECTORIES]).to eq('bar')
        expect(described_class[:GIT_EXEC_PATH]).to be_nil
        expect(described_class[:bar]).to be_nil
      end
    end
  end

  describe ".all" do
    context 'with RequestStore.store enabled' do
      before do
        allow(RequestStore).to receive(:active?).and_return(true)
        described_class.set(
          GIT_OBJECT_DIRECTORY: 'foo',
          GIT_ALTERNATE_OBJECT_DIRECTORIES: ['bar'])
      end

      it 'returns an env hash' do
        expect(described_class.all).to eq({
          'GIT_OBJECT_DIRECTORY' => 'foo',
          'GIT_ALTERNATE_OBJECT_DIRECTORIES' => ['bar']
        })
      end
    end
  end

  describe ".to_env_hash" do
    context 'with RequestStore.store enabled' do
      using RSpec::Parameterized::TableSyntax

      let(:key) { 'GIT_OBJECT_DIRECTORY' }
      subject { described_class.to_env_hash }

      where(:input, :output) do
        nil         | nil
        'foo'       | 'foo'
        []          | ''
        ['foo']     | 'foo'
        %w[foo bar] | 'foo:bar'
      end

      with_them do
        before do
          allow(RequestStore).to receive(:active?).and_return(true)
          described_class.set(key.to_sym => input)
        end

        it 'puts the right value in the hash' do
          if output
            expect(subject.fetch(key)).to eq(output)
          else
            expect(subject.has_key?(key)).to eq(false)
          end
        end
      end
    end
  end

  describe ".[]" do
    context 'with RequestStore.store enabled' do
      before do
        allow(RequestStore).to receive(:active?).and_return(true)
      end

      before do
        described_class.set(
          GIT_OBJECT_DIRECTORY: 'foo',
          GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar')
      end

      it 'returns a stored value for an existing key' do
        expect(described_class[:GIT_OBJECT_DIRECTORY]).to eq('foo')
      end

      it 'returns nil for an non-existing key' do
        expect(described_class[:foo]).to be_nil
      end
    end
  end

  describe 'thread-safety' do
    context 'with RequestStore.store enabled' do
      before do
        allow(RequestStore).to receive(:active?).and_return(true)
        described_class.set(GIT_OBJECT_DIRECTORY: 'foo')
      end

      it 'is thread-safe' do
        another_thread = Thread.new do
          described_class.set(GIT_OBJECT_DIRECTORY: 'bar')

          Thread.stop
          described_class[:GIT_OBJECT_DIRECTORY]
        end

        # Ensure another_thread runs first
        sleep 0.1 until another_thread.stop?

        expect(described_class[:GIT_OBJECT_DIRECTORY]).to eq('foo')

        another_thread.run
        expect(another_thread.value).to eq('bar')
      end
    end
  end
end