File: cmap_spec.rb

package info (click to toggle)
ruby-mongo 2.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,020 kB
  • sloc: ruby: 110,810; makefile: 5
file content (126 lines) | stat: -rw-r--r-- 4,022 bytes parent folder | download
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
# frozen_string_literal: true
# rubocop:todo all

require 'spec_helper'

require 'runners/cmap'

# Temporary scopes in all of the tests are needed to exclude endSessions
# commands being sent during cleanup from interfering with assertions.

describe 'Cmap' do
  clean_slate

  declare_topology_double

  let(:cluster) do
    double('cluster').tap do |cl|
      allow(cl).to receive(:topology).and_return(topology)
      allow(cl).to receive(:options).and_return({})
      allow(cl).to receive(:app_metadata).and_return(Mongo::Server::AppMetadata.new({}))
      allow(cl).to receive(:run_sdam_flow)
      allow(cl).to receive(:update_cluster_time)
      allow(cl).to receive(:cluster_time).and_return(nil)
    end
  end

  let(:options) do
    Mongo::Utils.shallow_symbolize_keys(Mongo::Client.canonicalize_ruby_options(
      SpecConfig.instance.all_test_options,
    )).update(monitoring_io: false, populator_io: true).tap do |options|
      # We have a wait queue timeout set in the test suite options, but having
      # this option set interferes with assertions in the cmap spec tests.
      options.delete(:wait_queue_timeout)
    end
  end

  CMAP_TESTS.each do |file|
    spec = Mongo::Cmap::Spec.new(file)

    context("#{spec.description} (#{file.sub(%r'.*/data/cmap/', '')})") do
      unless spec.satisfied?
        before(:all) do
          skip "Requirements not satisfied"
        end
      end

      before do
        subscriber = Mrss::EventSubscriber.new

        monitoring = Mongo::Monitoring.new(monitoring: false)
        monitoring.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)

        @server = register_server(
          Mongo::Server.new(
            ClusterConfig.instance.primary_address,
            cluster,
            monitoring,
            Mongo::Event::Listeners.new,
            options.merge(spec.pool_options)
          ).tap do |server|
            allow(server).to receive(:description).and_return(ClusterConfig.instance.primary_description)
            # Since we use a mock for the cluster, run_sdam_flow does not clear
            # the pool or mark the server unknown. Manually clear the pool and
            # mock the server as unknown.
            allow(server).to receive(:unknown!).and_wrap_original do |m, *args|
              m.call(*args)
              RSpec::Mocks.with_temporary_scope do
                allow(server).to receive(:unknown?).and_return(true)
                server.pool_internal&.clear(lazy: true)
              end
            end
          end
        )

        if app_name = spec.pool_options[:app_name]
          allow(cluster).to receive(:app_metadata).and_return(Mongo::Server::AppMetadata.new({ app_name: app_name }))
        end

        @client = ClusterTools.instance.direct_client(ClusterConfig.instance.primary_address,
          database: 'admin')
        spec.setup(@server, @client, subscriber)
      end

      after do
        if pool = @server&.pool_internal
          pool.disconnect!
        end

        spec.pool&.close
      end

      let!(:result) do
        if @server.load_balancer?
          allow_any_instance_of(Mongo::Server::Connection).to receive(:service_id).and_return('very fake')
        end
        spec.run
      end

      let(:verifier) do
        Mongo::Cmap::Verifier.new(spec)
      end

      it 'raises the correct error' do
        RSpec::Mocks.with_temporary_scope do
          expect(result['error']).to eq(spec.expected_error)
        end
      end

      let(:actual_events) { result['events'].freeze }

      it 'emits the correct number of events' do
        RSpec::Mocks.with_temporary_scope do
          expect(actual_events.length).to eq(spec.expected_events.length)
        end
      end

      spec.expected_events.each_with_index do |expected_event, index|
        it "emits correct event #{index+1}" do
          RSpec::Mocks.with_temporary_scope do
            verifier.verify_hashes(actual_events[index], expected_event)
          end
        end
      end
    end
  end
end