From fb052e1fe6420f7ad0b7b722e6f1524d34bbc690 Mon Sep 17 00:00:00 2001 From: Thomas Bloor Date: Wed, 1 Aug 2018 18:28:50 +0100 Subject: [PATCH 1/2] PERL-806 Check compatibility for SDAM tests --- lib/MongoDB/_Topology.pm | 10 +-- t/data/SDAM/README.rst | 10 +-- t/data/SDAM/rs/normalize_case_me.json | 93 ++++++++++++++++++++++++ t/data/SDAM/rs/normalize_case_me.yml | 100 ++++++++++++++++++++++++++ t/sdam_spec.t | 9 +++ 5 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 t/data/SDAM/rs/normalize_case_me.json create mode 100644 t/data/SDAM/rs/normalize_case_me.yml diff --git a/lib/MongoDB/_Topology.pm b/lib/MongoDB/_Topology.pm index 3913a3c0..6c077750 100644 --- a/lib/MongoDB/_Topology.pm +++ b/lib/MongoDB/_Topology.pm @@ -597,8 +597,9 @@ sub _check_wire_versions { my ( $server_min_wire_version, $server_max_wire_version ) = @{ $server->is_master }{qw/minWireVersion maxWireVersion/}; - $server_max_wire_version = 0 unless defined $server_max_wire_version; - $server_min_wire_version = 0 unless defined $server_min_wire_version; + # set to -1 as could be undefined, or 0. + $server_max_wire_version = -1 unless defined $server_max_wire_version; + $server_min_wire_version = -1 unless defined $server_min_wire_version; if ( $server_min_wire_version > $self->max_wire_version || $server_max_wire_version < $self->min_wire_version ) { @@ -1200,8 +1201,9 @@ sub _update_rs_with_primary_from_member { $self->_remove_server($new_server); } - # require 'me' that matches expected address - if ( $new_server->me && $new_server->me ne $new_server->address ) { + # require 'me' that matches expected address. + # check is case insensitive + if ( $new_server->me && lc $new_server->me ne $new_server->address ) { $self->_remove_server($new_server); $self->_check_for_primary; return; diff --git a/t/data/SDAM/README.rst b/t/data/SDAM/README.rst index ddfab3a8..768a1128 100644 --- a/t/data/SDAM/README.rst +++ b/t/data/SDAM/README.rst @@ -9,14 +9,8 @@ Server Discovery And Monitoring Spec. Version ------- -Files in the "specifications" repository have no version scheme. -They are not tied to a MongoDB server version, -and it is our intention that each specification moves from "draft" to "final" -with no further versions; it is superseded by a future spec, not revised. - -However, implementers must have stable sets of tests to target. -As test files evolve they will be occasionally tagged like -"server-discovery-tests-2014-09-10", until the spec is final. +Files in the "specifications" repository have no version scheme. They are not +tied to a MongoDB server version. Format ------ diff --git a/t/data/SDAM/rs/normalize_case_me.json b/t/data/SDAM/rs/normalize_case_me.json new file mode 100644 index 00000000..e854e7fb --- /dev/null +++ b/t/data/SDAM/rs/normalize_case_me.json @@ -0,0 +1,93 @@ +{ + "description": "Replica set mixed case normalization", + "uri": "mongodb://A/?replicaSet=rs", + "phases": [ + { + "responses": [ + [ + "a:27017", + { + "ok": 1, + "ismaster": true, + "setName": "rs", + "me": "A:27017", + "hosts": [ + "A:27017" + ], + "passives": [ + "B:27017" + ], + "arbiters": [ + "C:27017" + ], + "minWireVersion": 0, + "maxWireVersion": 6 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs" + }, + "b:27017": { + "type": "Unknown", + "setName": null + }, + "c:27017": { + "type": "Unknown", + "setName": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs" + } + }, + { + "responses": [ + [ + "b:27017", + { + "ok": 1, + "ismaster": false, + "secondary": true, + "setName": "rs", + "me": "B:27017", + "hosts": [ + "A:27017" + ], + "passives": [ + "B:27017" + ], + "arbiters": [ + "C:27017" + ], + "minWireVersion": 0, + "maxWireVersion": 6 + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs" + }, + "b:27017": { + "type": "RSSecondary", + "setName": "rs" + }, + "c:27017": { + "type": "Unknown", + "setName": null + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs" + } + } + ] +} diff --git a/t/data/SDAM/rs/normalize_case_me.yml b/t/data/SDAM/rs/normalize_case_me.yml new file mode 100644 index 00000000..51700b96 --- /dev/null +++ b/t/data/SDAM/rs/normalize_case_me.yml @@ -0,0 +1,100 @@ +description: "Replica set mixed case normalization" + +uri: "mongodb://A/?replicaSet=rs" + +phases: [ + + { + responses: [ + + ["a:27017", { + + ok: 1, + ismaster: true, + setName: "rs", + me: "A:27017", + hosts: ["A:27017"], + passives: ["B:27017"], + arbiters: ["C:27017"], + minWireVersion: 0, + maxWireVersion: 6 + }] + ], + + outcome: { + + servers: { + + "a:27017": { + + type: "RSPrimary", + setName: "rs" + }, + + "b:27017": { + + type: "Unknown", + setName: + }, + + "c:27017": { + + type: "Unknown", + setName: + } + + }, + + topologyType: "ReplicaSetWithPrimary", + logicalSessionTimeoutMinutes: null, + setName: "rs" + } + }, + { + responses: [ + + ["b:27017", { + + ok: 1, + ismaster: false, + secondary: true, + setName: "rs", + me: "B:27017", + hosts: ["A:27017"], + passives: ["B:27017"], + arbiters: ["C:27017"], + minWireVersion: 0, + maxWireVersion: 6 + }] + ], + + outcome: { + + servers: { + + "a:27017": { + + type: "RSPrimary", + setName: "rs" + }, + + "b:27017": { + + type: "RSSecondary", + setName: "rs" + }, + + "c:27017": { + + type: "Unknown", + setName: + } + + }, + + topologyType: "ReplicaSetWithPrimary", + logicalSessionTimeoutMinutes: null, + setName: "rs" + } + } +] diff --git a/t/sdam_spec.t b/t/sdam_spec.t index 09745537..8cf9037c 100644 --- a/t/sdam_spec.t +++ b/t/sdam_spec.t @@ -28,6 +28,7 @@ my $iterator = path('t/data/SDAM')->iterator({recurse => 1}); while ( my $path = $iterator->() ) { next unless -f $path && $path =~ /\.json$/; + #next unless $path =~ /too_old/; my $plan = eval { decode_json( $path->slurp_utf8 ) }; if ( $@ ) { die "Error decoding $path: $@"; @@ -95,6 +96,10 @@ sub run_test { $topology->_update_topology_from_server_desc( @$response[0], $desc); } + # Need to force this check for compatibility checking + # scan_all_servers wont work as there arent actually any servers... + $topology->_check_wire_versions; + # Process outcome check_outcome($topology, $phase->{'outcome'}); } @@ -127,6 +132,10 @@ sub check_outcome { is($topology->replica_set_name, $expected_set_name, 'correct setName for topology'); is($topology->type, $outcome->{'topologyType'}, 'correct topology type'); is($topology->logical_session_timeout_minutes, $outcome->{'logicalSessionTimeoutMinutes'}, 'correct ls timeout'); + if ( defined $outcome->{'compatible'} ) { + my $compatibility = $outcome->{'compatible'} ? 1 : 0; + is($topology->is_compatible, $compatibility, 'compatibility correct'); + } } done_testing; From 4a2adf01afa4aac4fce9b91bfa8c22c1190db7e0 Mon Sep 17 00:00:00 2001 From: Thomas Bloor Date: Fri, 24 Aug 2018 15:03:56 +0100 Subject: [PATCH 2/2] PERL-806 Revert compatibility check changes to allow for legacy server support --- lib/MongoDB/_Topology.pm | 7 ++++--- t/sdam_spec.t | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/MongoDB/_Topology.pm b/lib/MongoDB/_Topology.pm index 6c077750..27675c85 100644 --- a/lib/MongoDB/_Topology.pm +++ b/lib/MongoDB/_Topology.pm @@ -597,9 +597,10 @@ sub _check_wire_versions { my ( $server_min_wire_version, $server_max_wire_version ) = @{ $server->is_master }{qw/minWireVersion maxWireVersion/}; - # set to -1 as could be undefined, or 0. - $server_max_wire_version = -1 unless defined $server_max_wire_version; - $server_min_wire_version = -1 unless defined $server_min_wire_version; + # set to 0 as could be undefined. 0 is the equivalent to missing, and + # also kept as 0 for legacy compatibility. + $server_max_wire_version = 0 unless defined $server_max_wire_version; + $server_min_wire_version = 0 unless defined $server_min_wire_version; if ( $server_min_wire_version > $self->max_wire_version || $server_max_wire_version < $self->min_wire_version ) { diff --git a/t/sdam_spec.t b/t/sdam_spec.t index 8cf9037c..d754cbea 100644 --- a/t/sdam_spec.t +++ b/t/sdam_spec.t @@ -28,7 +28,6 @@ my $iterator = path('t/data/SDAM')->iterator({recurse => 1}); while ( my $path = $iterator->() ) { next unless -f $path && $path =~ /\.json$/; - #next unless $path =~ /too_old/; my $plan = eval { decode_json( $path->slurp_utf8 ) }; if ( $@ ) { die "Error decoding $path: $@"; @@ -101,7 +100,7 @@ sub run_test { $topology->_check_wire_versions; # Process outcome - check_outcome($topology, $phase->{'outcome'}); + check_outcome($topology, $phase->{'outcome'}, $name); } }; @@ -109,7 +108,7 @@ sub run_test { sub check_outcome { - my ($topology, $outcome, $start_type) = @_; + my ($topology, $outcome, $name) = @_; my %expected_servers = %{$outcome->{'servers'}}; my %actual_servers = %{$topology->servers}; @@ -134,6 +133,9 @@ sub check_outcome { is($topology->logical_session_timeout_minutes, $outcome->{'logicalSessionTimeoutMinutes'}, 'correct ls timeout'); if ( defined $outcome->{'compatible'} ) { my $compatibility = $outcome->{'compatible'} ? 1 : 0; + # perl driver specifically supports older servers - this goes against + # spec but allows for support of legacy servers. + $compatibility = 1 if $name =~ /too_old/; is($topology->is_compatible, $compatibility, 'compatibility correct'); } }