summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/gitaly_client/call_spec.rb
blob: 099307fc4e12a73ddb60e3c056741e3aafe4df92 (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
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::GitalyClient::Call do
  describe '#call', :request_store do
    let(:client) { Gitlab::GitalyClient }
    let(:storage) { 'default' }
    let(:remote_storage) { nil }
    let(:request) { Gitaly::FindLocalBranchesRequest.new }
    let(:rpc) { :find_local_branches }
    let(:service) { :ref_service }
    let(:timeout) { client.long_timeout }

    subject do
      described_class.new(storage, service, rpc, request, remote_storage, timeout).call
    end

    before do
      allow(client).to receive(:execute) { response }
      allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?) { true }
    end

    def expect_call_details_to_match(duration_higher_than: 0)
      expect(client.list_call_details.size).to eq(1)
      expect(client.list_call_details.first)
        .to match a_hash_including(
          start: a_value > 0,
          feature: "#{service}##{rpc}",
          duration: a_value > duration_higher_than,
          request: an_instance_of(Hash),
          rpc: rpc,
          backtrace: an_instance_of(Array)
        )
    end

    context 'when the response is not an enumerator' do
      let(:response) do
        Gitaly::FindLocalBranchesResponse.new
      end

      it 'returns the response' do
        expect(subject).to eq(response)
      end

      it 'stores timings and call details' do
        subject

        expect(client.query_time).to be > 0
        expect_call_details_to_match
      end

      context 'when err' do
        before do
          allow(client).to receive(:execute).and_raise(StandardError)
        end

        it 'stores timings and call details' do
          expect { subject }.to raise_error(StandardError)

          expect(client.query_time).to be > 0
          expect_call_details_to_match
        end
      end
    end

    context 'when the response is an enumerator' do
      let(:response) do
        Enumerator.new do |yielder|
          yielder << 1
          yielder << 2
        end
      end

      it 'returns a consumable enumerator' do
        instrumented_response = subject

        expect(instrumented_response).to be_a(Enumerator)
        expect(instrumented_response.to_a).to eq([1, 2])
      end

      context 'time measurements' do
        let(:response) do
          Enumerator.new do |yielder|
            sleep 0.1
            yielder << 1
            sleep 0.2
            yielder << 2
          end
        end

        it 'records full rpc stream consumption' do
          subject.to_a

          expect(client.query_time).to be > 0.3
          expect_call_details_to_match(duration_higher_than: 0.3)
        end

        it 'records partial rpc stream consumption' do
          subject.first

          expect(client.query_time).to be > 0.1
          expect_call_details_to_match(duration_higher_than: 0.1)
        end

        context 'when err' do
          let(:response) do
            Enumerator.new do |yielder|
              sleep 0.2
              yielder << 1
              raise StandardError
            end
          end

          it 'records partial rpc stream consumption' do
            expect { subject.to_a }.to raise_error(StandardError)

            expect(client.query_time).to be > 0.2
            expect_call_details_to_match(duration_higher_than: 0.2)
          end
        end
      end
    end
  end
end