build_client
get_capped
get_test_db
server_version
server_type
skip_unless_mongod
/
;
skip_unless_mongod();
my
$cb
= MongoDBTest::Callback->new;
my
$conn
= build_client(
monitoring_callback
=>
$cb
->callback
);
my
$testdb
= get_test_db(
$conn
);
my
$server_version
= server_version(
$conn
);
my
$server_type
= server_type(
$conn
);
my
$coll
=
$testdb
->get_collection(
'test_validating'
);
my
$res
;
my
$does_validation
=
$server_version
>= v3.1.3;
sub
_drop_coll {
$coll
->drop;
$testdb
->run_command( [
create
=>
$coll
->name ] );
if
(
$does_validation
) {
$testdb
->run_command(
[
collMod
=>
$coll
->name,
validator
=> {
x
=> {
'$exists'
=> 1 } } ] );
}
pass(
"reset collection"
);
}
subtest
"insert_one"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->insert_one( {}, {
bypassDocumentValidation
=> 0 } )};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->insert_one( {}, {
bypassDocumentValidation
=> 1 } )};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"replace_one"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
my
$id
=
$coll
->insert_one( {
x
=> 1 } )->inserted_id;
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->replace_one( {
_id
=>
$id
}, {
y
=> 1 }, {
bypassDocumentValidation
=> 0 })
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->replace_one( {
_id
=>
$id
}, {
y
=> 1 }, {
bypassDocumentValidation
=> 1 })
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"update_one"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
$coll
->insert_one( {
x
=> 1 } );
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->update_one(
{
x
=> 1 },
{
'$unset'
=> {
x
=> 1 } },
{
bypassDocumentValidation
=> 0 }
)
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->update_one(
{
x
=> 1 },
{
'$unset'
=> {
x
=> 1 } },
{
bypassDocumentValidation
=> 1 }
)
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"update_many"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
$coll
->insert_many( [ {
x
=> 1 }, {
x
=> 2 } ] );
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->update_many(
{},
{
'$unset'
=> {
x
=> 1 } },
{
bypassDocumentValidation
=> 0 }
)
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->update_many(
{},
{
'$unset'
=> {
x
=> 1 } },
{
bypassDocumentValidation
=> 1 }
)
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
'bulk_write (unordered)'
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
my
$err
;
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->bulk_write(
[ [
insert_one
=> [ {
x
=> 1 } ] ], [
insert_many
=> [ {}, {
x
=> 8 } ] ], ],
{
bypassDocumentValidation
=> 0,
ordered
=> 0 },
);
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->bulk_write(
[ [
insert_one
=> [ {
x
=> 1 } ] ], [
insert_many
=> [ {}, {
x
=> 8 } ] ], ],
{
bypassDocumentValidation
=> 1,
ordered
=> 0 },
);
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
'bulk_write (ordered)'
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
my
$err
;
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->bulk_write(
[ [
insert_one
=> [ {
x
=> 1 } ] ], [
insert_many
=> [ {}, {
x
=> 8 } ] ], ],
{
bypassDocumentValidation
=> 0,
ordered
=> 1 },
);
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->bulk_write(
[ [
insert_one
=> [ {
x
=> 1 } ] ], [
insert_many
=> [ {}, {
x
=> 8 } ] ], ],
{
bypassDocumentValidation
=> 1,
ordered
=> 1 },
);
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"insert_many"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->insert_many( [ {}, {} ], {
bypassDocumentValidation
=> 0 } )
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->insert_many( [ {}, {} ], {
bypassDocumentValidation
=> 1 } )
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"find_one_and_replace"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
$coll
->insert_one( {
x
=> 1 } );
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->find_one_and_replace( {
x
=> 1 }, {
y
=> 1 }, {
bypassDocumentValidation
=> 0 } )
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->find_one_and_replace( {
x
=> 1 }, {
y
=> 1 }, {
bypassDocumentValidation
=> 1 } )
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"find_one_and_update"
=>
sub
{
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
$coll
->insert_one( {
x
=> 1 } );
$cb
->clear_events;
my
$not_bypass
= exception {
$coll
->find_one_and_update(
{
x
=> 1 },
{
'$unset'
=> {
x
=> 1 } },
{
bypassDocumentValidation
=> 0 }
)
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$coll
->find_one_and_update(
{
x
=> 1 },
{
'$unset'
=> {
x
=> 1 } },
{
bypassDocumentValidation
=> 1 }
)
};
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
};
subtest
"aggregate with \$out"
=>
sub
{
plan
skip_all
=>
"Aggregation with \$out requires MongoDB 2.6+"
unless
$server_version
>= v2.6.0;
plan
skip_all
=>
"requires MongoDB 3.2+"
unless
$does_validation
;
_drop_coll();
my
$source
=
$testdb
->get_collection(
'test_source'
);
$source
->insert_many( [
map
{ {
count
=>
$_
} } 1 .. 20 ] );
$cb
->clear_events;
my
$not_bypass
= exception {
$source
->aggregate(
[ {
'$match'
=> {
count
=> {
'$gt'
=> 10 } } }, {
'$out'
=>
$coll
->name } ],
{
bypassDocumentValidation
=> 0 } )
};
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation not inserted when false'
);
like(
$not_bypass
,
qr/failed validation/
,
"invalid when false on bypass"
);
$cb
->clear_events;
my
$valid_bypass
= exception {
$source
->aggregate(
[ {
'$match'
=> {
count
=> {
'$gt'
=> 10 } } }, {
'$out'
=>
$coll
->name } ],
{
bypassDocumentValidation
=> 1 } ) };
my
$event
=
$cb
->events->[-2];
ok(
exists
$event
->{ command }->{
'bypassDocumentValidation'
},
'bypassDocumentValidation inserted when true'
);
is(
$valid_bypass
,
undef
,
"validation bypassed"
);
is(
$coll
->count_documents({}), 10,
"correct doc count in \$out collection"
);
is(
exception {
$source
->aggregate(
[ {
'$match'
=> {
count
=> {
'$gt'
=> 10 } } } ],
{
bypassDocumentValidation
=> 1 } );
},
undef
,
"bypassDocumentValidation without \$out"
,
);
};
subtest
bypass_validation_default
=>
sub
{
my
$source
=
$testdb
->get_collection(
'test_source'
);
$coll
->drop;
my
%cases
= (
insert_one
=>
sub
{
$coll
->insert_one( {} ) },
replace_one
=>
sub
{
$coll
->replace_one( {
_id
=> 123 }, {
y
=> 1 } ) },
update_one
=>
sub
{
$coll
->update_one( {
x
=> 1 }, {
'$unset'
=> {
x
=> 1 } } ) },
update_many
=>
sub
{
$coll
->update_many( {}, {
'$unset'
=> {
x
=> 1 } } ) },
bulk_write
=>
sub
{
$coll
->bulk_write(
[ [
insert_one
=> [ {
x
=> 1 } ] ], [
insert_many
=> [ {}, {
x
=> 8 } ] ] ] );
},
insert_many
=>
sub
{
$coll
->insert_many( [ {}, {} ], ) },
fine_one_and_replace
=>
sub
{
$coll
->find_one_and_replace( {
x
=> 1 }, {
y
=> 1 } ) },
find_one_and_update
=>
sub
{
$coll
->find_one_and_update( {
x
=> 1 }, {
'$unset'
=> {
x
=> 1 } } ) },
aggregate_with_out
=>
sub
{
$source
->aggregate(
[ {
'$match'
=> {
count
=> {
'$gt'
=> 10 } } }, {
'$out'
=>
$coll
->name } ] );
},
);
for
my
$k
(
sort
keys
%cases
) {
$cb
->clear_events;
$cases
{
$k
}->();
my
$err_event
=
$cb
->events->[-2];
ok( !
exists
$err_event
->{ command }->{
'bypassDocumentValidation'
},
"$k: bypassDocumentValidation not inserted when default undef"
);
}
};
done_testing;