summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/graphql/calls_gitaly/field_extension_spec.rb
blob: 1d8849f7e38d5926d830fe973979035507d046c7 (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
# frozen_string_literal: true
require 'spec_helper'

RSpec.describe Gitlab::Graphql::CallsGitaly::FieldExtension, :request_store do
  include GraphqlHelpers

  let(:field_args) { {} }
  let(:owner) { fresh_object_type }
  let(:field) do
    ::Types::BaseField.new(name: 'value', type: GraphQL::STRING_TYPE, null: true, owner: owner, **field_args)
  end

  def resolve_value
    resolve_field(field, { value: 'foo' }, object_type: owner)
  end

  context 'when the field calls gitaly' do
    before do
      owner.define_method :value do
        Gitlab::SafeRequestStore['gitaly_call_actual'] = 1
        'fresh-from-the-gitaly-mines!'
      end
    end

    context 'when the field has a constant complexity' do
      let(:field_args) { { complexity: 100 } }

      it 'allows the call' do
        expect { resolve_value }.not_to raise_error
      end
    end

    context 'when the field declares that it calls gitaly' do
      let(:field_args) { { calls_gitaly: true } }

      it 'allows the call' do
        expect { resolve_value }.not_to raise_error
      end
    end

    context 'when the field does not have these arguments' do
      let(:field_args) { {} }

      it 'notices, and raises, mentioning the field' do
        expect { resolve_value }.to raise_error(include('Object.value'))
      end
    end
  end

  context 'when it does not call gitaly' do
    let(:field_args) { {} }

    it 'does not raise' do
      value = resolve_value

      expect(value).to eq 'foo'
    end
  end

  context 'when some field calls gitaly while we were waiting' do
    let(:extension) { described_class.new(field: field, options: {}) }

    it 'is acceptable if all are accounted for' do
      object = :anything
      arguments = :any_args

      ::Gitlab::SafeRequestStore['gitaly_call_actual'] = 3
      ::Gitlab::SafeRequestStore['graphql_gitaly_accounted_for'] = 0

      expect do |b|
        extension.resolve(object: object, arguments: arguments, &b)
      end.to yield_with_args(object, arguments, [3, 0])

      ::Gitlab::SafeRequestStore['gitaly_call_actual'] = 13
      ::Gitlab::SafeRequestStore['graphql_gitaly_accounted_for'] = 10

      expect { extension.after_resolve(value: 'foo', memo: [3, 0]) }.not_to raise_error
    end

    it 'is unacceptable if some of the calls are unaccounted for' do
      ::Gitlab::SafeRequestStore['gitaly_call_actual'] = 10
      ::Gitlab::SafeRequestStore['graphql_gitaly_accounted_for'] = 9

      expect { extension.after_resolve(value: 'foo', memo: [0, 0]) }.to raise_error(include('Object.value'))
    end
  end
end