override_spec.rb 4.89 KB
Newer Older
1
require 'fast_spec_helper'
2 3

describe Gitlab::Utils::Override do
4 5 6 7 8 9 10
  let(:base) do
    Struct.new(:good) do
      def self.good
        0
      end
    end
  end
11 12 13 14 15 16 17

  let(:derived) { Class.new(base).tap { |m| m.extend described_class } }
  let(:extension) { Module.new.tap { |m| m.extend described_class } }

  let(:prepending_class) { base.tap { |m| m.prepend extension } }
  let(:including_class) { base.tap { |m| m.include extension } }

18 19 20 21 22 23 24 25
  let(:prepending_class_methods) do
    base.tap { |m| m.singleton_class.prepend extension }
  end

  let(:extending_class_methods) do
    base.tap { |m| m.extend extension }
  end

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
  let(:klass) { subject }

  def good(mod)
    mod.module_eval do
      override :good
      def good
        super.succ
      end
    end

    mod
  end

  def bad(mod)
    mod.module_eval do
      override :bad
      def bad
        true
      end
    end

    mod
  end

  shared_examples 'checking as intended' do
    it 'checks ok for overriding method' do
      good(subject)
53
      result = instance.good
54 55 56 57 58 59 60 61

      expect(result).to eq(1)
      described_class.verify!
    end

    it 'raises NotImplementedError when it is not overriding anything' do
      expect do
        bad(subject)
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
        instance.bad
        described_class.verify!
      end.to raise_error(NotImplementedError)
    end
  end

  shared_examples 'checking as intended, nothing was overridden' do
    it 'raises NotImplementedError because it is not overriding it' do
      expect do
        good(subject)
        instance.good
        described_class.verify!
      end.to raise_error(NotImplementedError)
    end

    it 'raises NotImplementedError when it is not overriding anything' do
      expect do
        bad(subject)
        instance.bad
81 82 83 84 85 86 87 88
        described_class.verify!
      end.to raise_error(NotImplementedError)
    end
  end

  shared_examples 'nothing happened' do
    it 'does not complain when it is overriding something' do
      good(subject)
89
      result = instance.good
90 91 92 93 94 95 96

      expect(result).to eq(1)
      described_class.verify!
    end

    it 'does not complain when it is not overriding anything' do
      bad(subject)
97
      result = instance.bad
98 99 100 101 102 103 104 105 106 107 108 109

      expect(result).to eq(true)
      described_class.verify!
    end
  end

  before do
    # Make sure we're not touching the internal cache
    allow(described_class).to receive(:extensions).and_return({})
  end

  describe '#override' do
110 111
    context 'when instance is klass.new(0)' do
      let(:instance) { klass.new(0) }
112

113 114 115 116
      context 'when STATIC_VERIFICATION is set' do
        before do
          stub_env('STATIC_VERIFICATION', 'true')
        end
117

118 119 120 121 122 123 124 125 126 127 128 129
        context 'when subject is a class' do
          subject { derived }

          it_behaves_like 'checking as intended'
        end

        context 'when subject is a module, and class is prepending it' do
          subject { extension }
          let(:klass) { prepending_class }

          it_behaves_like 'checking as intended'
        end
130

131 132 133
        context 'when subject is a module, and class is including it' do
          subject { extension }
          let(:klass) { including_class }
134

135 136
          it_behaves_like 'checking as intended, nothing was overridden'
        end
137 138
      end

139 140 141 142
      context 'when STATIC_VERIFICATION is not set' do
        before do
          stub_env('STATIC_VERIFICATION', nil)
        end
143

144 145 146 147
        context 'when subject is a class' do
          subject { derived }

          it_behaves_like 'nothing happened'
148 149
        end

150 151 152 153 154
        context 'when subject is a module, and class is prepending it' do
          subject { extension }
          let(:klass) { prepending_class }

          it_behaves_like 'nothing happened'
155 156
        end

157 158 159
        context 'when subject is a module, and class is including it' do
          subject { extension }
          let(:klass) { including_class }
160

161 162 163
          it 'does not complain when it is overriding something' do
            good(subject)
            result = instance.good
164

165 166 167
            expect(result).to eq(0)
            described_class.verify!
          end
168

169 170 171
          it 'does not complain when it is not overriding anything' do
            bad(subject)
            result = instance.bad
172

173 174 175 176 177
            expect(result).to eq(true)
            described_class.verify!
          end
        end
      end
178 179
    end

180 181
    context 'when instance is klass' do
      let(:instance) { klass }
182

183 184 185 186
      context 'when STATIC_VERIFICATION is set' do
        before do
          stub_env('STATIC_VERIFICATION', 'true')
        end
187

188 189 190
        context 'when subject is a module, and class is prepending it' do
          subject { extension }
          let(:klass) { prepending_class_methods }
191

192 193
          it_behaves_like 'checking as intended'
        end
194

195 196 197 198 199 200
        context 'when subject is a module, and class is extending it' do
          subject { extension }
          let(:klass) { extending_class_methods }

          it_behaves_like 'checking as intended, nothing was overridden'
        end
201 202 203 204
      end
    end
  end
end