File: command_spec.rb

package info (click to toggle)
ruby-mongo 2.21.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 14,764 kB
  • sloc: ruby: 108,806; makefile: 5; sh: 2
file content (157 lines) | stat: -rw-r--r-- 4,164 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# frozen_string_literal: true
# rubocop:todo all

require 'spec_helper'

describe 'Command' do

  let(:subscriber) { Mrss::EventSubscriber.new }

  describe 'payload' do
    let(:server) { authorized_client.cluster.next_primary }

    let(:payload) do
      server.with_connection do |connection|
        command.send(:final_operation).send(:message, connection).payload.dup.tap do |payload|
          if payload['request_id'].is_a?(Integer)
            payload['request_id'] = 42
          end
          # $clusterTime may be present depending on the client's state
          payload['command'].delete('$clusterTime')
          # 3.6+ servers also return a payload field, earlier ones do not.
          # The contents of this field duplicates the rest of the response
          # so we can get rid of it without losing information.
          payload.delete('reply')
        end
      end
    end

    let(:session) { nil }

    context 'commitTransaction' do
      # Although these are unit tests, when targeting pre-4.0 servers
      # the driver does not add arguments like write concerns to commands that
      # it adds for 4.0+ servers, breaking expectations
      min_server_fcv '4.0'

      let(:selector) do
        { commitTransaction: 1 }.freeze
      end

      let(:write_concern) { nil }

      let(:command) do
        Mongo::Operation::Command.new(
          selector: selector,
          db_name: 'admin',
          session: session,
          txn_num: 123,
          write_concern: write_concern,
        )
      end

      let(:expected_payload) do
        {
          'command' => {
            'commitTransaction' => 1,
            '$db' => 'admin',
          },
          'command_name' => 'commitTransaction',
          'database_name' => 'admin',
          'request_id' => 42,
        }
      end

      it 'returns expected payload' do
        expect(payload).to eq(expected_payload)
      end

      context 'with session' do
        min_server_fcv '3.6'

        let(:session) do
          authorized_client.start_session.tap do |session|
            # We are bypassing the normal transaction lifecycle, which would
            # set txn_options
            allow(session).to receive(:txn_options).and_return({})
          end
        end

        let(:expected_payload) do
          {
            'command' => {
              'commitTransaction' => 1,
              'lsid' => session.session_id,
              'txnNumber' => BSON::Int64.new(123),
              '$db' => 'admin',
            },
            'command_name' => 'commitTransaction',
            'database_name' => 'admin',
            'request_id' => 42,
          }
        end

        it 'returns selector with write concern' do
          expect(payload).to eq(expected_payload)
        end
      end

      context 'with write concern' do
        let(:write_concern) { Mongo::WriteConcern.get(w: :majority) }

        let(:expected_payload) do
          {
            'command' => {
              '$db' => 'admin',
              'commitTransaction' => 1,
              'writeConcern' => {'w' => 'majority'},
            },
            'command_name' => 'commitTransaction',
            'database_name' => 'admin',
            'request_id' => 42,
          }
        end

        it 'returns selector with write concern' do
          expect(payload).to eq(expected_payload)
        end
      end
    end

    context 'find' do
      let(:selector) do
        { find: 'collection_name' }.freeze
      end

      let(:command) do
        Mongo::Operation::Command.new(
          selector: selector,
          db_name: 'foo',
          session: session,
        )
      end

      context 'OP_MSG-capable servers' do
        min_server_fcv '3.6'

        let(:expected_payload) do
          {
            'command' => {
              '$db' => 'foo',
              'find' => 'collection_name',
            },
            'command_name' => 'find',
            'database_name' => 'foo',
            'request_id' => 42,
          }
        end

        it 'returns expected payload' do
          expect(payload).to eq(expected_payload)
        end
      end
    end

  end

end