From 7645618fd3914cb8a20561625913c20d49504a49 Mon Sep 17 00:00:00 2001 From: Antonin Kral Date: Wed, 11 Aug 2010 12:38:57 +0200 Subject: Imported Upstream version 1.6.0 --- jstests/_fail.js | 4 + jstests/_runner.js | 8 +- jstests/apitest_db.js | 14 +- jstests/apply_ops1.js | 51 ++++++ jstests/arrayfind2.js | 8 +- jstests/capped3.js | 7 +- jstests/capped6.js | 82 ++++++++++ jstests/capped7.js | 72 +++++++++ jstests/clone/clonecollection.js | 150 +----------------- jstests/conc_update.js | 45 ++++++ jstests/copydb-auth.js | 17 ++ jstests/copydb2.js | 17 -- jstests/cursor8.js | 12 +- jstests/cursora.js | 34 ++++ jstests/datasize.js | 8 +- jstests/datasize2.js | 27 ++++ jstests/dbadmin.js | 5 +- jstests/dbcase.js | 23 +++ jstests/dbhash.js | 9 ++ jstests/disk/directoryperdb.js | 8 +- jstests/disk/repair.js | 37 ++++- jstests/disk/repair2.js | 47 ++++++ jstests/disk/repair3.js | 52 +++++++ jstests/disk/repair4.js | 44 ++++++ jstests/distinct_array1.js | 24 +++ jstests/distinct_speed1.js | 26 ++++ jstests/drop.js | 2 +- jstests/evalb.js | 3 + jstests/explain2.js | 2 +- jstests/find_and_modify.js | 4 +- jstests/find_and_modify2.js | 10 ++ jstests/find_and_modify3.js | 21 +++ jstests/find_and_modify4.js | 55 +++++++ jstests/fm4.js | 16 ++ jstests/geo2.js | 1 + jstests/geo3.js | 2 +- jstests/geo_box3.js | 36 +++++ jstests/geo_circle2.js | 23 +++ jstests/geo_circle3.js | 28 ++++ jstests/geo_circle4.js | 24 +++ jstests/geo_circle5.js | 28 ++++ jstests/geo_haystack1.js | 59 +++++++ jstests/geo_haystack2.js | 60 +++++++ jstests/geod.js | 14 ++ jstests/geoe.js | 32 ++++ jstests/group6.js | 31 ++++ jstests/hint1.js | 4 +- jstests/in3.js | 4 +- jstests/in4.js | 53 +++++++ jstests/in5.js | 56 +++++++ jstests/in6.js | 13 ++ jstests/in7.js | 6 + jstests/index1.js | 6 +- jstests/index10.js | 4 +- jstests/index6.js | 2 +- jstests/index7.js | 18 ++- jstests/index_check2.js | 2 +- jstests/index_check6.js | 52 ++++++- jstests/index_check8.js | 15 ++ jstests/index_elemmatch1.js | 28 ++++ jstests/index_many.js | 75 +++++---- jstests/index_many2.js | 29 ++++ jstests/indexapi.js | 2 +- jstests/indexe.js | 2 +- jstests/indexh.js | 34 ++++ jstests/maxscan.js | 14 ++ jstests/not2.js | 15 +- jstests/numberlong.js | 55 +++++++ jstests/objid5.js | 12 ++ jstests/objid6.js | 14 ++ jstests/objid7.js | 13 ++ jstests/or1.js | 57 +++++++ jstests/or2.js | 68 ++++++++ jstests/or3.js | 64 ++++++++ jstests/or4.js | 98 ++++++++++++ jstests/or5.js | 107 +++++++++++++ jstests/or6.js | 31 ++++ jstests/or7.js | 41 +++++ jstests/or8.js | 16 ++ jstests/or9.js | 54 +++++++ jstests/ora.js | 17 ++ jstests/orb.js | 17 ++ jstests/pullall2.js | 20 +++ jstests/ref3.js | 22 +-- jstests/regex5.js | 22 +-- jstests/repair.js | 2 +- jstests/repl/basic1.js | 53 ++++--- jstests/repl/block1.js | 24 +++ jstests/repl/block2.js | 45 ++++++ jstests/repl/mastermaster1.js | 34 ++++ jstests/repl/repair.js | 14 ++ jstests/repl/replacePeer2.js | 14 +- jstests/repl/snapshot2.js | 13 +- jstests/repl/snapshot3.js | 17 +- jstests/replsets/replset1.js | 115 ++++++++++++++ jstests/replsets/replset2.js | 111 +++++++++++++ jstests/replsets/replset3.js | 56 +++++++ jstests/replsets/replset4.js | 29 ++++ jstests/replsets/replset_remove_node.js | 57 +++++++ jstests/replsets/replsetadd.js | 31 ++++ jstests/replsets/replsetarb1.js | 33 ++++ jstests/replsets/replsetarb2.js | 45 ++++++ jstests/replsets/replsetprio1.js | 53 +++++++ jstests/replsets/replsetrestart1.js | 57 +++++++ jstests/replsets/replsetrestart2.js | 46 ++++++ jstests/replsets/rollback.js | 129 +++++++++++++++ jstests/replsets/rollback2.js | 199 ++++++++++++++++++++++++ jstests/replsets/sync1.js | 192 +++++++++++++++++++++++ jstests/replsets/twosets.js | 36 +++++ jstests/rs/rs_basic.js | 177 +++++++++++++++++++++ jstests/rs/test_framework.js | 30 ++++ jstests/sharding/addshard1.js | 56 +++++++ jstests/sharding/auto1.js | 34 ++-- jstests/sharding/auto2.js | 105 ++++++++++++- jstests/sharding/bigMapReduce.js | 17 ++ jstests/sharding/count1.js | 64 ++++++-- jstests/sharding/count2.js | 43 +++++ jstests/sharding/cursor1.js | 60 +++++++ jstests/sharding/diffservers1.js | 2 +- jstests/sharding/error1.js | 24 ++- jstests/sharding/features1.js | 27 +++- jstests/sharding/features2.js | 53 ++++++- jstests/sharding/features3.js | 86 ++++++++++ jstests/sharding/findandmodify1.js | 42 +++-- jstests/sharding/key_many.js | 41 ++++- jstests/sharding/movePrimary1.js | 19 ++- jstests/sharding/moveshard1.js | 39 ----- jstests/sharding/presplit.js | 37 +++++ jstests/sharding/remove1.js | 16 ++ jstests/sharding/rename.js | 26 ++++ jstests/sharding/shard1.js | 14 +- jstests/sharding/shard2.js | 45 +++++- jstests/sharding/shard3.js | 48 +++++- jstests/sharding/shard6.js | 75 ++++++++- jstests/sharding/sort1.js | 81 ++++++++++ jstests/sharding/splitpick.js | 14 +- jstests/sharding/stats.js | 60 +++++++ jstests/sharding/sync1.js | 5 + jstests/sharding/sync2.js | 70 +++++++-- jstests/sharding/sync3.js | 10 ++ jstests/sharding/sync4.js | 19 +++ jstests/sharding/update1.js | 19 ++- jstests/shellkillop.js | 2 +- jstests/shellspawn.js | 6 +- jstests/slice1.js | 68 ++++++++ jstests/slow/indexbg1.js | 117 -------------- jstests/slow/indexbg2.js | 83 ---------- jstests/slow/ns1.js | 49 ------ jstests/slowNightly/remove9.js | 12 ++ jstests/slowNightly/run_sharding_passthrough.js | 94 +++++++++++ jstests/slowNightly/sharding_balance1.js | 55 +++++++ jstests/slowNightly/sharding_balance2.js | 54 +++++++ jstests/slowNightly/sharding_balance3.js | 57 +++++++ jstests/slowNightly/sharding_balance4.js | 122 +++++++++++++++ jstests/slowNightly/sharding_cursors1.js | 71 +++++++++ jstests/slowNightly/sharding_rs1.js | 61 ++++++++ jstests/slowWeekly/conc_update.js | 51 ++++++ jstests/slowWeekly/indexbg1.js | 117 ++++++++++++++ jstests/slowWeekly/indexbg2.js | 83 ++++++++++ jstests/slowWeekly/ns1.js | 49 ++++++ jstests/slowWeekly/query_yield1.js | 73 +++++++++ jstests/slowWeekly/query_yield2.js | 73 +++++++++ jstests/slowWeekly/update_yield1.js | 78 ++++++++++ jstests/splitvector.js | 81 ++++++++++ jstests/tempCleanup.js | 16 ++ jstests/tool/csv1.js | 8 +- jstests/tool/exportimport1.js | 13 ++ jstests/tool/files1.js | 27 ++++ jstests/update_addToSet2.js | 11 ++ jstests/update_arraymatch4.js | 18 +++ jstests/update_arraymatch5.js | 15 ++ jstests/update_multi4.js | 18 +++ jstests/update_multi5.js | 17 ++ jstests/upsert1.js | 14 ++ jstests/where3.js | 10 ++ 175 files changed, 6212 insertions(+), 718 deletions(-) create mode 100644 jstests/_fail.js create mode 100644 jstests/apply_ops1.js create mode 100644 jstests/capped6.js create mode 100644 jstests/capped7.js create mode 100644 jstests/conc_update.js create mode 100644 jstests/copydb-auth.js delete mode 100644 jstests/copydb2.js create mode 100644 jstests/cursora.js create mode 100644 jstests/datasize2.js create mode 100644 jstests/dbcase.js create mode 100644 jstests/disk/repair2.js create mode 100644 jstests/disk/repair3.js create mode 100644 jstests/disk/repair4.js create mode 100644 jstests/distinct_array1.js create mode 100644 jstests/distinct_speed1.js create mode 100644 jstests/find_and_modify2.js create mode 100644 jstests/find_and_modify3.js create mode 100644 jstests/find_and_modify4.js create mode 100644 jstests/fm4.js create mode 100644 jstests/geo_box3.js create mode 100644 jstests/geo_circle2.js create mode 100644 jstests/geo_circle3.js create mode 100644 jstests/geo_circle4.js create mode 100644 jstests/geo_circle5.js create mode 100644 jstests/geo_haystack1.js create mode 100644 jstests/geo_haystack2.js create mode 100644 jstests/geod.js create mode 100644 jstests/geoe.js create mode 100644 jstests/group6.js create mode 100644 jstests/in4.js create mode 100644 jstests/in5.js create mode 100644 jstests/in6.js create mode 100644 jstests/in7.js create mode 100644 jstests/index_check8.js create mode 100644 jstests/index_elemmatch1.js create mode 100644 jstests/index_many2.js create mode 100644 jstests/indexh.js create mode 100644 jstests/maxscan.js create mode 100644 jstests/numberlong.js create mode 100644 jstests/objid6.js create mode 100644 jstests/objid7.js create mode 100644 jstests/or1.js create mode 100644 jstests/or2.js create mode 100644 jstests/or3.js create mode 100644 jstests/or4.js create mode 100644 jstests/or5.js create mode 100644 jstests/or6.js create mode 100644 jstests/or7.js create mode 100644 jstests/or8.js create mode 100644 jstests/or9.js create mode 100644 jstests/ora.js create mode 100644 jstests/orb.js create mode 100644 jstests/pullall2.js create mode 100644 jstests/repl/block1.js create mode 100644 jstests/repl/block2.js create mode 100644 jstests/repl/mastermaster1.js create mode 100644 jstests/repl/repair.js create mode 100644 jstests/replsets/replset1.js create mode 100644 jstests/replsets/replset2.js create mode 100644 jstests/replsets/replset3.js create mode 100644 jstests/replsets/replset4.js create mode 100644 jstests/replsets/replset_remove_node.js create mode 100644 jstests/replsets/replsetadd.js create mode 100644 jstests/replsets/replsetarb1.js create mode 100644 jstests/replsets/replsetarb2.js create mode 100644 jstests/replsets/replsetprio1.js create mode 100644 jstests/replsets/replsetrestart1.js create mode 100644 jstests/replsets/replsetrestart2.js create mode 100644 jstests/replsets/rollback.js create mode 100644 jstests/replsets/rollback2.js create mode 100644 jstests/replsets/sync1.js create mode 100644 jstests/replsets/twosets.js create mode 100644 jstests/rs/rs_basic.js create mode 100644 jstests/rs/test_framework.js create mode 100644 jstests/sharding/addshard1.js create mode 100644 jstests/sharding/bigMapReduce.js create mode 100644 jstests/sharding/count2.js create mode 100644 jstests/sharding/cursor1.js create mode 100644 jstests/sharding/features3.js delete mode 100644 jstests/sharding/moveshard1.js create mode 100644 jstests/sharding/presplit.js create mode 100644 jstests/sharding/remove1.js create mode 100644 jstests/sharding/rename.js create mode 100644 jstests/sharding/sort1.js create mode 100644 jstests/sharding/stats.js create mode 100644 jstests/sharding/sync3.js create mode 100644 jstests/sharding/sync4.js create mode 100644 jstests/slice1.js delete mode 100644 jstests/slow/indexbg1.js delete mode 100644 jstests/slow/indexbg2.js delete mode 100644 jstests/slow/ns1.js create mode 100644 jstests/slowNightly/remove9.js create mode 100644 jstests/slowNightly/run_sharding_passthrough.js create mode 100644 jstests/slowNightly/sharding_balance1.js create mode 100644 jstests/slowNightly/sharding_balance2.js create mode 100644 jstests/slowNightly/sharding_balance3.js create mode 100644 jstests/slowNightly/sharding_balance4.js create mode 100644 jstests/slowNightly/sharding_cursors1.js create mode 100644 jstests/slowNightly/sharding_rs1.js create mode 100644 jstests/slowWeekly/conc_update.js create mode 100644 jstests/slowWeekly/indexbg1.js create mode 100644 jstests/slowWeekly/indexbg2.js create mode 100644 jstests/slowWeekly/ns1.js create mode 100644 jstests/slowWeekly/query_yield1.js create mode 100644 jstests/slowWeekly/query_yield2.js create mode 100644 jstests/slowWeekly/update_yield1.js create mode 100644 jstests/splitvector.js create mode 100644 jstests/tempCleanup.js create mode 100644 jstests/tool/files1.js create mode 100644 jstests/update_addToSet2.js create mode 100644 jstests/update_arraymatch4.js create mode 100644 jstests/update_arraymatch5.js create mode 100644 jstests/update_multi4.js create mode 100644 jstests/update_multi5.js create mode 100644 jstests/upsert1.js create mode 100644 jstests/where3.js (limited to 'jstests') diff --git a/jstests/_fail.js b/jstests/_fail.js new file mode 100644 index 0000000..9d41d25 --- /dev/null +++ b/jstests/_fail.js @@ -0,0 +1,4 @@ +// For testing the test runner. +assert.eq(1, 2, "fail1") + +print("you should not see this") \ No newline at end of file diff --git a/jstests/_runner.js b/jstests/_runner.js index f0ce49d..48619c1 100644 --- a/jstests/_runner.js +++ b/jstests/_runner.js @@ -3,11 +3,12 @@ // var files = listFiles("jstests"); +var runnerStart = new Date() + files.forEach( function(x) { - if ( /_runner/.test(x.name) || - /_lodeRunner/.test(x.name) || + if ( /[\/\\]_/.test(x.name) || ! /\.js$/.test(x.name ) ){ print(" >>>>>>>>>>>>>>> skipping " + x.name); return; @@ -22,3 +23,6 @@ files.forEach( ); +var runnerEnd = new Date() + +print( "total runner time: " + ( ( runnerEnd.getTime() - runnerStart.getTime() ) / 1000 ) + "secs" ) diff --git a/jstests/apitest_db.js b/jstests/apitest_db.js index 45e25b6..f54879c 100644 --- a/jstests/apitest_db.js +++ b/jstests/apitest_db.js @@ -2,6 +2,8 @@ * Tests for the db object enhancement */ +assert( "test" == db, "wrong database currently not test" ); + dd = function( x ){ //print( x ); } @@ -34,7 +36,7 @@ dd( "d" ); db.createCollection("test"); var found = false; db.getCollection( "system.namespaces" ).find().forEach( function(x) { if (x.name == "test.test") found = true; }); -assert(found); +assert(found, "found test.test in system.namespaces"); dd( "e" ); @@ -43,16 +45,16 @@ dd( "e" ); */ db.setProfilingLevel(0); -assert(db.getProfilingLevel() == 0); +assert(db.getProfilingLevel() == 0, "prof level 0"); db.setProfilingLevel(1); -assert(db.getProfilingLevel() == 1); +assert(db.getProfilingLevel() == 1, "p1"); db.setProfilingLevel(2); -assert(db.getProfilingLevel() == 2); +assert(db.getProfilingLevel() == 2, "p2"); db.setProfilingLevel(0); -assert(db.getProfilingLevel() == 0); +assert(db.getProfilingLevel() == 0, "prof level 0"); dd( "f" ); asserted = false; @@ -64,7 +66,7 @@ catch (e) { asserted = true; assert(e.dbSetProfilingException); } -assert( asserted ); +assert( asserted, "should have asserted" ); dd( "g" ); diff --git a/jstests/apply_ops1.js b/jstests/apply_ops1.js new file mode 100644 index 0000000..adfcc27 --- /dev/null +++ b/jstests/apply_ops1.js @@ -0,0 +1,51 @@ + +t = db.apply_ops1; +t.drop(); + +assert.eq( 0 , t.find().count() , "A0" ); +db.runCommand( { applyOps : [ { "op" : "i" , "ns" : t.getFullName() , "o" : { _id : 5 , x : 17 } } ] } ) +assert.eq( 1 , t.find().count() , "A1" ); + +o = { _id : 5 , x : 17 } +assert.eq( o , t.findOne() , "A2" ); + +res = db.runCommand( { applyOps : [ + { "op" : "u" , "ns" : t.getFullName() , "o2" : { _id : 5 } , "o" : { $inc : { x : 1 } } } , + { "op" : "u" , "ns" : t.getFullName() , "o2" : { _id : 5 } , "o" : { $inc : { x : 1 } } } +] } ) + +o.x++; +o.x++; + +assert.eq( 1 , t.find().count() , "A3" ); +assert.eq( o , t.findOne() , "A4" ); + + +res = db.runCommand( { applyOps : + [ + { "op" : "u" , "ns" : t.getFullName() , "o2" : { _id : 5 } , "o" : { $inc : { x : 1 } } } , + { "op" : "u" , "ns" : t.getFullName() , "o2" : { _id : 5 } , "o" : { $inc : { x : 1 } } } + ] + , + preCondition : [ { ns : t.getFullName() , q : { _id : 5 } , res : { x : 19 } } ] + } ); + +o.x++; +o.x++; + +assert.eq( 1 , t.find().count() , "B1" ); +assert.eq( o , t.findOne() , "B2" ); + + +res = db.runCommand( { applyOps : + [ + { "op" : "u" , "ns" : t.getFullName() , "o2" : { _id : 5 } , "o" : { $inc : { x : 1 } } } , + { "op" : "u" , "ns" : t.getFullName() , "o2" : { _id : 5 } , "o" : { $inc : { x : 1 } } } + ] + , + preCondition : [ { ns : t.getFullName() , q : { _id : 5 } , res : { x : 19 } } ] + } ); + +assert.eq( 1 , t.find().count() , "B3" ); +assert.eq( o , t.findOne() , "B4" ); + diff --git a/jstests/arrayfind2.js b/jstests/arrayfind2.js index 59bf2b0..94d77f1 100644 --- a/jstests/arrayfind2.js +++ b/jstests/arrayfind2.js @@ -22,14 +22,14 @@ go( "no index" ); t.ensureIndex( { a : 1 } ); go( "index(a)" ); -assert.eq( [], t.find( { a : { $all : [ { $elemMatch : { x : 3 } } ] } } ).explain().indexBounds ); +assert.eq( {}, t.find( { a : { $all : [ { $elemMatch : { x : 3 } } ] } } ).explain().indexBounds ); t.ensureIndex( { "a.x": 1 } ); -assert.eq( [ [ {"a.x":3},{"a.x":3} ] ], t.find( { a : { $all : [ { $elemMatch : { x : 3 } } ] } } ).explain().indexBounds ); +assert.eq( {"a.x":[[3,3]]}, t.find( { a : { $all : [ { $elemMatch : { x : 3 } } ] } } ).explain().indexBounds ); // only first $elemMatch used to find bounds -assert.eq( [ [ {"a.x":3},{"a.x":3} ] ], t.find( { a : { $all : [ { $elemMatch : { x : 3 } }, { $elemMatch : { y : 5 } } ] } } ).explain().indexBounds ); +assert.eq( {"a.x":[[3,3]]}, t.find( { a : { $all : [ { $elemMatch : { x : 3 } }, { $elemMatch : { y : 5 } } ] } } ).explain().indexBounds ); t.ensureIndex( { "a.x":1,"a.y":-1 } ); -assert.eq( [ [ {"a.x":3,"a.y":1.7976931348623157e+308},{"a.x":3,"a.y":4} ] ], t.find( { a : { $all : [ { $elemMatch : { x : 3, y : { $gt: 4 } } } ] } } ).explain().indexBounds ); +assert.eq( {"a.x":[[3,3]],"a.y":[[1.7976931348623157e+308,4]]}, t.find( { a : { $all : [ { $elemMatch : { x : 3, y : { $gt: 4 } } } ] } } ).explain().indexBounds ); diff --git a/jstests/capped3.js b/jstests/capped3.js index c4f1a3c..d6d2b23 100644 --- a/jstests/capped3.js +++ b/jstests/capped3.js @@ -23,9 +23,10 @@ c = t2.find().sort( {$natural:-1} ); i = 999; while( c.hasNext() ) { assert.eq( i--, c.next().i, "E" ); -} -print( "i: " + i ); -print( "stats: " + tojson( t2.stats() ) ); +} +//print( "i: " + i ); +var str = tojson( t2.stats() ); +//print( "stats: " + tojson( t2.stats() ) ); assert( i < 990, "F" ); t.drop(); diff --git a/jstests/capped6.js b/jstests/capped6.js new file mode 100644 index 0000000..851bbd1 --- /dev/null +++ b/jstests/capped6.js @@ -0,0 +1,82 @@ +Random.setRandomSeed(); + +db.capped6.drop(); +db._dbCommand( { create: "capped6", capped: true, size: 1000, $nExtents: 11, autoIndexId: false } ); +tzz = db.capped6; + +function debug( x ) { +// print( x ); +} + +function checkOrder( i ) { + res = tzz.find().sort( { $natural: -1 } ); + assert( res.hasNext(), "A" ); + var j = i; + while( res.hasNext() ) { + try { + assert.eq( val[ j-- ].a, res.next().a, "B" ); + } catch( e ) { + debug( "capped6 err " + j ); + throw e; + } + } + res = tzz.find().sort( { $natural: 1 } ); + assert( res.hasNext(), "C" ); + while( res.hasNext() ) + assert.eq( val[ ++j ].a, res.next().a, "D" ); + assert.eq( j, i, "E" ); +} + +var val = new Array( 500 ); +var c = ""; +for( i = 0; i < 500; ++i, c += "-" ) { + val[ i ] = { a: c }; +} + +var oldMax = Random.randInt( 500 ); +var max = 0; + +function doTest() { + for( var i = max; i < oldMax; ++i ) { + tzz.save( val[ i ] ); + } + max = oldMax; + count = tzz.count(); + + var min = 1; + if ( Random.rand() > 0.3 ) { + min = Random.randInt( count ) + 1; + } + + while( count > min ) { + var n = Random.randInt( count - min - 1 ); // 0 <= x <= count - min - 1 + var inc = Random.rand() > 0.5; + debug( count + " " + n + " " + inc ); + assert.commandWorked( db.runCommand( { captrunc:"capped6", n:n, inc:inc } ) ); + if ( inc ) { + n += 1; + } + count -= n; + max -= n; + checkOrder( max - 1 ); + } +} + +for( var i = 0; i < 10; ++i ) { + doTest(); +} + +// reverse order of values +var val = new Array( 500 ); + +var c = ""; +for( i = 499; i >= 0; --i, c += "-" ) { + val[ i ] = { a: c }; +} +db.capped6.drop(); +db._dbCommand( { create: "capped6", capped: true, size: 1000, $nExtents: 11, autoIndexId: false } ); +tzz = db.capped6; + +for( var i = 0; i < 10; ++i ) { + doTest(); +} diff --git a/jstests/capped7.js b/jstests/capped7.js new file mode 100644 index 0000000..ecb689e --- /dev/null +++ b/jstests/capped7.js @@ -0,0 +1,72 @@ +Random.setRandomSeed(); + +db.capped7.drop(); +db._dbCommand( { create: "capped7", capped: true, size: 1000, $nExtents: 11, autoIndexId: false } ); +tzz = db.capped7; + +var ten = new Array( 11 ).toString().replace( /,/g, "-" ); + +count = 0; + +function insertUntilFull() { +count = tzz.count(); + var j = 0; +while( 1 ) { + tzz.save( {i:ten,j:j++} ); + var newCount = tzz.count(); + if ( count == newCount ) { + break; + } + count = newCount; +} +} + +insertUntilFull(); + +oldCount = count; + +assert.eq.automsg( "11", "tzz.stats().numExtents" ); +var oldSize = tzz.stats().storageSize; + +assert.commandWorked( db._dbCommand( { emptycapped: "capped7" } ) ); + +assert.eq.automsg( "11", "tzz.stats().numExtents" ); +assert.eq.automsg( "oldSize", "tzz.stats().storageSize" ); + +assert.eq.automsg( "0", "tzz.find().itcount()" ); +assert.eq.automsg( "0", "tzz.count()" ); + +insertUntilFull(); + +assert.eq.automsg( "oldCount", "count" ); +assert.eq.automsg( "oldCount", "tzz.find().itcount()" ); +assert.eq.automsg( "oldCount", "tzz.count()" ); + +assert.eq.automsg( "11", "tzz.stats().numExtents" ); +var oldSize = tzz.stats().storageSize; + +assert.commandWorked( db._dbCommand( { emptycapped: "capped7" } ) ); + +assert.eq.automsg( "11", "tzz.stats().numExtents" ); +assert.eq.automsg( "oldSize", "tzz.stats().storageSize" ); + +var total = Random.randInt( 2000 ); +for( var j = 1; j <= total; ++j ) { + tzz.save( {i:ten,j:j} ); + if ( Random.rand() > 0.95 ) { + assert.automsg( "j >= tzz.count()" ); + assert.eq.automsg( "tzz.count()", "tzz.find().itcount()" ); + var c = tzz.find().sort( {$natural:-1} ); + var k = j; + assert.automsg( "c.hasNext()" ); + while( c.hasNext() ) { + assert.eq.automsg( "c.next().j", "k--" ); + } + var c = tzz.find().sort( {$natural:1} ); + assert.automsg( "c.hasNext()" ); + while( c.hasNext() ) { + assert.eq.automsg( "c.next().j", "++k" ); + } + assert.eq.automsg( "j", "k" ); + } +} \ No newline at end of file diff --git a/jstests/clone/clonecollection.js b/jstests/clone/clonecollection.js index b1f9c29..ea5f229 100644 --- a/jstests/clone/clonecollection.js +++ b/jstests/clone/clonecollection.js @@ -2,65 +2,6 @@ var baseName = "jstests_clonecollection"; -parallel = function() { - return t.parallelStatus; -} - -resetParallel = function() { - parallel().drop(); -} - -doParallel = function( work ) { - resetParallel(); - startMongoProgramNoConnect( "mongo", "--port", ports[ 1 ], "--eval", work + "; db.parallelStatus.save( {done:1} );", baseName ); -} - -doneParallel = function() { - return !!parallel().findOne(); -} - -waitParallel = function() { - assert.soon( function() { return doneParallel(); }, "parallel did not finish in time", 300000, 1000 ); -} - -cloneNo = -1; -startstartclone = function( spec ) { - spec = spec || ""; - cloneNo++; - doParallel( "z = db.runCommand( {startCloneCollection:\"jstests_clonecollection.a\", from:\"localhost:" + ports[ 0 ] + "\"" + spec + " } ); print( \"clone_clone_clone_commandResult::" + cloneNo + "::\" + tojson( z , '' , true ) + \":::::\" );" ); -} - -finishstartclone = function() { - waitParallel(); - // even after parallel shell finished, must wait for finishToken line to appear in log - assert.soon( function() { - raw = rawMongoProgramOutput().replace( /[\r\n]/gm , " " ) - ret = raw.match( new RegExp( "clone_clone_clone_commandResult::" + cloneNo + "::(.*):::::" ) ); - if ( ret == null ) { - return false; - } - ret = ret[ 1 ]; - return true; - } ); - - eval( "ret = " + ret ); - - assert.commandWorked( ret ); - return ret; -} - -dofinishclonecmd = function( ret ) { - finishToken = ret.finishToken; - // Round-tripping through JS can corrupt the cursor ids we store as BSON - // Date elements. Date( 0 ) will correspond to a cursorId value of 0, which - // makes the db start scanning from the beginning of the collection. - finishToken.cursorId = new Date( 0 ); - return t.runCommand( {finishCloneCollection:finishToken} ); -} - -finishclone = function( ret ) { - assert.commandWorked( dofinishclonecmd( ret ) ); -} ports = allocatePorts( 2 ); @@ -91,7 +32,9 @@ if ( t.system.indexes.find().count() != 2 ) { } assert.eq( 2, t.system.indexes.find().count(), "expected index missing" ); // Verify index works -assert.eq( 50, t.a.find( { i: 50 } ).hint( { i: 1 } ).explain().indexBounds[0][0].i , "verify 1" ); +x = t.a.find( { i: 50 } ).hint( { i: 1 } ).explain() +printjson( x ) +assert.eq( 50, x.indexBounds.i[0][0] , "verify 1" ); assert.eq( 1, t.a.find( { i: 50 } ).hint( { i: 1 } ).toArray().length, "match length did not match expected" ); // Check that capped-ness is preserved on clone @@ -103,91 +46,4 @@ assert( f.a.isCapped() ); assert.commandWorked( t.cloneCollection( "localhost:" + ports[ 0 ], "a" ) ); assert( t.a.isCapped(), "cloned collection not capped" ); -// Now test insert + delete + update during clone -f.a.drop(); -t.a.drop(); - -for( i = 0; i < 100000; ++i ) { - f.a.save( { i: i } ); -} -assert.eq( 100000, f.a.count() ); - -startstartclone( ", query:{i:{$gte:0}}" ); - -sleep( 200 ); -f.a.save( { i: 200000 } ); -f.a.save( { i: -1 } ); -f.a.remove( { i: 0 } ); -f.a.update( { i: 99998 }, { i: 99998, x: "y" } ); -assert.eq( 100001, f.a.count() , "D0" ); -ret = finishstartclone(); -finishclone( ret ); - -assert.eq( 100000, t.a.find().count() , "D1" ); -assert.eq( 1, t.a.find( { i: 200000 } ).count() , "D2" ); -assert.eq( 0, t.a.find( { i: -1 } ).count() , "D3" ); -assert.eq( 0, t.a.find( { i: 0 } ).count() , "D4" ); -assert.eq( 1, t.a.find( { i: 99998, x: "y" } ).count() , "D5" ); - - -// Now test oplog running out of space -- specify small size clone oplog for test. -f.a.drop(); -t.a.drop(); - -for( i = 0; i < 200000; ++i ) { - f.a.save( { i: i } ); -} -assert.eq( 200000, f.a.count() , "E1" ); - -startstartclone( ", logSizeMb:1" ); -ret = finishstartclone(); - -for( i = 200000; i < 250000; ++i ) { - f.a.save( { i: i } ); -} - -assert.eq( 250000, f.a.count() , "F0" ); - -assert.commandFailed( dofinishclonecmd( ret ) ); - -// Make sure the same works with standard size op log. -f.a.drop(); -t.a.drop(); - -for( i = 0; i < 200000; ++i ) { - f.a.save( { i: i } ); -} -assert.eq( 200000, f.a.count() , "F1" ); - -startstartclone(); -ret = finishstartclone(); - -for( i = 200000; i < 250000; ++i ) { - f.a.save( { i: i } ); -} -assert.eq( 250000, f.a.count() , "F2" ); - -finishclone( ret ); -assert.eq( 250000, t.a.find().count() , "F3" ); - -// Test startCloneCollection and finishCloneCollection commands. -f.a.drop(); -t.a.drop(); - -for( i = 0; i < 100000; ++i ) { - f.a.save( { i: i } ); -} -assert.eq( 100000, f.a.count() , "G1" ); - -startstartclone(); - -sleep( 200 ); -f.a.save( { i: -1 } ); - -ret = finishstartclone(); -assert.eq( 100001, t.a.find().count() , "G2" ); -f.a.save( { i: -2 } ); -assert.eq( 100002, f.a.find().count() , "G3" ); -finishclone( ret ); -assert.eq( 100002, t.a.find().count() , "G4" ); diff --git a/jstests/conc_update.js b/jstests/conc_update.js new file mode 100644 index 0000000..ac70861 --- /dev/null +++ b/jstests/conc_update.js @@ -0,0 +1,45 @@ +// db = db.getSisterDB("concurrency") +// db.dropDatabase(); +// +// NRECORDS=10*1024*1024 // this needs to be relatively big so that +// // the update() will take a while. +// +// print("loading data (will take a while; progress msg every 1024*1024 documents)") +// for (i=0; i<(10*1024*1024); i++) { +// db.conc.insert({x:i}) +// if ((i%(1024*1024))==0) +// print("loaded " + i/(1024*1024) + " mibi-records") +// } +// +// print("making an index (will take a while)") +// db.conc.ensureIndex({x:1}) +// +// var c1=db.conc.count({x:{$lt:NRECORDS}}) +// // this is just a flag that the child will toggle when it's done. +// db.concflag.update({}, {inprog:true}, true) +// +// updater=startParallelShell("db=db.getSisterDB('concurrency');\ +// db.conc.update({}, {$inc:{x: "+NRECORDS+"}}, false, true);\ +// print(db.getLastError());\ +// db.concflag.update({},{inprog:false})"); +// +// querycount=0; +// decrements=0; +// misses=0 +// while (1) { +// if (db.concflag.findOne().inprog) { +// c2=db.conc.count({x:{$lt:10*1024*1024}}) +// print(c2) +// querycount++; +// if (c2 0; } ).sort( { _id : -1 } ).limit(n).itcount() + end = new Date() + + join() + + print( "num: " + num + " time:" + ( end.getTime() - start.getTime() ) ) + assert.eq( 0 , t.count() , "after remove" ) + if ( n == num ) + print( "warning: shouldn't have counted all n: " + n + " num: " + num ); +} + +run( 1500 ) +run( 5000 ) + +run( 1500 , true ) +run( 5000 , true ) + + diff --git a/jstests/datasize.js b/jstests/datasize.js index 396d24d..277efac 100644 --- a/jstests/datasize.js +++ b/jstests/datasize.js @@ -5,7 +5,7 @@ assert.eq( 0, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); f.save( {qq:'c'} ); assert.eq( 32, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); f.save( {qq:'fg'} ); -assert.eq( 65, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); +assert.eq( 68, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); f.drop(); f.ensureIndex( {qq:1} ); @@ -13,14 +13,14 @@ assert.eq( 0, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); f.save( {qq:'c'} ); assert.eq( 32, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); f.save( {qq:'fg'} ); -assert.eq( 65, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); +assert.eq( 68, db.runCommand( {datasize:"test.jstests_datasize"} ).size ); assert.eq( 0, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'a'}} ).ok ); -assert.eq( 65, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'a'}, max:{qq:'z' }} ).size ); +assert.eq( 68, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'a'}, max:{qq:'z' }} ).size ); assert.eq( 32, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'a'}, max:{qq:'d' }} ).size ); assert.eq( 32, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'a'}, max:{qq:'d' }, keyPattern:{qq:1}} ).size ); -assert.eq( 33, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'d'}, max:{qq:'z' }, keyPattern:{qq:1}} ).size ); +assert.eq( 36, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'d'}, max:{qq:'z' }, keyPattern:{qq:1}} ).size ); assert.eq( 0, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'c'}, max:{qq:'c' }} ).size ); assert.eq( 32, db.runCommand( {datasize:"test.jstests_datasize", min:{qq:'c'}, max:{qq:'d' }} ).size ); diff --git a/jstests/datasize2.js b/jstests/datasize2.js new file mode 100644 index 0000000..103cb20 --- /dev/null +++ b/jstests/datasize2.js @@ -0,0 +1,27 @@ + +t = db.datasize2 +t.drop(); + +N = 1000 +for ( i=0; i 0 , "listDatabases 1" ); +assert( res.databases && res.databases.length > 0 , "listDatabases 1 " + tojson(res) ); + +x = db._adminCommand( "ismaster" ); +assert( x.ismaster , "ismaster failed: " + tojson( x ) ) // TODO: add more tests here diff --git a/jstests/dbcase.js b/jstests/dbcase.js new file mode 100644 index 0000000..bf0c8e6 --- /dev/null +++ b/jstests/dbcase.js @@ -0,0 +1,23 @@ + +a = db.getSisterDB( "test_dbnamea" ) +b = db.getSisterDB( "test_dbnameA" ) + +a.dropDatabase(); +b.dropDatabase(); + +a.foo.save( { x : 1 } ) +z = db.getLastErrorObj(); +assert.eq( 0 , z.code || 0 , "A : " + tojson(z) ) + +b.foo.save( { x : 1 } ) +z = db.getLastErrorObj(); +assert.eq( 13297 , z.code || 0 , "B : " + tojson(z) ) + +print( db.getMongo().getDBNames() ) + +a.dropDatabase(); +b.dropDatabase(); + +print( db.getMongo().getDBNames() ) + + diff --git a/jstests/dbhash.js b/jstests/dbhash.js index 101be18..e9cbc94 100644 --- a/jstests/dbhash.js +++ b/jstests/dbhash.js @@ -5,6 +5,15 @@ b = db.dbhashb; a.drop(); b.drop(); +// debug SERVER-761 +db.getCollectionNames().forEach( function( x ) { + v = db[ x ].validate(); + if ( !v.valid ) { + print( x ); + printjson( v ); + } + } ); + function gh( coll , mydb ){ if ( ! mydb ) mydb = db; var x = mydb.runCommand( "dbhash" ).collections[coll.getName()]; diff --git a/jstests/disk/directoryperdb.js b/jstests/disk/directoryperdb.js index a5fd18e..90a1f03 100644 --- a/jstests/disk/directoryperdb.js +++ b/jstests/disk/directoryperdb.js @@ -6,7 +6,7 @@ dbpath = "/data/db/" + baseDir + "/"; var m = startMongod( "--directoryperdb", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); db = m.getDB( baseName ); db[ baseName ].save( {} ); -assert.eq( 1, db[ baseName ].count() ); +assert.eq( 1, db[ baseName ].count() , "A : " + tojson( db[baseName].find().toArray() ) ); checkDir = function( dir ) { db.runCommand( {fsync:1} ); @@ -22,7 +22,7 @@ checkDir = function( dir ) { files = listFiles( dir + baseName ); for( f in files ) { - assert( new RegExp( baseName + "/" + baseName + "." ).test( files[ f ].name ) ); + assert( new RegExp( baseName + "/" + baseName + "." ).test( files[ f ].name ) , "B dir:" + dir + " f: " + f ); } } checkDir( dbpath ); @@ -40,7 +40,7 @@ for( f in files ) { } } checkDir( backupDir ); -assert.eq( 1, db[ baseName ].count() ); +assert.eq( 1, db[ baseName ].count() , "C" ); // tool test stopMongod( port ); @@ -53,7 +53,7 @@ runMongoProgram( "mongorestore", "--dbpath", dbpath, "--directoryperdb", "--dir" m = startMongoProgram( "mongod", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); db = m.getDB( baseName ); checkDir( dbpath ); -assert.eq( 1, db[ baseName ].count() ); +assert.eq( 1, db[ baseName ].count() , "C" ); assert( m.getDBs().totalSize > 0, "bad size calc" ); // drop db test diff --git a/jstests/disk/repair.js b/jstests/disk/repair.js index 6c8d81b..1308beb 100644 --- a/jstests/disk/repair.js +++ b/jstests/disk/repair.js @@ -1,3 +1,5 @@ +// check --repairpath and --repair + var baseName = "jstests_disk_repair"; port = allocatePorts( 1 )[ 0 ]; @@ -10,9 +12,36 @@ resetDbpath( repairpath ); m = startMongoProgram( "mongod", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); db = m.getDB( baseName ); db[ baseName ].save( {} ); -db.runCommand( {repairDatabase:1, backupOriginalFiles:true} ); +assert.commandWorked( db.runCommand( {repairDatabase:1, backupOriginalFiles:true} ) ); +function check() { + files = listFiles( dbpath ); + for( f in files ) { + assert( ! new RegExp( "^" + dbpath + "backup_" ).test( files[ f ].name ), "backup dir in dbpath" ); + } -files = listFiles( dbpath ); -for( f in files ) { - assert( ! new RegExp( "^" + dbpath + "backup_" ).test( files[ f ].name ), "backup dir in dbpath" ); + assert.eq.automsg( "1", "db[ baseName ].count()" ); } +check(); +stopMongod( port ); + +resetDbpath( repairpath ); +m = startMongoProgram( "mongod", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +assert.commandWorked( db.runCommand( {repairDatabase:1} ) ); +check(); +stopMongod( port ); + +resetDbpath( repairpath ); +rc = runMongoProgram( "mongod", "--repair", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +assert.eq.automsg( "0", "rc" ); +m = startMongoProgram( "mongod", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +check(); +stopMongod( port ); + +resetDbpath( repairpath ); +rc = runMongoProgram( "mongod", "--repair", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +assert.eq.automsg( "0", "rc" ); +m = startMongoProgram( "mongod", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +check(); diff --git a/jstests/disk/repair2.js b/jstests/disk/repair2.js new file mode 100644 index 0000000..a28ef79 --- /dev/null +++ b/jstests/disk/repair2.js @@ -0,0 +1,47 @@ +// repair with --directoryperdb + +var baseName = "jstests_disk_repair2"; + +port = allocatePorts( 1 )[ 0 ]; +dbpath = "/data/db/" + baseName + "/"; +repairpath = dbpath + "repairDir/" + +resetDbpath( dbpath ); +resetDbpath( repairpath ); + +m = startMongoProgram( "mongod", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +db[ baseName ].save( {} ); +assert.commandWorked( db.runCommand( {repairDatabase:1, backupOriginalFiles:true} ) ); +function check() { + files = listFiles( dbpath ); + for( f in files ) { + assert( ! new RegExp( "^" + dbpath + "backup_" ).test( files[ f ].name ), "backup dir in dbpath" ); + } + + assert.eq.automsg( "1", "db[ baseName ].count()" ); +} +check(); +stopMongod( port ); + +resetDbpath( repairpath ); +m = startMongoProgram( "mongod", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +assert.commandWorked( db.runCommand( {repairDatabase:1} ) ); +check(); +stopMongod( port ); + +resetDbpath( repairpath ); +rc = runMongoProgram( "mongod", "--repair", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +assert.eq.automsg( "0", "rc" ); +m = startMongoProgram( "mongod", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +check(); +stopMongod( port ); + +resetDbpath( repairpath ); +rc = runMongoProgram( "mongod", "--repair", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +assert.eq.automsg( "0", "rc" ); +m = startMongoProgram( "mongod", "--directoryperdb", "--port", port, "--dbpath", dbpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); +db = m.getDB( baseName ); +check(); diff --git a/jstests/disk/repair3.js b/jstests/disk/repair3.js new file mode 100644 index 0000000..c986dce --- /dev/null +++ b/jstests/disk/repair3.js @@ -0,0 +1,52 @@ +// test --repairpath on aother partition + +var baseName = "jstests_disk_repair3"; +var repairbase = "/data/db/repairpartitiontest" +var repairpath = repairbase + "/dir" + +doIt = false; +files = listFiles( "/data/db" ); +for ( i in files ) { + if ( files[ i ].name == repairbase ) { + doIt = true; + } +} + +if ( !doIt ) { + print( "path " + repairpath + " missing, skipping repair3 test" ); + doIt = false; +} + +if ( doIt ) { + + port = allocatePorts( 1 )[ 0 ]; + dbpath = "/data/db/" + baseName + "/"; + + resetDbpath( dbpath ); + resetDbpath( repairpath ); + + m = startMongoProgram( "mongod", "--nssize", "8", "--noprealloc", "--smallfiles", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); + db = m.getDB( baseName ); + db[ baseName ].save( {} ); + assert.commandWorked( db.runCommand( {repairDatabase:1, backupOriginalFiles:false} ) ); + function check() { + files = listFiles( dbpath ); + for( f in files ) { + assert( ! new RegExp( "^" + dbpath + "backup_" ).test( files[ f ].name ), "backup dir in dbpath" ); + } + + assert.eq.automsg( "1", "db[ baseName ].count()" ); + } + + check(); + stopMongod( port ); + + resetDbpath( repairpath ); + rc = runMongoProgram( "mongod", "--nssize", "8", "--noprealloc", "--smallfiles", "--repair", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); + assert.eq.automsg( "0", "rc" ); + m = startMongoProgram( "mongod", "--nssize", "8", "--noprealloc", "--smallfiles", "--port", port, "--dbpath", dbpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); + db = m.getDB( baseName ); + check(); + stopMongod( port ); + +} \ No newline at end of file diff --git a/jstests/disk/repair4.js b/jstests/disk/repair4.js new file mode 100644 index 0000000..64c0f37 --- /dev/null +++ b/jstests/disk/repair4.js @@ -0,0 +1,44 @@ +// test that disk space check happens on --repairpath partition + +var baseName = "jstests_disk_repair4"; +var smallbase = "/data/db/repairpartitiontest" +var smallpath = smallbase + "/dir" + +doIt = false; +files = listFiles( "/data/db" ); +for ( i in files ) { + if ( files[ i ].name == smallbase ) { + doIt = true; + } +} + +if ( !doIt ) { + print( "path " + smallpath + " missing, skipping repair4 test" ); + doIt = false; +} + +if ( doIt ) { + + port = allocatePorts( 1 )[ 0 ]; + repairpath = "/data/db/" + baseName + "/"; + + resetDbpath( smallpath ); + resetDbpath( repairpath ); + + m = startMongoProgram( "mongod", "--nssize", "8", "--noprealloc", "--smallfiles", "--port", port, "--dbpath", smallpath, "--repairpath", repairpath, "--nohttpinterface", "--bind_ip", "127.0.0.1" ); + db = m.getDB( baseName ); + db[ baseName ].save( {} ); + assert.commandWorked( db.runCommand( {repairDatabase:1, backupOriginalFiles:true} ) ); + function check() { + files = listFiles( smallpath ); + for( f in files ) { + assert( ! new RegExp( "^" + smallpath + "backup_" ).test( files[ f ].name ), "backup dir in dbpath" ); + } + + assert.eq.automsg( "1", "db[ baseName ].count()" ); + } + + check(); + stopMongod( port ); + +} \ No newline at end of file diff --git a/jstests/distinct_array1.js b/jstests/distinct_array1.js new file mode 100644 index 0000000..0d41b80 --- /dev/null +++ b/jstests/distinct_array1.js @@ -0,0 +1,24 @@ +t = db.distinct_array1; +t.drop(); + +t.save( { a : [1,2,3] } ) +t.save( { a : [2,3,4] } ) +t.save( { a : [3,4,5] } ) +t.save( { a : 9 } ) + + +res = t.distinct( "a" ); +assert.eq( "1,2,3,4,5,9" , res.toString() , "A1" ); + + +//t.drop(); + +t.save( { a : [{b:"a"}, {b:"d"}] , c : 12 } ); +t.save( { a : [{b:"b"}, {b:"d"}] , c : 12 } ); +t.save( { a : [{b:"c"}, {b:"e"}] , c : 12 } ); +t.save( { a : [{b:"c"}, {b:"f"}] , c : 12 } ); +t.save( { a : [] , c : 12 } ); +t.save( { a : { b : "z"} , c : 12 } ); + +res = t.distinct( "a.b" ); +assert.eq( "a,b,c,d,e,f,z" , res.toString() , "B1" ); diff --git a/jstests/distinct_speed1.js b/jstests/distinct_speed1.js new file mode 100644 index 0000000..4cae5b0 --- /dev/null +++ b/jstests/distinct_speed1.js @@ -0,0 +1,26 @@ + +t = db.distinct_speed1; + +t.drop(); +for ( var i=0; i<10000; i++ ){ + t.save( { x : i % 10 } ); +} + +assert.eq( 10 , t.distinct("x").length , "A1" ); + +function fast(){ + t.find().explain().millis; +} + +function slow(){ + t.distinct("x"); +} + +for ( i=0; i<3; i++ ){ + print( "it: " + Date.timeFunc( fast ) ); + print( "di: " + Date.timeFunc( slow ) ); +} + + +t.ensureIndex( { x : 1 } ); +t.distinct( "x" , { x : 5 } ) diff --git a/jstests/drop.js b/jstests/drop.js index 1bd539e..e1ecf8d 100644 --- a/jstests/drop.js +++ b/jstests/drop.js @@ -13,7 +13,7 @@ assert.eq( 0, db.system.indexes.find( {ns:"test.jstests_drop"} ).count() , "D" ) f.resetIndexCache(); f.ensureIndex( {a:1} ); assert.eq( 2, db.system.indexes.find( {ns:"test.jstests_drop"} ).count() , "E" ); -assert.commandWorked( db.runCommand( {deleteIndexes:"jstests_drop",index:"*"} ) ); +assert.commandWorked( db.runCommand( {deleteIndexes:"jstests_drop",index:"*"} ), "delete indexes A" ); assert.eq( 1, db.system.indexes.find( {ns:"test.jstests_drop"} ).count() , "G" ); // make sure we can still use it diff --git a/jstests/evalb.js b/jstests/evalb.js index 3bc3db1..177930c 100644 --- a/jstests/evalb.js +++ b/jstests/evalb.js @@ -10,5 +10,8 @@ db.setProfilingLevel( 2 ); assert.eq( 3, db.eval( function(){ return db.evalb.findOne().x; } ) , "B" ); +o = db.system.profile.find().sort( { $natural : -1 } ).limit(1).next(); +assert( o.info.indexOf( "findOne().x" ) > 0 , "C : " + tojson( o ) ) + db.setProfilingLevel( 0 ); diff --git a/jstests/explain2.js b/jstests/explain2.js index 5a36552..4960e5a 100644 --- a/jstests/explain2.js +++ b/jstests/explain2.js @@ -19,7 +19,7 @@ q = { a : { $gt : 3 } } go( q , 6 , 7 , 6 ); q.b = 5 -go( q , 1 , 6 , 1 ); +go( q , 1 , 1 , 1 ); delete q.b q.c = 5 diff --git a/jstests/find_and_modify.js b/jstests/find_and_modify.js index 5e10079..a80859a 100644 --- a/jstests/find_and_modify.js +++ b/jstests/find_and_modify.js @@ -33,6 +33,6 @@ assert.eq(out.priority, 1); out = t.findAndModify({sort:{priority:1}, remove:1}); assert.eq(out.priority, 2); -// return empty obj if no matches (drivers may handle this differently) +// return null (was {} before 1.5.4) if no matches (drivers may handle this differently) out = t.findAndModify({query:{no_such_field:1}, remove:1}); -assert.eq(out, {}); +assert.eq(out, null); diff --git a/jstests/find_and_modify2.js b/jstests/find_and_modify2.js new file mode 100644 index 0000000..108fc0f --- /dev/null +++ b/jstests/find_and_modify2.js @@ -0,0 +1,10 @@ +t = db.find_and_modify2; +t.drop(); + +t.insert({_id:1, i:0, j:0}); + +out = t.findAndModify({update: {$inc: {i:1}}, 'new': true, fields: {i:1}}); +assert.eq(out, {_id:1, i:1}); + +out = t.findAndModify({update: {$inc: {i:1}}, fields: {i:0}}); +assert.eq(out, {_id:1, j:0}); diff --git a/jstests/find_and_modify3.js b/jstests/find_and_modify3.js new file mode 100644 index 0000000..1d30204 --- /dev/null +++ b/jstests/find_and_modify3.js @@ -0,0 +1,21 @@ +t = db.find_and_modify3; +t.drop(); + +t.insert({_id:0, other:0, comments:[{i:0, j:0}, {i:1, j:1}]}); +t.insert({_id:1, other:1, comments:[{i:0, j:0}, {i:1, j:1}]}); // this is the only one that gets modded +t.insert({_id:2, other:2, comments:[{i:0, j:0}, {i:1, j:1}]}); + +orig0 = t.findOne({_id:0}) +orig2 = t.findOne({_id:2}) + +out = t.findAndModify({query: {_id:1, 'comments.i':0}, update: {$set: {'comments.$.j':2}}, 'new': true}); +assert.eq(out.comments[0], {i:0, j:2}); +assert.eq(out.comments[1], {i:1, j:1}); +assert.eq(t.findOne({_id:0}), orig0); +assert.eq(t.findOne({_id:2}), orig2); + +out = t.findAndModify({query: {other:1, 'comments.i':1}, update: {$set: {'comments.$.j':3}}, 'new': true}); +assert.eq(out.comments[0], {i:0, j:2}); +assert.eq(out.comments[1], {i:1, j:3}); +assert.eq(t.findOne({_id:0}), orig0); +assert.eq(t.findOne({_id:2}), orig2); diff --git a/jstests/find_and_modify4.js b/jstests/find_and_modify4.js new file mode 100644 index 0000000..ad1fb36 --- /dev/null +++ b/jstests/find_and_modify4.js @@ -0,0 +1,55 @@ +t = db.find_and_modify4; +t.drop(); + +// this is the best way to build auto-increment +function getNextVal(counterName){ + var ret = t.findAndModify({ + query: {_id: counterName}, + update: {$inc: {val: 1}}, + upsert: true, + 'new': true, + }); + return ret.val; +} + +assert.eq(getNextVal("a"), 1); +assert.eq(getNextVal("a"), 2); +assert.eq(getNextVal("a"), 3); +assert.eq(getNextVal("z"), 1); +assert.eq(getNextVal("z"), 2); +assert.eq(getNextVal("a"), 4); + +t.drop(); + +function helper(upsert){ + return t.findAndModify({ + query: {_id: "asdf"}, + update: {$inc: {val: 1}}, + upsert: upsert, + 'new': false // the default + }); +} + +// upsert:false so nothing there before and after +assert.eq(helper(false), null); +assert.eq(t.count(), 0); + +// upsert:false so nothing there before; something there after +assert.eq(helper(true), {}); +assert.eq(t.count(), 1); +assert.eq(helper(true), {_id: 'asdf', val: 1}); +assert.eq(helper(false), {_id: 'asdf', val: 2}); // upsert only matters when obj doesn't exist +assert.eq(helper(true), {_id: 'asdf', val: 3}); + + +// _id created if not specified +var out = t.findAndModify({ + query: {a:1}, + update: {$set: {b: 2}}, + upsert: true, + 'new': true + }); +assert.neq(out._id, undefined); +assert.eq(out.a, 1); +assert.eq(out.b, 2); + diff --git a/jstests/fm4.js b/jstests/fm4.js new file mode 100644 index 0000000..1ce947a --- /dev/null +++ b/jstests/fm4.js @@ -0,0 +1,16 @@ +t = db.fm4 +t.drop(); + +t.insert({_id:1, a:1, b:1}); + +assert.eq( t.findOne({}, {_id:1}), {_id:1}, 1) +assert.eq( t.findOne({}, {_id:0}), {a:1, b:1}, 2) + +assert.eq( t.findOne({}, {_id:1, a:1}), {_id:1, a:1}, 3) +assert.eq( t.findOne({}, {_id:0, a:1}), {a:1}, 4) + +assert.eq( t.findOne({}, {_id:0, a:0}), {b:1}, 6) +assert.eq( t.findOne({}, { a:0}), {_id:1, b:1}, 5) + +// not sure if we want to suport this since it is the same as above +//assert.eq( t.findOne({}, {_id:1, a:0}), {_id:1, b:1}, 5) diff --git a/jstests/geo2.js b/jstests/geo2.js index 6b1a1a2..ff4552b 100644 --- a/jstests/geo2.js +++ b/jstests/geo2.js @@ -43,6 +43,7 @@ printjson( t.find( { loc : { $near : [ 50 , 50 ] } } ).explain() ) assert.lt( 3 , a( t.find( { loc : { $near : [ 50 , 50 ] } } ).limit(50) ) , "C1" ) assert.gt( 3 , a( t.find( { loc : { $near : [ 50 , 50 , 3 ] } } ).limit(50) ) , "C2" ) +assert.gt( 3 , a( t.find( { loc : { $near : [ 50 , 50 ] , $maxDistance : 3 } } ).limit(50) ) , "C3" ) diff --git a/jstests/geo3.js b/jstests/geo3.js index 6bf27f9..ea6b497 100644 --- a/jstests/geo3.js +++ b/jstests/geo3.js @@ -18,7 +18,7 @@ fast = db.runCommand( { geoNear : t.getName() , near : [ 50 , 50 ] , num : 10 } slow = db.runCommand( { geoNear : t.getName() , near : [ 50 , 50 ] , num : 10 , start : "11" } ); -//printjson( slow.stats ); +printjson( slow.stats ); assert.lt( fast.stats.nscanned * 10 , slow.stats.nscanned , "A1" ); assert.lt( fast.stats.objectsLoaded , slow.stats.objectsLoaded , "A2" ); diff --git a/jstests/geo_box3.js b/jstests/geo_box3.js new file mode 100644 index 0000000..8941f63 --- /dev/null +++ b/jstests/geo_box3.js @@ -0,0 +1,36 @@ +// How to construct a test to stress the flaw in SERVER-994: +// construct an index, think up a bounding box inside the index that +// doesn't include the center of the index, and put a point inside the +// bounding box. + +// This is the bug reported in SERVER-994. +t=db.geo_box3; +t.drop(); +t.insert({ point : { x : -15000000, y : 10000000 } }); +t.ensureIndex( { point : "2d" } , { min : -21000000 , max : 21000000 } ); +var c=t.find({point: {"$within": {"$box": [[-20000000, 7000000], [0, 15000000]]} } }); +assert.eq(1, c.count(), "A1"); + +// Same thing, modulo 1000000. +t=db.geo_box3; +t.drop(); +t.insert({ point : { x : -15, y : 10 } }); +t.ensureIndex( { point : "2d" } , { min : -21 , max : 21 } ); +var c=t.find({point: {"$within": {"$box": [[-20, 7], [0, 15]]} } }); +assert.eq(1, c.count(), "B1"); + +// Two more examples, one where the index is centered at the origin, +// one not. +t=db.geo_box3; +t.drop(); +t.insert({ point : { x : 1.0 , y : 1.0 } }); +t.ensureIndex( { point : "2d" } , { min : -2 , max : 2 } ); +var c=t.find({point: {"$within": {"$box": [[.1, .1], [1.99, 1.99]]} } }); +assert.eq(1, c.count(), "C1"); + +t=db.geo_box3; +t.drop(); +t.insert({ point : { x : 3.9 , y : 3.9 } }); +t.ensureIndex( { point : "2d" } , { min : 0 , max : 4 } ); +var c=t.find({point: {"$within": {"$box": [[2.05, 2.05], [3.99, 3.99]]} } }); +assert.eq(1, c.count(), "D1"); diff --git a/jstests/geo_circle2.js b/jstests/geo_circle2.js new file mode 100644 index 0000000..0232490 --- /dev/null +++ b/jstests/geo_circle2.js @@ -0,0 +1,23 @@ + +t = db.geo_circle2; +t.drop(); + +t.ensureIndex({loc : "2d", categories:1}, {"name":"placesIdx", "min": -100, "max": 100}); + +t.insert({ "uid" : 368900 , "loc" : { "x" : -36 , "y" : -8} ,"categories" : [ "sports" , "hotel" , "restaurant"]}); +t.insert({ "uid" : 555344 , "loc" : { "x" : 13 , "y" : 29} ,"categories" : [ "sports" , "hotel"]}); +t.insert({ "uid" : 855878 , "loc" : { "x" : 38 , "y" : 30} ,"categories" : [ "sports" , "hotel"]}); +t.insert({ "uid" : 917347 , "loc" : { "x" : 15 , "y" : 46} ,"categories" : [ "hotel"]}); +t.insert({ "uid" : 647874 , "loc" : { "x" : 25 , "y" : 23} ,"categories" : [ "hotel" , "restaurant"]}); +t.insert({ "uid" : 518482 , "loc" : { "x" : 4 , "y" : 25} ,"categories" : [ ]}); +t.insert({ "uid" : 193466 , "loc" : { "x" : -39 , "y" : 22} ,"categories" : [ "sports" , "hotel"]}); +t.insert({ "uid" : 622442 , "loc" : { "x" : -24 , "y" : -46} ,"categories" : [ "hotel"]}); +t.insert({ "uid" : 297426 , "loc" : { "x" : 33 , "y" : -49} ,"categories" : [ "hotel"]}); +t.insert({ "uid" : 528464 , "loc" : { "x" : -43 , "y" : 48} ,"categories" : [ "restaurant"]}); +t.insert({ "uid" : 90579 , "loc" : { "x" : -4 , "y" : -23} ,"categories" : [ "restaurant"]}); +t.insert({ "uid" : 368895 , "loc" : { "x" : -8 , "y" : 14} ,"categories" : [ "sports" ]}); +t.insert({ "uid" : 355844 , "loc" : { "x" : 34 , "y" : -4} ,"categories" : [ "sports" , "hotel"]}); + + +assert.eq( 10 , t.find({ "loc" : { "$within" : { "$center" : [ { "x" : 0 ,"y" : 0} , 50]}} } ).itcount() , "A" ); +assert.eq( 6 , t.find({ "loc" : { "$within" : { "$center" : [ { "x" : 0 ,"y" : 0} , 50]}}, "categories" : "sports" } ).itcount() , "B" ); diff --git a/jstests/geo_circle3.js b/jstests/geo_circle3.js new file mode 100644 index 0000000..2882b47 --- /dev/null +++ b/jstests/geo_circle3.js @@ -0,0 +1,28 @@ +// SERVER-848 and SERVER-1191. +db.places.drop() + +n = 0; +db.places.save({ "_id": n++, "loc" : { "x" : 4.9999, "y" : 52 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 5, "y" : 52 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 5.0001, "y" : 52 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 5, "y" : 52.0001 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 5, "y" : 51.9999 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 4.9999, "y" : 52.0001 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 5.0001, "y" : 52.0001 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 4.9999, "y" : 51.9999 } }) +db.places.save({ "_id": n++, "loc" : { "x" : 5.0001, "y" : 51.9999 } }) +db.places.ensureIndex( { loc : "2d" } ) +radius=0.0001 +center=[5,52] +//print(db.places.find({"loc" : {"$within" : {"$center" : [center, radius]}}}).count()) +// FIXME: we want an assert, e.g., that there be 5 answers in the find(). +db.places.find({"loc" : {"$within" : {"$center" : [center, radius]}}}).forEach(printjson); + + +// the result: +// { "_id" : ObjectId("4bb1f2f088df513435bcb4e1"), "loc" : { "x" : 5, "y" : 52 } } +// { "_id" : ObjectId("4bb1f54383459c40223a8ae7"), "loc" : { "x" : 5, "y" : 51.9999 } } +// { "_id" : ObjectId("4bb1f54583459c40223a8aeb"), "loc" : { "x" : 5.0001, "y" : 51.9999 } } +// { "_id" : ObjectId("4bb1f2e588df513435bcb4e0"), "loc" : { "x" : 4.9999, "y" : 52 } } +// { "_id" : ObjectId("4bb1f30888df513435bcb4e2"), "loc" : { "x" : 5.0001, "y" : 52 } } +// { "_id" : ObjectId("4bb1f54383459c40223a8ae8"), "loc" : { "x" : 4.9999, "y" : 52.0001 } } diff --git a/jstests/geo_circle4.js b/jstests/geo_circle4.js new file mode 100644 index 0000000..9edd5a1 --- /dev/null +++ b/jstests/geo_circle4.js @@ -0,0 +1,24 @@ +// Reported as server-848. +db.server848.drop(); + +radius=0.0001; +center=[5,52]; + +db.server848.save({ "_id": 1, "loc" : { "x" : 4.9999, "y" : 52 } }); +db.server848.save({ "_id": 2, "loc" : { "x" : 5, "y" : 52 } }); +db.server848.save({ "_id": 3, "loc" : { "x" : 5.0001, "y" : 52 } }); +db.server848.save({ "_id": 4, "loc" : { "x" : 5, "y" : 52.0001 } }); +db.server848.save({ "_id": 5, "loc" : { "x" : 5, "y" : 51.9999 } }); +db.server848.save({ "_id": 6, "loc" : { "x" : 4.9999, "y" : 52.0001 } }); +db.server848.save({ "_id": 7, "loc" : { "x" : 5.0001, "y" : 52.0001 } }); +db.server848.save({ "_id": 8, "loc" : { "x" : 4.9999, "y" : 51.9999 } }); +db.server848.save({ "_id": 9, "loc" : { "x" : 5.0001, "y" : 51.9999 } }); +db.server848.ensureIndex( { loc : "2d" } ); +r=db.server848.find({"loc" : {"$within" : {"$center" : [center, radius]}}}, {_id:1}); +assert.eq(5, r.count(), "A1"); +// FIXME: surely code like this belongs in utils.js. +a=r.toArray(); +x=[]; +for (k in a) { x.push(a[k]["_id"]) } +x.sort() +assert.eq([1,2,3,4,5], x, "B1"); diff --git a/jstests/geo_circle5.js b/jstests/geo_circle5.js new file mode 100644 index 0000000..ed190e4 --- /dev/null +++ b/jstests/geo_circle5.js @@ -0,0 +1,28 @@ +// reported as server-1238. + +db.server1238.drop(); +db.server1238.remove() +db.server1238.save({ loc: [ 5000000, 900000 ], id: 1}) +db.server1238.save({ loc: [ 5000000, 900000 ], id: 2}) +db.server1238.ensureIndex( { loc : "2d" } , { min : -21000000 , max : 21000000 } ) +db.server1238.save({ loc: [ 5000000, 900000 ], id: 3}) +db.server1238.save({ loc: [ 5000000, 900000 ], id: 4}) + +c1=db.server1238.find({"loc" : {"$within" : {"$center" : [[5000000, 900000], 1.0]}}}).count() + +c2=db.server1238.find({"loc" : {"$within" : {"$center" : [[5000001, 900000], 5.0]}}}).count() + + +assert.eq(4, c1, "A1"); +assert.eq(c1, c2, "B1"); +//print(db.server1238.find({"loc" : {"$within" : {"$center" : [[5000001, 900000], 5.0]}}}).toArray()); +// [ +// { +// "_id" : ObjectId("4c173306f5d9d34a46cb7b11"), +// "loc" : [ +// 5000000, +// 900000 +// ], +// "id" : 4 +// } +// ] \ No newline at end of file diff --git a/jstests/geo_haystack1.js b/jstests/geo_haystack1.js new file mode 100644 index 0000000..f4035ec --- /dev/null +++ b/jstests/geo_haystack1.js @@ -0,0 +1,59 @@ + +t = db.geo_haystack1 +t.drop() + +function distance( a , b ){ + var x = a[0] - b[0]; + var y = a[1] - b[1]; + return Math.sqrt( ( x * x ) + ( y * y ) ); +} + +function distanceTotal( a , arr , f ){ + var total = 0; + for ( var i=0; i queries[i].maxDistance ) + continue; + if ( queries[i].search.z != n % 5 ) + continue; + answers[i].results.push( { _id : n , loc : [ x , y ]} ) + answers[i].totalDistance += d; + } + + n++; + } +} + +t.ensureIndex( { loc : "geoHaystack" , z : 1 } , { bucketSize : .7 } ); + +for ( i=0; i queries[i].maxDistance ) + continue; + if ( queries[i].search.z != n % 10 && + queries[i].search.z != ( n + 5 ) % 10 ) + continue; + answers[i].results.push( { _id : n , loc : [ x , y ] } ) + answers[i].totalDistance += d; + } + + n++; + } +} + +t.ensureIndex( { loc : "geoHaystack" , z : 1 } , { bucketSize : .7 } ); + +for ( i=0; i ib.b[ 1 ][ 0 ]" ); +ib = t.find( {a:2,b:{$in:[3,4]}} ).sort( {a:-1,b:1} ).explain().indexBounds; +checkRanges( {a:[[2,2]],b:[[3,3],[4,4]]}, ib ); +assert.automsg( "ib.b[ 0 ][ 0 ] < ib.b[ 1 ][ 0 ]" ); diff --git a/jstests/in5.js b/jstests/in5.js new file mode 100644 index 0000000..435c886 --- /dev/null +++ b/jstests/in5.js @@ -0,0 +1,56 @@ + +t = db.in5 + +function go( fn ){ + t.drop(); + o = {}; + o[fn] = { a : 1 , b : 2 }; + t.insert( o ); + + x = {}; + x[fn] = { a : 1 , b : 2 }; + assert.eq( 1 , t.find( x ).itcount() , "A1 - " + fn ); + + + y = {}; + y[fn] = { $in : [ { a : 1 , b : 2 } ] } + assert.eq( 1 , t.find( y ).itcount() , "A2 - " + fn ); + + + z = {}; + z[fn+".a"] = 1; + z[fn+".b"] = { $in : [ 2 ] } + assert.eq( 1 , t.find( z ).itcount() , "A3 - " + fn ); // SERVER-1366 + + + i = {} + i[fn] = 1 + t.ensureIndex( i ) + + assert.eq( 1 , t.find( x ).itcount() , "B1 - " + fn ); + assert.eq( 1 , t.find( y ).itcount() , "B2 - " + fn ); + assert.eq( 1 , t.find( z ).itcount() , "B3 - " + fn ); // SERVER-1366 + + t.dropIndex( i ) + + assert.eq( 1 , t.getIndexes().length , "T2" ); + + i = {} + i[fn + ".a" ] = 1; + t.ensureIndex( i ) + assert.eq( 2 , t.getIndexes().length , "T3" ); + + assert.eq( 1 , t.find( x ).itcount() , "C1 - " + fn ); + assert.eq( 1 , t.find( y ).itcount() , "C2 - " + fn ); + assert.eq( 1 , t.find( z ).itcount() , "C3 - " + fn ); // SERVER-1366 + + t.dropIndex( i ) + + +} + +go( "x" ); +go( "_id" ) + + + diff --git a/jstests/in6.js b/jstests/in6.js new file mode 100644 index 0000000..f114d93 --- /dev/null +++ b/jstests/in6.js @@ -0,0 +1,13 @@ +t = db.jstests_in6; +t.drop(); + +t.save( {} ); + +function doTest() { + assert.eq.automsg( "1", "t.count( {i:null} )" ); + assert.eq.automsg( "1", "t.count( {i:{$in:[null]}} )" ); +} + +doTest(); +t.ensureIndex( {i:1} ); +doTest(); diff --git a/jstests/in7.js b/jstests/in7.js new file mode 100644 index 0000000..212723d --- /dev/null +++ b/jstests/in7.js @@ -0,0 +1,6 @@ +t = db.jstests_slow_in1; + +t.drop(); +t.ensureIndex( {a:1,b:1,c:1,d:1,e:1,f:1} ); +i = {$in:[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]}; +assert.throws.automsg( function() { t.count( {a:i,b:i,c:i,d:i,e:i,f:i} ); } ); diff --git a/jstests/index1.js b/jstests/index1.js index 620f8bb..9767d08 100644 --- a/jstests/index1.js +++ b/jstests/index1.js @@ -17,9 +17,9 @@ assert( t.findOne( { z : { a : 17 } } ) == null); o = { name : "bar" , z : { a : 18 } }; t.save( o ); -assert( t.find().length() == 2 ); -assert( t.find().sort( { "z.a" : 1 } ).length() == 2 ); -assert( t.find().sort( { "z.a" : -1 } ).length() == 2 ); +assert.eq.automsg( "2", "t.find().length()" ); +assert.eq.automsg( "2", "t.find().sort( { 'z.a' : 1 } ).length()" ); +assert.eq.automsg( "2", "t.find().sort( { 'z.a' : -1 } ).length()" ); // We are planning to phase out this syntax. assert( t.find().sort( { z : { a : 1 } } ).length() == 2 ); assert( t.find().sort( { z : { a: -1 } } ).length() == 2 ); diff --git a/jstests/index10.js b/jstests/index10.js index c638264..92f5927 100644 --- a/jstests/index10.js +++ b/jstests/index10.js @@ -14,9 +14,9 @@ assert.eq( 5, t.count() ); t.dropIndexes(); t.ensureIndex( {i:1}, true ); err = db.getLastErrorObj(); -assert( err.err ); +assert( err.err , "err.err" ); assert.eq( 11000, err.code ); -assert.eq( 1, db.system.indexes.count( {ns:"test.jstests_index10" } ) ); // only id index +assert( 1 == db.system.indexes.count( {ns:"test.jstests_index10" } ), "only id index" ); // t.dropIndexes(); ts = t.totalIndexSize(); diff --git a/jstests/index6.js b/jstests/index6.js index 7514aca..8dbd8f7 100644 --- a/jstests/index6.js +++ b/jstests/index6.js @@ -1,6 +1,6 @@ // index6.js Test indexes on array subelements. -r = db.ed.db.index5; +r = db.ed.db.index6; r.drop(); r.save( { comments : [ { name : "eliot", foo : 1 } ] } ); diff --git a/jstests/index7.js b/jstests/index7.js index a3b88d5..9e3a6c6 100644 --- a/jstests/index7.js +++ b/jstests/index7.js @@ -9,12 +9,14 @@ function noIndex( q ) { } function start( k, q, rev) { - var s = q.explain().indexBounds[rev?1:0][0]; + var exp = q.explain().indexBounds; + var s = {a:exp.a[rev?1:0][0],b:exp.b[0][0]}; assert.eq( k.a, s.a ); assert.eq( k.b, s.b ); } function end( k, q, rev) { - var e = q.explain().indexBounds[rev?1:0][1]; + var exp = q.explain().indexBounds + var e = {a:exp.a[rev?1:0][1],b:exp.b[0][1]}; assert.eq( k.a, e.a ); assert.eq( k.b, e.b ); } @@ -33,12 +35,12 @@ noIndex( f.find( { a: 5 } ).sort( { a: 1 } ).hint( { $natural: 1 } ) ); f.drop(); f.ensureIndex( { a: 1, b: 1 } ); -assert.eq( 1, f.find( { a: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds[0][0].a ); -assert.eq( 1, f.find( { a: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds[0][1].a ); -assert.eq( 1, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds[0][0].a ); -assert.eq( 1, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds[0][1].a ); -assert.eq( null, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds[0][0].c ); -assert.eq( null, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds[0][1].c ); +assert.eq( 1, f.find( { a: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds.a[0][0] ); +assert.eq( 1, f.find( { a: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds.a[0][1] ); +assert.eq( 1, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds.a[0][0] ); +assert.eq( 1, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds.a[0][1] ); +assert.eq( null, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds.c ); +assert.eq( null, f.find( { a: 1, c: 1 } ).hint( { a: 1, b: 1 } ).explain().indexBounds.c ); start( { a: "a", b: 1 }, f.find( { a: /^a/, b: 1 } ).hint( { a: 1, b: 1 } ) ); start( { a: "a", b: 1 }, f.find( { a: /^a/, b: 1 } ).sort( { a: 1, b: 1 } ).hint( { a: 1, b: 1 } ) ); diff --git a/jstests/index_check2.js b/jstests/index_check2.js index a489fd6..eed3b8e 100644 --- a/jstests/index_check2.js +++ b/jstests/index_check2.js @@ -38,4 +38,4 @@ scanned3 = t.find(q3).explain().nscanned; assert( scanned3 <= Math.max( scanned1 , scanned2 ) , "$all makes query optimizer not work well" ); exp3 = t.find( q3 ).explain(); -assert.eq( exp3.indexBounds[0][0], exp3.indexBounds[0][1], "$all range not a single key" ); +assert.eq( exp3.indexBounds.tags[0][0], exp3.indexBounds.tags[0][1], "$all range not a single key" ); diff --git a/jstests/index_check6.js b/jstests/index_check6.js index 71e6420..240f4cf 100644 --- a/jstests/index_check6.js +++ b/jstests/index_check6.js @@ -12,6 +12,54 @@ for ( var age=10; age<50; age++ ){ assert.eq( 10 , t.find( { age : 30 } ).explain().nscanned , "A" ); assert.eq( 20 , t.find( { age : { $gte : 29 , $lte : 30 } } ).explain().nscanned , "B" ); +assert.eq( 12 , t.find( { age : { $gte : 25 , $lte : 30 }, rating: {$in: [0,9] } } ).explain().nscanned , "C1" ); + +assert.eq( 2 , t.find( { age : { $gte : 29 , $lte : 30 } , rating : 5 } ).explain().nscanned , "C" ); // SERVER-371 +assert.eq( 4 , t.find( { age : { $gte : 29 , $lte : 30 } , rating : { $gte : 4 , $lte : 5 } } ).explain().nscanned , "D" ); // SERVER-371 + +assert.eq.automsg( "2", "t.find( { age:30, rating:{ $gte:4, $lte:5} } ).explain().nscanned" ); + +t.drop(); + +for ( var a=1; a<10; a++ ){ + for ( var b=0; b<10; b++ ){ + for ( var c=0; c<10; c++ ) { + t.save( { a:a, b:b, c:c } ); + } + } +} + +function doTest( s ) { + sort = s; +assert.eq.automsg( "1", "t.find( { a:5, b:5, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "2", "t.find( { a:5, b:5, c:{$gte:5,$lte:6} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "1", "t.find( { a:5, b:5, c:{$gte:5.5,$lte:6} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "1", "t.find( { a:5, b:5, c:{$gte:5,$lte:5.5} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "3", "t.find( { a:5, b:5, c:{$gte:5,$lte:7} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "2", "t.find( { a:5, b:{$gte:5,$lte:6}, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "1", "t.find( { a:5, b:{$gte:5.5,$lte:6}, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "1", "t.find( { a:5, b:{$gte:5,$lte:5.5}, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "3", "t.find( { a:5, b:{$gte:5,$lte:7}, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "2", "t.find( { a:{$gte:5,$lte:6}, b:5, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "1", "t.find( { a:{$gte:5.5,$lte:6}, b:5, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "1", "t.find( { a:{$gte:5,$lte:5.5}, b:5, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "3", "t.find( { a:{$gte:5,$lte:7}, b:5, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "4", "t.find( { a:{$gte:5,$lte:6}, b:5, c:{$gte:5,$lte:6} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "2", "t.find( { a:{$gte:5.5,$lte:6}, b:5, c:{$gte:5,$lte:6} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "4", "t.find( { a:5, b:{$gte:5,$lte:6}, c:{$gte:5,$lte:6} } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "4", "t.find( { a:{$gte:5,$lte:6}, b:{$gte:5,$lte:6}, c:5 } ).sort( sort ).explain().nscanned" ); +assert.eq.automsg( "8", "t.find( { a:{$gte:5,$lte:6}, b:{$gte:5,$lte:6}, c:{$gte:5,$lte:6} } ).sort( sort ).explain().nscanned" ); +} + +for ( var a = -1; a <= 1; a += 2 ) { + for( var b = -1; b <= 1; b += 2 ) { + for( var c = -1; c <= 1; c += 2 ) { + t.dropIndexes(); + var spec = {a:a,b:b,c:c}; + t.ensureIndex( spec ); + doTest( spec ); + doTest( {a:-a,b:-b,c:-c} ); + } + } +} -//assert.eq( 2 , t.find( { age : { $gte : 29 , $lte : 30 } , rating : 5 } ).explain().nscanned , "C" ); // SERVER-371 -//assert.eq( 4 , t.find( { age : { $gte : 29 , $lte : 30 } , rating : { $gte : 4 , $lte : 5 } } ).explain().nscanned , "D" ); // SERVER-371 diff --git a/jstests/index_check8.js b/jstests/index_check8.js new file mode 100644 index 0000000..bc267df --- /dev/null +++ b/jstests/index_check8.js @@ -0,0 +1,15 @@ + +t = db.index_check8 +t.drop(); + +t.insert( { a : 1 , b : 1 , c : 1 , d : 1 , e : 1 } ) +t.ensureIndex( { a : 1 , b : 1 , c : 1 } ) +t.ensureIndex( { a : 1 , b : 1 , d : 1 , e : 1 } ) + +x = t.find( { a : 1 , b : 1 , d : 1 } ).sort( { e : 1 } ).explain() +assert( ! x.scanAndOrder , "A : " + tojson( x ) ) + +x = t.find( { a : 1 , b : 1 , c : 1 , d : 1 } ).sort( { e : 1 } ).explain() +//assert( ! x.scanAndOrder , "B : " + tojson( x ) ) + + diff --git a/jstests/index_elemmatch1.js b/jstests/index_elemmatch1.js new file mode 100644 index 0000000..425807a --- /dev/null +++ b/jstests/index_elemmatch1.js @@ -0,0 +1,28 @@ + +t = db.index_elemmatch1 +t.drop() + +x = 0 +y = 0 +for ( a=0; a<100; a++ ){ + for ( b=0; b<100; b++ ){ + t.insert( { a : a , b : b % 10 , arr : [ { x : x++ % 10 , y : y++ % 10 } ] } ) + } +} + +t.ensureIndex( { a : 1 , b : 1 } ) +t.ensureIndex( { "arr.x" : 1 , a : 1 } ) + +assert.eq( 100 , t.find( { a : 55 } ).itcount() , "A1" ); +assert.eq( 10 , t.find( { a : 55 , b : 7 } ).itcount() , "A2" ); + +q = { a : 55 , b : { $in : [ 1 , 5 , 8 ] } } +assert.eq( 30 , t.find( q ).itcount() , "A3" ) + +q.arr = { $elemMatch : { x : 5 , y : 5 } } +assert.eq( 10 , t.find( q ).itcount() , "A4" ) + +assert.eq( t.find(q).itcount() , t.find(q).explain().nscanned , "A5" ) + + + diff --git a/jstests/index_many.js b/jstests/index_many.js index 9960afa..46705a2 100644 --- a/jstests/index_many.js +++ b/jstests/index_many.js @@ -1,34 +1,51 @@ -t = db.many; +/* test using lots of indexes on one collection */ -t.drop(); -db.many2.drop(); +t = db.many; -t.save({x:9}); -t.save({x:19}); +function f() { + + t.drop(); + db.many2.drop(); + + t.save({ x: 9, y : 99 }); + t.save({ x: 19, y : 99 }); + + x = 2; + while (x < 70) { + patt = {}; + patt[x] = 1; + if (x == 20) + patt = { x: 1 }; + if (x == 64) + patt = { y: 1 }; + t.ensureIndex(patt); + x++; + } + + // print( tojson(db.getLastErrorObj()) ); + assert(db.getLastError(), "should have got an error 'too many indexes'"); + + // 40 is the limit currently + lim = t.getIndexes().length; + if (lim != 64) { + print("# of indexes should be 64 but is : " + lim); + return; + } + assert(lim == 64, "not 64 indexes"); + + assert(t.find({ x: 9 }).length() == 1, "b"); + assert(t.find({ x: 9 }).explain().cursor.match(/Btree/), "not using index?"); + + assert(t.find({ y: 99 }).length() == 2, "y idx"); + assert(t.find({ y: 99 }).explain().cursor.match(/Btree/), "not using y index?"); + + /* check that renamecollection remaps all the indexes right */ + assert(t.renameCollection("many2").ok, "rename failed"); + assert(t.find({ x: 9 }).length() == 0, "many2a"); + assert(db.many2.find({ x: 9 }).length() == 1, "many2b"); + assert(t.find({ y: 99 }).length() == 0, "many2c"); + assert(db.many2.find({ y: 99 }).length() == 2, "many2d"); -x = 2; -while( x < 60 ) { - patt={}; - patt[x] = 1; - if( x == 20 ) - patt = { x : 1 }; - t.ensureIndex(patt); - x++; } -// print( tojson(db.getLastErrorObj()) ); -assert( db.getLastError(), "should have an error 'too many indexes'" ); - -// 40 is the limit currently - -// print( t.getIndexes().length == 40, "40" ); - -assert( t.getIndexes().length == 40, "40" ); - -assert( t.find({x:9}).length() == 1, "b" ) ; - -t.renameCollection( "many2" ); - -assert( t.find({x:9}).length() == 0, "c" ) ; - -assert( db.many2.find({x:9}).length() == 1, "d" ) ; +f(); diff --git a/jstests/index_many2.js b/jstests/index_many2.js new file mode 100644 index 0000000..3fca5f5 --- /dev/null +++ b/jstests/index_many2.js @@ -0,0 +1,29 @@ + +t = db.index_many2; +t.drop() + +t.save( { x : 1 } ) + +assert.eq( 1 , t.getIndexKeys().length , "A1" ) + +function make( n ){ + var x = {} + x["x"+n] = 1; + return x; +} + +for ( i=1; i<1000; i++ ){ + t.ensureIndex( make(i) ); +} + +assert.eq( 64 , t.getIndexKeys().length , "A2" ) + + +num = t.getIndexKeys().length + +t.dropIndex( make(num-1) ) +assert.eq( num - 1 , t.getIndexKeys().length , "B0" ) + +t.ensureIndex( { z : 1 } ) +assert.eq( num , t.getIndexKeys().length , "B1" ) + diff --git a/jstests/indexapi.js b/jstests/indexapi.js index ae76ec7..1bbdf43 100644 --- a/jstests/indexapi.js +++ b/jstests/indexapi.js @@ -34,7 +34,7 @@ idx = t.getIndexes(); assert.eq( 2 , idx.length , "M1" ); assert.eq( key , idx[1].key , "M2" ); assert( idx[1].unique , "M3" ); -printjson( idx ); +//printjson( idx ); db.system.indexes.insert( { ns : "test" , key : { x : 1 } , name : "x" } ); assert( db.getLastError().indexOf( "invalid" ) >= 0 , "Z1" ); diff --git a/jstests/indexe.js b/jstests/indexe.js index 3170757..c08d117 100644 --- a/jstests/indexe.js +++ b/jstests/indexe.js @@ -12,7 +12,7 @@ assert.eq( num , t.find().count() ,"A1" ); assert.eq( num , t.find( { a : "b" } ).count() , "B1" ); assert.eq( num , t.find( { a : "b" } ).itcount() , "C1" ); -t.ensureIndex( { a : "b" } ); +t.ensureIndex( { a : 1 } ); assert.eq( num , t.find().count() ,"A2" ); assert.eq( num , t.find().sort( { a : 1 } ).count() , "A2a" ); diff --git a/jstests/indexh.js b/jstests/indexh.js new file mode 100644 index 0000000..c6aad18 --- /dev/null +++ b/jstests/indexh.js @@ -0,0 +1,34 @@ +// This should get skipped when testing replication + +t = db.jstests_indexh; + +function debug( t ) { + print( t ); +} + +// index extent freeing +t.drop(); +t.save( {} ); +var s1 = db.stats().dataSize; +debug( "s1: " + s1 ); +t.ensureIndex( {a:1} ); +var s2 = db.stats().dataSize; +debug( "s2: " + s2 ); +assert.automsg( "s1 < s2" ); +t.dropIndex( {a:1} ); +var s3 = db.stats().dataSize; +debug( "s3: " + s3 ); +assert.eq.automsg( "s1", "s3" ); + +// index node freeing +t.drop(); +t.ensureIndex( {a:1} ); +for( i = 'a'; i.length < 500; i += 'a' ) { + t.save( {a:i} ); +} +var s4 = db.stats().indexSize; +debug( "s4: " + s4 ); +t.remove( {} ); +var s5 = db.stats().indexSize; +debug( "s5: " + s5 ); +assert.automsg( "s5 < s4" ); \ No newline at end of file diff --git a/jstests/maxscan.js b/jstests/maxscan.js new file mode 100644 index 0000000..c455efb --- /dev/null +++ b/jstests/maxscan.js @@ -0,0 +1,14 @@ + +t = db.maxscan; +t.drop(); + +N = 100; +for ( i=0; i 0" ); + +assert.commandWorked( m.getDB( "local" ).repairDatabase() ); +assert.automsg( "c <= m.getDB( 'local' ).oplog.$main.count()" ); diff --git a/jstests/repl/replacePeer2.js b/jstests/repl/replacePeer2.js index f519b17..c2983dc 100644 --- a/jstests/repl/replacePeer2.js +++ b/jstests/repl/replacePeer2.js @@ -44,8 +44,16 @@ doTest = function( signal ) { checkWrite( rp.master(), rp.slave() ); // allow slave to finish initial sync - assert.soon( function() { return 1 == rp.slave().getDB( "admin" ).runCommand( {replacepeer:1} ).ok; } ); - + assert.soon( + function() { + var res = rp.slave().getDB( "admin" ).runCommand( {replacepeer:1} ); + if ( res.ok == 1 ) + return true; + printjson( res ); + return false; + } + ); + // Should not be saved to slave. writeOne( rp.master() ); // Make sure there would be enough time to save to l if we hadn't called replacepeer. @@ -81,3 +89,5 @@ doTest = function( signal ) { doTest( 15 ); // SIGTERM doTest( 9 ); // SIGKILL + +print("replace2Peer finishes"); diff --git a/jstests/repl/snapshot2.js b/jstests/repl/snapshot2.js index 4ebd786..d65cad7 100644 --- a/jstests/repl/snapshot2.js +++ b/jstests/repl/snapshot2.js @@ -13,12 +13,13 @@ rp = new ReplPair( l, r, a ); rp.start(); rp.waitForSteadyState(); -big = new Array( 2000 ).toString(); +big = new Array( 2000 ).toString(); // overflow oplog, so test can't pass supriously rp.slave().setSlaveOk(); -for( i = 0; i < 1000; ++i ) { +for( i = 0; i < 500; ++i ) { rp.master().getDB( baseName )[ baseName ].save( { _id: new ObjectId(), i: i, b: big } ); if ( i % 250 == 249 ) { assert.soon( function() { return i+1 == rp.slave().getDB( baseName )[ baseName ].count(); } ); + sleep( 10 ); // give master a chance to grab a sync point - have such small oplogs the master log might overflow otherwise } } @@ -40,11 +41,11 @@ rp.left_.extraArgs_ = [ "--fastsync" ]; rp.start( true ); rp.waitForSteadyState(); -assert.eq( 1000, rp.master().getDB( baseName )[ baseName ].count() ); +assert.eq( 500, rp.master().getDB( baseName )[ baseName ].count() ); rp.slave().setSlaveOk(); -assert.eq( 1000, rp.slave().getDB( baseName )[ baseName ].count() ); -rp.master().getDB( baseName )[ baseName ].save( {i:1000} ); -assert.soon( function() { return 1001 == rp.slave().getDB( baseName )[ baseName ].count(); } ); +assert.eq( 500, rp.slave().getDB( baseName )[ baseName ].count() ); +rp.master().getDB( baseName )[ baseName ].save( {i:500} ); +assert.soon( function() { return 501 == rp.slave().getDB( baseName )[ baseName ].count(); } ); assert( !rawMongoProgramOutput().match( /resync/ ) ); assert( !rawMongoProgramOutput().match( /SyncException/ ) ); \ No newline at end of file diff --git a/jstests/repl/snapshot3.js b/jstests/repl/snapshot3.js index 296ebd0..d8d268d 100644 --- a/jstests/repl/snapshot3.js +++ b/jstests/repl/snapshot3.js @@ -13,12 +13,13 @@ rp = new ReplPair( l, r, a ); rp.start(); rp.waitForSteadyState(); -big = new Array( 2000 ).toString(); +big = new Array( 2000 ).toString(); // overflow oplog, so test can't pass supriously rp.slave().setSlaveOk(); -for( i = 0; i < 1000; ++i ) { +for( i = 0; i < 500; ++i ) { rp.master().getDB( baseName )[ baseName ].save( { _id: new ObjectId(), i: i, b: big } ); if ( i % 250 == 249 ) { assert.soon( function() { return i+1 == rp.slave().getDB( baseName )[ baseName ].count(); } ); + sleep( 10 ); // give master a chance to grab a sync point - have such small oplogs the master log might overflow otherwise } } @@ -40,11 +41,13 @@ rp.left_.extraArgs_ = [ "--fastsync" ]; rp.start( true ); rp.waitForSteadyState(); -assert.eq( 1000, rp.master().getDB( baseName )[ baseName ].count() ); +assert.eq( 500, rp.master().getDB( baseName )[ baseName ].count() ); rp.slave().setSlaveOk(); -assert.eq( 1000, rp.slave().getDB( baseName )[ baseName ].count() ); -rp.master().getDB( baseName )[ baseName ].save( {i:1000} ); -assert.soon( function() { return 1001 == rp.slave().getDB( baseName )[ baseName ].count(); } ); +assert.eq( 500, rp.slave().getDB( baseName )[ baseName ].count() ); +rp.master().getDB( baseName )[ baseName ].save( {i:500} ); +assert.soon( function() { return 501 == rp.slave().getDB( baseName )[ baseName ].count(); } ); assert( !rawMongoProgramOutput().match( /resync/ ) ); -assert( !rawMongoProgramOutput().match( /SyncException/ ) ); \ No newline at end of file +assert( !rawMongoProgramOutput().match( /SyncException/ ) ); + +print("snapshot3.js finishes"); diff --git a/jstests/replsets/replset1.js b/jstests/replsets/replset1.js new file mode 100644 index 0000000..6a18dff --- /dev/null +++ b/jstests/replsets/replset1.js @@ -0,0 +1,115 @@ +doTest = function( signal ) { + + // Test basic replica set functionality. + // -- Replication + // -- Failover + + // Replica set testing API + // Create a new replica set test. Specify set name and the number of nodes you want. + var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} ); + + // call startSet() to start each mongod in the replica set + // this returns a list of nodes + var nodes = replTest.startSet(); + + // Call initiate() to send the replSetInitiate command + // This will wait for initiation + replTest.initiate(); + + // Call getMaster to return a reference to the node that's been + // elected master. + var master = replTest.getMaster(); + + // Calling getMaster also makes available the liveNodes structure, + // which looks like this: + // liveNodes = {master: masterNode, + // slaves: [slave1, slave2] + // } + printjson(replTest.liveNodes); + + // Here's how you save something to master + master.getDB("foo").foo.save({a: 1000}); + + // This method will check the oplogs of the master + // and slaves in the set and wait until the change has replicated. + replTest.awaitReplication(); + + + cppconn = new Mongo( replTest.getURL() ).getDB( "foo" ); + assert.eq( 1000 , cppconn.foo.findOne().a , "cppconn 1" ); + + { + // check c++ finding other servers + var temp = replTest.getURL(); + temp = temp.substring( 0 , temp.lastIndexOf( "," ) ); + temp = new Mongo( temp ).getDB( "foo" ); + assert.eq( 1000 , temp.foo.findOne().a , "cppconn 1" ); + } + + + // Here's how to stop the master node + var master_id = replTest.getNodeId( master ); + replTest.stop( master_id ); + + // Now let's see who the new master is: + var new_master = replTest.getMaster(); + + // Is the new master the same as the old master? + var new_master_id = replTest.getNodeId( new_master ); + + assert( master_id != new_master_id, "Old master shouldn't be equal to new master." ); + + { + // this may fail since it has to reconnect + try { + cppconn.foo.findOne() + } + catch ( e ){ + } + assert.eq( 1000 , cppconn.foo.findOne().a , "cppconn 2" ); + + } + + // Now let's write some documents to the new master + for(var i=0; i<1000; i++) { + new_master.getDB("bar").bar.save({a: i}); + } + new_master.getDB("admin").runCommand({getlasterror: 1}); + + // Here's how to restart the old master node: + slave = replTest.restart( master_id ); + + + // Now, let's make sure that the old master comes up as a slave + assert.soon(function() { + var res = slave.getDB("admin").runCommand({ismaster: 1}); + printjson(res); + return res['ok'] == 1 && res['ismaster'] == false; + }); + + // And we need to make sure that the replset comes back up + assert.soon(function() { + var res = new_master.getDB("admin").runCommand({replSetGetStatus: 1}); + printjson( res ); + return res.myState == 1; + }); + + // And that both slave nodes have all the updates + new_master = replTest.getMaster(); + assert.eq( 1000 , new_master.getDB( "bar" ).runCommand( { count:"bar"} ).n , "assumption 2") + replTest.awaitReplication(); + + slaves = replTest.liveNodes.slaves; + assert( slaves.length == 2, "Expected 2 slaves but length was " + slaves.length ); + slaves.forEach(function(slave) { + slave.setSlaveOk(); + var count = slave.getDB("bar").runCommand({count: "bar"}); + printjson( count ); + assert.eq( 1000 , count.n , "slave count wrong: " + slave ); + }); + + // Shut down the set and finish the test. + replTest.stopSet( signal ); +} + +doTest( 15 ); diff --git a/jstests/replsets/replset2.js b/jstests/replsets/replset2.js new file mode 100644 index 0000000..eaa35ee --- /dev/null +++ b/jstests/replsets/replset2.js @@ -0,0 +1,111 @@ + +doTest = function( signal ) { + + // FAILING TEST + // See below: + + // Test replication with getLastError + + // Replica set testing API + // Create a new replica set test. Specify set name and the number of nodes you want. + var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} ); + + // call startSet() to start each mongod in the replica set + // this returns a list of nodes + var nodes = replTest.startSet(); + + // Call initiate() to send the replSetInitiate command + // This will wait for initiation + replTest.initiate(); + + // Call getMaster to return a reference to the node that's been + // elected master. + var master = replTest.getMaster(); + + // Wait for replication to a single node + master.getDB("test").bar.insert({n: 1}); + + // Wait for initial sync + replTest.awaitReplication(); + + var slaves = replTest.liveNodes.slaves; + slaves.forEach(function(slave) { slave.setSlaveOk(); }); + + var testDB = "repl-test"; + + var failed = false; + var callGetLastError = function(w, timeout, db) { + var result = master.getDB(db).getLastErrorObj( w , timeout ); + printjson( result ); + if(result['ok'] != 1) { + print("FAILURE"); + failed = true; + } + } + + // Test getlasterror with multiple inserts + // TEST FAILS HERE + print("**** Try inserting a multiple records -- first insert ****") + master.getDB(testDB).foo.insert({n: 1}); + master.getDB(testDB).foo.insert({n: 2}); + master.getDB(testDB).foo.insert({n: 3}); + callGetLastError(3, 10000, testDB); + + print("**** TEMP 1a ****") + + m1 = master.getDB(testDB).foo.findOne({n: 1}); + printjson( m1 ); + assert( m1['n'] == 1 , "Failed to save to master on multiple inserts"); + + print("**** TEMP 1b ****") + + var s0 = slaves[0].getDB(testDB).foo.findOne({n: 1}); + assert( s0['n'] == 1 , "Failed to replicate to slave 0 on multiple inserts"); + + var s1 = slaves[1].getDB(testDB).foo.findOne({n: 1}); + assert( s1['n'] == 1 , "Failed to replicate to slave 1 on multiple inserts"); + + + // Test getlasterror with a simple insert + print("**** Try inserting a single record ****") + master.getDB(testDB).dropDatabase(); + master.getDB(testDB).foo.insert({n: 1}); + callGetLastError(3, 10000, testDB); + + m1 = master.getDB(testDB).foo.findOne({n: 1}); + printjson( m1 ); + assert( m1['n'] == 1 , "Failed to save to master"); + + + var s0 = slaves[0].getDB(testDB).foo.findOne({n: 1}); + assert( s0['n'] == 1 , "Failed to replicate to slave 0"); + + var s1 = slaves[1].getDB(testDB).foo.findOne({n: 1}); + assert( s1['n'] == 1 , "Failed to replicate to slave 1"); + + + // Test getlasterror with large insert + print("**** Try inserting many records ****") + bigData = new Array(2000).toString() + for(var n=0; n<1000; n++) { + master.getDB(testDB).baz.insert({n: n, data: bigData}); + } + callGetLastError(3, 60000, testDB); + + var verifyReplication = function(nodeName, collection) { + data = collection.findOne({n: 1}); + assert( data['n'] == 1 , "Failed to save to " + nodeName); + data = collection.findOne({n: 999}); + assert( data['n'] == 999 , "Failed to save to " + nodeName); + } + + verifyReplication("master", master.getDB(testDB).baz); + verifyReplication("slave 0", slaves[0].getDB(testDB).baz); + verifyReplication("slave 1", slaves[1].getDB(testDB).baz); + + assert( failed == false, "Replication with getLastError failed. See errors." ); + + replTest.stopSet( signal ); +} + +doTest( 15 ); diff --git a/jstests/replsets/replset3.js b/jstests/replsets/replset3.js new file mode 100644 index 0000000..8126b9d --- /dev/null +++ b/jstests/replsets/replset3.js @@ -0,0 +1,56 @@ + +doTest = function( signal ) { + + // Test replica set step down + + // Replica set testing API + // Create a new replica set test. Specify set name and the number of nodes you want. + var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} ); + + // call startSet() to start each mongod in the replica set + // this returns a list of nodes + var nodes = replTest.startSet(); + + // Call initiate() to send the replSetInitiate command + // This will wait for initiation + replTest.initiate(); + + // Get master node + var master = replTest.getMaster(); + + // Write some data to master + // NOTE: this test fails unless we write some data. + master.getDB("foo").foo.save({a: 1}); + master.getDB("foo").runCommand({getlasterror: 1, w:3, wtimeout: 20000}); + + // Step down master + master.getDB("admin").runCommand({replSetStepDown: true}); + + try { + var new_master = replTest.getMaster(); + } + catch( err ) { + throw( "Could not elect new master before timeout." ); + } + + assert( master != new_master, "Old master shouldn't be equal to new master." ); + + // Make sure that slaves are still up + var result = new_master.getDB("admin").runCommand({replSetGetStatus: 1}); + assert( result['ok'] == 1, "Could not verify that slaves were still up:" + result ); + + slaves = replTest.liveNodes.slaves; + assert.soon(function() { + res = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1}) + return res.myState == 2; + }, "Slave 0 state not ready."); + + assert.soon(function() { + res = slaves[1].getDB("admin").runCommand({replSetGetStatus: 1}) + return res.myState == 2; + }, "Slave 1 state not ready."); + + replTest.stopSet( 15 ); +} + +doTest( 15 ); diff --git a/jstests/replsets/replset4.js b/jstests/replsets/replset4.js new file mode 100644 index 0000000..4f6c454 --- /dev/null +++ b/jstests/replsets/replset4.js @@ -0,0 +1,29 @@ +doTest = function( signal ) { + + // Test orphaned master steps down + var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} ); + + replTest.startSet(); + replTest.initiate(); + + var master = replTest.getMaster(); + + // Kill both slaves, simulating a network partition + var slaves = replTest.liveNodes.slaves; + for(var i=0; i= 1, "count check"); + doWritesToKeep2(a); + + // A is 1 2 3 7 8 + // B is 1 2 3 4 5 6 + + // bring B back online + // as A is primary, B will roll back and then catch up + B.runCommand({ replSetTest: 1, blind: false }); + + wait(function () { return B.isMaster().ismaster || B.isMaster().secondary; }); + + // everyone is up here... + assert(A.isMaster().ismaster || A.isMaster().secondary, "A up"); + assert(B.isMaster().ismaster || B.isMaster().secondary, "B up"); + + verify(a); + + assert( dbs_match(a,b), "server data sets do not match after rollback, something is wrong"); + + pause("SUCCESS"); + replTest.stopSet(signal); +} + +doTest( 15 ); diff --git a/jstests/replsets/sync1.js b/jstests/replsets/sync1.js new file mode 100644 index 0000000..0f7754e --- /dev/null +++ b/jstests/replsets/sync1.js @@ -0,0 +1,192 @@ +// test rollback of replica sets + +var debugging=0; + +function pause(s) { + // for debugging just to keep processes running + print("\nsync1.js: " + s); + if (debugging) { + while (1) { + print("\nsync1.js: " + s); + sleep(4000); + } + } +} + +doTest = function (signal) { + + var replTest = new ReplSetTest({ name: 'testSet', nodes: 3 }); + var nodes = replTest.startSet({ oplogSize: "40" }); + + sleep(5000); + + print("\nsync1.js ********************************************************************** part 0"); + replTest.initiate(); + + // get master + print("\nsync1.js ********************************************************************** part 1"); + var master = replTest.getMaster(); + print("\nsync1.js ********************************************************************** part 2"); + var dbs = [master.getDB("foo")]; + + for (var i in nodes) { + if (nodes[i] + "" == master + "") { + continue; + } + dbs.push(nodes[i].getDB("foo")); + nodes[i].setSlaveOk(); + } + + print("\nsync1.js ********************************************************************** part 3"); + dbs[0].bar.drop(); + + print("\nsync1.js ********************************************************************** part 4"); + // slow things down a bit + dbs[0].bar.ensureIndex({ x: 1 }); + dbs[0].bar.ensureIndex({ y: 1 }); + dbs[0].bar.ensureIndex({ z: 1 }); + dbs[0].bar.ensureIndex({ w: 1 }); + + var ok = false; + var inserts = 100000; + + print("\nsync1.js ********************************************************************** part 5"); + + for (var i = 0; i < inserts; i++) { + dbs[0].bar.insert({ x: "foo" + i, y: "bar" + i, z: i, w: "biz baz bar boo" }); + } + + var status; + do { + sleep(1000); + status = dbs[0].getSisterDB("admin").runCommand({replSetGetStatus : 1}); + } while(status.members[1].state != 2 && status.members[2].state != 2); + + print("\nsync1.js ********************************************************************** part 6"); + dbs[0].getSisterDB("admin").runCommand({ replSetTest: 1, blind: true }); + + print("\nsync1.js ********************************************************************** part 7"); + + sleep(5000); + + // yay! there are out-of-date nodes + var max1; + var max2; + var count = 0; + while( 1 ) { + try { + max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next(); + max2 = dbs[2].bar.find().sort({ z: -1 }).limit(1).next(); + } + catch(e) { + print("\nsync1.js couldn't get max1/max2; retrying " + e); + sleep(2000); + count++; + if (count == 50) { + assert(false, "errored out 50 times"); + } + continue; + } + break; + } + + print("\nsync1.js ********************************************************************** part 8"); + + if (max1.z == (inserts-1) && max2.z == (inserts-1)) { + print("\nsync1.js try increasing # if inserts and running again"); + replTest.stopSet(signal); + return; + } + + // wait for a new master to be elected + sleep(5000); + + // figure out who is master now + var newMaster = replTest.getMaster(); + + print("\nsync1.js ********************************************************************** part 9"); + + print("\nsync1.js \nsync1.js ********************************************************************** part 9 **********************************************"); + assert(newMaster + "" != master + "", "new master is " + newMaster + ", old master was " + master); + print("\nsync1.js new master is " + newMaster + ", old master was " + master); + + count = 0; + do { + try { + max1 = dbs[1].bar.find().sort({ z: -1 }).limit(1).next(); + max2 = dbs[2].bar.find().sort({ z: -1 }).limit(1).next(); + } + catch( e ) { + print("\nsync1.js: exception querying; will sleep and try again " + e); + sleep(2000); + continue; + } + + print("\nsync1.js waiting for match " + count + " " + Date() + " z[1]:" + max1.z + " z[2]:" + max2.z); + + // printjson(max1); + // printjson(max2); + + sleep(2000); + + count++; + if (count == 100) { + pause("fail phase 1"); + assert(false, "replsets/\nsync1.js fails timing out"); + replTest.stopSet(signal); + return; + } + } while (max1.z != max2.z); + + // okay, now they're caught up. We have a max: + var max = max1.z; + + print("\nsync1.js ********************************************************************** part 10"); + + // now, let's see if rollback works + var result = dbs[0].getSisterDB("admin").runCommand({ replSetTest: 1, blind: false }); + dbs[0].getMongo().setSlaveOk(); + + printjson(result); + sleep(5000); + + // FAIL! This never resyncs + // now this should resync + print("\nsync1.js ********************************************************************** part 11"); + var max0 = null; + count = 0; + do { + try { + max0 = dbs[0].bar.find().sort({ z: -1 }).limit(1).next(); + } + catch(e) { + print("\nsync1.js part 11 exception on bar.find() will sleep and try again " + e); + sleep(2000); + continue; + } + + printjson(max); + printjson(max0); + print("\nsync1.js part 11 waiting for match " + count + " " + Date() + " z[0]:" + max0.z + " z:" + max); + + sleep(2000); + + count++; + if (count == 100) { + pause("fail part 11"); + assert(false, "replsets/\nsync1.js fails timing out"); + replTest.stopSet(signal); + return; + } + print("||||| count:" + count); + printjson(max0); + } while (! max0 || max0.z != max); + + print("\nsync1.js ********************************************************************** part 12"); + pause("\nsync1.js success"); + replTest.stopSet(signal); +} + +if( 1 || debugging ) { + doTest( 15 ); +} diff --git a/jstests/replsets/twosets.js b/jstests/replsets/twosets.js new file mode 100644 index 0000000..7cf367b --- /dev/null +++ b/jstests/replsets/twosets.js @@ -0,0 +1,36 @@ +// add a node from a different set to the current set +// I don't know what should happen here. + +doTest = function( signal ) { + + var orig = new ReplSetTest( {name: 'testSet', nodes: 3} ); + orig.startSet(); + + var interloper = new ReplSetTest( {name: 'testSet', nodes: 3, startPort : 31003} ); + interloper.startSet(); + + sleep(5000); + + orig.initiate(); + interloper.initiate(); + + sleep(5000); + + var master = orig.getMaster(); + + var conf = master.getDB("local").system.replset.findOne(); + + var nodes = interloper.nodeList(); + var host = nodes[0]; + var id = conf.members.length; + conf.members.push({_id : id, host : host}); + conf.version++; + + var result = master.getDB("admin").runCommand({replSetReconfig : conf}); + + // now... stuff should blow up? + + sleep(10); +} + +doTest(15); \ No newline at end of file diff --git a/jstests/rs/rs_basic.js b/jstests/rs/rs_basic.js new file mode 100644 index 0000000..08de689 --- /dev/null +++ b/jstests/rs/rs_basic.js @@ -0,0 +1,177 @@ +// rs_basic.js + +load("../../jstests/rs/test_framework.js"); + +function go() { + assert(__nextPort == 27000, "_nextPort==27000"); + + a = null; + try {init + a = new Mongo("localhost:27000"); + print("using already open mongod on port 27000 -- presume you are debugging or something. should start empty."); + __nextPort++; + } + catch (e) { + a = rs_mongod(); + } + + b = rs_mongod(); + + x = a.getDB("admin"); + y = b.getDB("admin"); + memb = []; + memb[0] = x; + memb[1] = y; + + print("rs_basic.js go(): started 2 servers"); + + cfg = { _id: 'asdf', members: [] }; + var hn = hostname(); + cfg.members[0] = { _id: 0, host: hn + ":27000" }; + cfg.members[1] = { _id: 1, host: hn + ":27001" }; + + print("cfg=" + tojson(cfg)); +} + +function init(server) { + var i = server; + //i = Random.randInt(2); // a random member of the set + var m = memb[i]; + assert(!m.ismaster(), "not ismaster"); + var res = m.runCommand({ replSetInitiate: cfg }); + return res; +} + +_path = '../../db/Debug/'; +print("_path var set to " + _path); + +print("go() to run"); +print("init() to initiate"); + + +/* +var rt = new ReplTest( "basic1" ); + +m = rt.start( true ); +s = rt.start( false ); + +function block(){ + am.runCommand( { getlasterror : 1 , w : 2 , wtimeout : 3000 } ) +} + +am = m.getDB( "foo" ); +as = s.getDB( "foo" ); + +function check( note ){ + var start = new Date(); + var x,y; + while ( (new Date()).getTime() - start.getTime() < 30000 ){ + x = am.runCommand( "dbhash" ); + y = as.runCommand( "dbhash" ); + if ( x.md5 == y.md5 ) + return; + sleep( 200 ); + } + assert.eq( x.md5 , y.md5 , note ); +} + +am.a.save( { x : 1 } ); +check( "A" ); + +am.a.save( { x : 5 } ); + +am.a.update( {} , { $inc : { x : 1 } } ); +check( "B" ); + +am.a.update( {} , { $inc : { x : 1 } } , false , true ); +check( "C" ); + +// ----- check features ------- + +// map/reduce +am.mr.insert( { tags : [ "a" ] } ) +am.mr.insert( { tags : [ "a" , "b" ] } ) +am.getLastError(); +check( "mr setup" ); + +m = function(){ + for ( var i=0; i counts[0] , "counts 1 : " + tojson( counts ) ) +sorted = counts.slice(0) +sorted.sort(); +assert.eq( counts , sorted , "counts 2 : " + tojson( counts ) ) + +print( counts ) +printjson( db.stats() ) s.stop(); diff --git a/jstests/sharding/auto2.js b/jstests/sharding/auto2.js index c6ec374..5ac9cd9 100644 --- a/jstests/sharding/auto2.js +++ b/jstests/sharding/auto2.js @@ -1,6 +1,6 @@ // auto2.js -s = new ShardingTest( "auto2" , 2 , 1 , 1 ); +s = new ShardingTest( "auto2" , 2 , 5 , 2 ); s.adminCommand( { enablesharding : "test" } ); s.adminCommand( { shardcollection : "test.foo" , key : { num : 1 } } ); @@ -26,19 +26,116 @@ for ( j=0; j<30; j++ ){ ) ); } +assert.eq( i , j * 100 , "setup" ); s.adminCommand( "connpoolsync" ); +db.getLastError(); print( "done inserting data" ); print( "datasize: " + tojson( s.getServer( "test" ).getDB( "admin" ).runCommand( { datasize : "test.foo" } ) ) ); s.printChunks(); -counta = s._connections[0].getDB( "test" ).foo.count(); -countb = s._connections[1].getDB( "test" ).foo.count(); +function doCountsGlobal(){ + counta = s._connections[0].getDB( "test" ).foo.count(); + countb = s._connections[1].getDB( "test" ).foo.count(); + return counta + countb; +} + +doCountsGlobal() + +assert( counta > 0 , "diff1" ); +assert( countb > 0 , "diff2" ); + +print( "checkpoint B" ) + +var missing = []; + +for ( i=0; i 0 ) + s += ","; + s += o.name; + } + return s; +} + +assert.eq( "allan,bob,eliot,joe,mark,sara" , nameString( db.foo.find().sort( { name : 1 } ) ) , "sort 1" ); +assert.eq( "sara,mark,joe,eliot,bob,allan" , nameString( db.foo.find().sort( { name : -1 } ) ) , "sort 2" ); + +assert.eq( 2 , db.foo.find().limit(2).itcount() , "LS1" ) +assert.eq( 2 , db.foo.find().skip(2).limit(2).itcount() , "LS2" ) +assert.eq( 1 , db.foo.find().skip(5).limit(2).itcount() , "LS3" ) +assert.eq( 6 , db.foo.find().limit(2).count() , "LSC1" ) +assert.eq( 2 , db.foo.find().limit(2).size() , "LSC2" ) +assert.eq( 2 , db.foo.find().skip(2).limit(2).size() , "LSC3" ) +assert.eq( 1 , db.foo.find().skip(5).limit(2).size() , "LSC4" ) + +assert.eq( "allan,bob" , nameString( db.foo.find().sort( { name : 1 } ).limit(2) ) , "LSD1" ) +assert.eq( "bob,eliot" , nameString( db.foo.find().sort( { name : 1 } ).skip(1).limit(2) ) , "LSD2" ) +assert.eq( "joe,mark" , nameString( db.foo.find().sort( { name : 1 } ).skip(3).limit(2) ) , "LSD3" ) + +assert.eq( "eliot,sara" , nameString( db.foo.find().sort( { _id : 1 } ).limit(2) ) , "LSE1" ) +assert.eq( "sara,bob" , nameString( db.foo.find().sort( { _id : 1 } ).skip(1).limit(2) ) , "LSE2" ) +assert.eq( "joe,mark" , nameString( db.foo.find().sort( { _id : 1 } ).skip(3).limit(2) ) , "LSE3" ) + +for ( i=0; i<10; i++ ){ + db.foo.save( { _id : 7 + i , name : "zzz" + i } ) +} + +assert.eq( 10 , db.foo.find( { name : { $gt : "z" } } ).itcount() , "LSF1" ) +assert.eq( 10 , db.foo.find( { name : { $gt : "z" } } ).sort( { _id : 1 } ).itcount() , "LSF2" ) +assert.eq( 5 , db.foo.find( { name : { $gt : "z" } } ).sort( { _id : 1 } ).skip(5).itcount() , "LSF3" ) +sleep( 5000 ) +assert.eq( 3 , db.foo.find( { name : { $gt : "z" } } ).sort( { _id : 1 } ).skip(5).limit(3).itcount() , "LSF4" ) s.stop(); diff --git a/jstests/sharding/count2.js b/jstests/sharding/count2.js new file mode 100644 index 0000000..2d9507e --- /dev/null +++ b/jstests/sharding/count2.js @@ -0,0 +1,43 @@ +// count2.js + +s1 = new ShardingTest( "count2" , 2 , 1 , 2 ); +s2 = s1._mongos[1]; + +s1.adminCommand( { enablesharding: "test" } ); +s1.adminCommand( { shardcollection: "test.foo" , key : { name : 1 } } ); + +db1 = s1.getDB( "test" ).foo; +db2 = s2.getDB( "test" ).foo; + +assert.eq( 1, s1.config.chunks.count(), "sanity check A"); + +db1.save( { name : "aaa" } ) +db1.save( { name : "bbb" } ) +db1.save( { name : "ccc" } ) +db1.save( { name : "ddd" } ) +db1.save( { name : "eee" } ) +db1.save( { name : "fff" } ) + +s1.adminCommand( { split : "test.foo" , middle : { name : "ddd" } } ); + +assert.eq( 3, db1.count( { name : { $gte: "aaa" , $lt: "ddd" } } ) , "initial count mongos1" ); +assert.eq( 3, db2.count( { name : { $gte: "aaa" , $lt: "ddd" } } ) , "initial count mongos2" ); + +s1.printChunks( "test.foo" ) + +s1.adminCommand( { movechunk : "test.foo" , find : { name : "aaa" } , to : s1.getOther( s1.getServer( "test" ) ).name } ); + +assert.eq( 3, db1.count( { name : { $gte: "aaa" , $lt: "ddd" } } ) , "post count mongos1" ); + +// The second mongos still thinks its shard mapping is valid and accepts a cound +print( "before sleep: " + Date() ) +sleep( 2000 ) +print( "after sleep: " + Date() ) +s1.printChunks( "test.foo" ) +assert.eq( 3, db2.find( { name : { $gte: "aaa" , $lt: "ddd" } } ).count() , "post count mongos2" ); + +db2.findOne(); + +assert.eq( 3, db2.count( { name : { $gte: "aaa" , $lt: "ddd" } } ) ); + +s1.stop(); diff --git a/jstests/sharding/cursor1.js b/jstests/sharding/cursor1.js new file mode 100644 index 0000000..2a30936 --- /dev/null +++ b/jstests/sharding/cursor1.js @@ -0,0 +1,60 @@ +// cursor1.js +// checks that cursors survive a chunk's move + +s = new ShardingTest( "sharding_cursor1" , 2 , 2 ) + +// take the balancer out of the equation +s.config.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true ); +s.config.settings.find().forEach( printjson ) + +// create a sharded 'test.foo', for the moment with just one chunk +s.adminCommand( { enablesharding: "test" } ); +s.adminCommand( { shardcollection: "test.foo", key: { _id: 1 } } ) + +db = s.getDB( "test" ); +primary = s.getServer( "test" ).getDB( "test" ); +secondary = s.getOther( primary ).getDB( "test" ); + +numObjs = 10; +for (i=0; i < numObjs; i++){ + db.foo.insert({_id: i}); +} +db.getLastError(); +assert.eq( 1, s.config.chunks.count() , "test requires collection to have one chunk initially" ); + +// we'll split the collection in two and move the second chunk while three cursors are open +// cursor1 still has more data in the first chunk, the one that didn't move +// cursor2 buffered the last obj of the first chunk +// cursor3 buffered data that was moved on the second chunk +var cursor1 = db.foo.find().batchSize( 3 ); +assert.eq( 3 , cursor1.objsLeftInBatch() ); +var cursor2 = db.foo.find().batchSize( 5 ); +assert.eq( 5 , cursor2.objsLeftInBatch() ); +var cursor3 = db.foo.find().batchSize( 7 ); +assert.eq( 7 , cursor3.objsLeftInBatch() ); + +s.adminCommand( { split: "test.foo" , middle : { _id : 5 } } ); +s.adminCommand( { movechunk : "test.foo" , find : { _id : 5 } , to : secondary.getMongo().name } ); +assert.eq( 2, s.config.chunks.count() ); + +// the cursors should not have been affected +assert.eq( numObjs , cursor1.itcount() , "c1" ); +assert.eq( numObjs , cursor2.itcount() , "c2" ); +assert.eq( numObjs , cursor3.itcount() , "c3" ); + +// test timeout +gc(); gc(); +cur = db.foo.find().batchSize( 2 ) +assert( cur.next() , "T1" ) +assert( cur.next() , "T2" ); +before = db.runCommand( { "cursorInfo" : 1 , "setTimeout" : 10000 } ) // 10 seconds +printjson( before ) +sleep( 6000 ) +assert( cur.next() , "T3" ) +assert( cur.next() , "T4" ); +sleep( 22000 ) +assert.throws( function(){ cur.next(); } , "T5" ) +after = db.runCommand( { "cursorInfo" : 1 , "setTimeout" : 10000 } ) // 10 seconds +gc(); gc() + +s.stop() diff --git a/jstests/sharding/diffservers1.js b/jstests/sharding/diffservers1.js index 6497bc0..31fd75a 100644 --- a/jstests/sharding/diffservers1.js +++ b/jstests/sharding/diffservers1.js @@ -14,7 +14,7 @@ assert( 3 , test1.count() ); assert( ! s.admin.runCommand( { addshard: "sdd$%" } ).ok , "bad hostname" ); assert( ! s.admin.runCommand( { addshard: "127.0.0.1:43415" } ).ok , "host not up" ); -assert( ! s.admin.runCommand( { addshard: "127.0.0.1:43415" , allowLocal : true } ).ok , "host not up" ); +assert( ! s.admin.runCommand( { addshard: "10.0.0.1:43415" } ).ok , "allowed shard in IP when config is localhost" ); s.stop(); diff --git a/jstests/sharding/error1.js b/jstests/sharding/error1.js index b4db9c3..e1aae06 100644 --- a/jstests/sharding/error1.js +++ b/jstests/sharding/error1.js @@ -18,19 +18,21 @@ assert( db.getLastError() , "gle22" ); s.adminCommand( { shardcollection : "test.foo2" , key : { num : 1 } } ); -db.foo2.insert( { _id : 1 , num : 5 } ); -db.foo2.insert( { _id : 2 , num : 10 } ); -db.foo2.insert( { _id : 3 , num : 15 } ); -db.foo2.insert( { _id : 4 , num : 20 } ); +db.foo2.save( { _id : 1 , num : 5 } ); +db.foo2.save( { _id : 2 , num : 10 } ); +db.foo2.save( { _id : 3 , num : 15 } ); +db.foo2.save( { _id : 4 , num : 20 } ); s.adminCommand( { split : "test.foo2" , middle : { num : 10 } } ); s.adminCommand( { movechunk : "test.foo2" , find : { num : 20 } , to : s.getOther( s.getServer( "test" ) ).name } ); +print( "a: " + a.foo2.count() ); +print( "b: " + b.foo2.count() ); assert( a.foo2.count() > 0 && a.foo2.count() < 4 , "se1" ); assert( b.foo2.count() > 0 && b.foo2.count() < 4 , "se2" ); assert.eq( 4 , db.foo2.count() , "se3" ); -db.foo2.insert( { _id : 5 , num : 25 } ); +db.foo2.save( { _id : 5 , num : 25 } ); assert( ! db.getLastError() , "se3.5" ); s.sync(); assert.eq( 5 , db.foo2.count() , "se4" ); @@ -43,5 +45,17 @@ assert( db.getLastError() , "se6" ); assert.eq( 5 , db.foo2.count() , "se5" ); + +// assert in mongos +s.adminCommand( { shardcollection : "test.foo3" , key : { num : 1 } } ); +assert.isnull(db.getLastError() , "gle C1" ); + +db.foo3.insert({}); //this fails with no shard key error +assert(db.getLastError() , "gle C2a" ); +assert(db.getLastError() , "gle C2b" ); + +db.foo3.insert({num:1}); +assert.isnull(db.getLastError() , "gle C3a" ); + // ---- s.stop(); diff --git a/jstests/sharding/features1.js b/jstests/sharding/features1.js index d2f692a..05b8b8c 100644 --- a/jstests/sharding/features1.js +++ b/jstests/sharding/features1.js @@ -50,10 +50,15 @@ s.sync(); assert.eq( 4 , a.foo.getIndexKeys().length , "a index 3" ); assert.eq( 4 , b.foo.getIndexKeys().length , "b index 3" ); +db.foo.ensureIndex( { num : 1 , bar : 1 } , true ); +s.sync(); +assert.eq( 5 , b.foo.getIndexKeys().length , "c index 3" ); + // ---- can't shard thing with unique indexes db.foo2.ensureIndex( { a : 1 } ); s.sync(); +printjson( db.system.indexes.find( { ns : "test.foo2" } ).toArray() ); assert( s.admin.runCommand( { shardcollection : "test.foo2" , key : { num : 1 } } ).ok , "shard with index" ); db.foo3.ensureIndex( { a : 1 } , true ); @@ -61,6 +66,12 @@ s.sync(); printjson( db.system.indexes.find( { ns : "test.foo3" } ).toArray() ); assert( ! s.admin.runCommand( { shardcollection : "test.foo3" , key : { num : 1 } } ).ok , "shard with unique index" ); +db.foo7.ensureIndex( { num : 1 , a : 1 } , true ); +s.sync(); +printjson( db.system.indexes.find( { ns : "test.foo7" } ).toArray() ); +assert( s.admin.runCommand( { shardcollection : "test.foo7" , key : { num : 1 } } ).ok , "shard with ok unique index" ); + + // ----- eval ----- db.foo2.save( { num : 5 , a : 7 } ); @@ -83,6 +94,7 @@ s.adminCommand( { split : "test.foo4" , middle : { num : 10 } } ); s.adminCommand( { movechunk : "test.foo4" , find : { num : 20 } , to : s.getOther( s.getServer( "test" ) ).name } ); db.foo4.save( { num : 5 } ); db.foo4.save( { num : 15 } ); +db.getLastError(); s.sync(); assert.eq( 1 , a.foo4.count() , "ua1" ); assert.eq( 1 , b.foo4.count() , "ub1" ); @@ -120,13 +132,15 @@ assert( ! s.admin.runCommand( { shardcollection : "test.foo5" , key : { num : 1 db.foo6.save( { a : 1 } ); db.foo6.save( { a : 3 } ); db.foo6.save( { a : 3 } ); +db.foo6.ensureIndex( { a : 1 } ); s.sync(); +printjson( db.system.indexes.find( { ns : "test.foo6" } ).toArray() ); assert.eq( 2 , db.foo6.group( { key : { a : 1 } , initial : { count : 0 } , reduce : function(z,prev){ prev.count++; } } ).length ); assert.eq( 3 , db.foo6.find().count() ); -assert( s.admin.runCommand( { shardcollection : "test.foo6" , key : { a : 2 } } ).ok ); +assert( s.admin.runCommand( { shardcollection : "test.foo6" , key : { a : 1 } } ).ok ); assert.eq( 3 , db.foo6.find().count() ); s.adminCommand( { split : "test.foo6" , middle : { a : 2 } } ); @@ -135,5 +149,16 @@ s.adminCommand( { movechunk : "test.foo6" , find : { a : 3 } , to : s.getOther( assert.throws( function(){ db.foo6.group( { key : { a : 1 } , initial : { count : 0 } , reduce : function(z,prev){ prev.count++; } } ); } );; +// ---- can't shard non-empty collection without index ----- + +db.foo8.save( { a : 1 } ); +assert( ! s.admin.runCommand( { shardcollection : "test.foo8" , key : { a : 1 } } ).ok , "non-empty collection" ); + +// --- listDatabases --- + +r = db.getMongo().getDBs() +assert.eq( 4 , r.databases.length , "listDatabases 1 : " + tojson( r ) ) +assert.lt( 10000 , r.totalSize , "listDatabases 2 : " + tojson( r ) ); + s.stop() diff --git a/jstests/sharding/features2.js b/jstests/sharding/features2.js index 47fedc8..dfb2883 100644 --- a/jstests/sharding/features2.js +++ b/jstests/sharding/features2.js @@ -13,6 +13,7 @@ db = s.getDB( "test" ); db.foo.save( { x : 1 } ); db.foo.save( { x : 2 } ); db.foo.save( { x : 3 } ); +db.foo.ensureIndex( { x : 1 } ); assert.eq( "1,2,3" , db.foo.distinct( "x" ) , "distinct 1" ); assert( a.foo.distinct("x").length == 3 || b.foo.distinct("x").length == 3 , "distinct 2" ); @@ -51,25 +52,27 @@ assert.eq( 0 , db.foo.count() , "D7" ); // --- _id key --- -db.foo2.insert( { _id : new ObjectId() } ); -db.foo2.insert( { _id : new ObjectId() } ); -db.foo2.insert( { _id : new ObjectId() } ); +db.foo2.save( { _id : new ObjectId() } ); +db.foo2.save( { _id : new ObjectId() } ); +db.foo2.save( { _id : new ObjectId() } ); +db.getLastError(); assert.eq( 1 , s.onNumShards( "foo2" ) , "F1" ); +printjson( db.system.indexes.find( { ns : "test.foo2" } ).toArray() ); s.adminCommand( { shardcollection : "test.foo2" , key : { _id : 1 } } ); assert.eq( 3 , db.foo2.count() , "F2" ) db.foo2.insert( {} ); assert.eq( 4 , db.foo2.count() , "F3" ) - // --- map/reduce db.mr.save( { x : 1 , tags : [ "a" , "b" ] } ); db.mr.save( { x : 2 , tags : [ "b" , "c" ] } ); db.mr.save( { x : 3 , tags : [ "c" , "a" ] } ); db.mr.save( { x : 4 , tags : [ "b" , "c" ] } ); +db.mr.ensureIndex( { x : 1 } ); m = function(){ this.tags.forEach( @@ -88,8 +91,12 @@ r = function( key , values ){ }; doMR = function( n ){ + print(n); + var res = db.mr.mapReduce( m , r ); printjson( res ); + assert.eq( new NumberLong(4) , res.counts.input , "MR T0 " + n ); + var x = db[res.result]; assert.eq( 3 , x.find().count() , "MR T1 " + n ); @@ -111,4 +118,42 @@ assert.eq( 2 , s.onNumShards( "mr" ) , "E1" ); doMR( "after" ); +s.adminCommand({split:'test.mr' , middle:{x:3}} ); +s.adminCommand({split:'test.mr' , middle:{x:4}} ); +s.adminCommand({movechunk:'test.mr', find:{x:3}, to: s.getServer('test').name } ); + +doMR( "after extra split" ); + +cmd = { mapreduce : "mr" , map : "emit( " , reduce : "fooz + " }; + +x = db.runCommand( cmd ); +y = s._connections[0].getDB( "test" ).runCommand( cmd ); + +printjson( x ) +printjson( y ) + +// count + +db.countaa.save({"regex" : /foo/i}) +db.countaa.save({"regex" : /foo/i}) +db.countaa.save({"regex" : /foo/i}) +assert.eq( 3 , db.countaa.count() , "counta1" ); +assert.eq( 3 , db.countaa.find().itcount() , "counta1" ); + +x = null; y = null; +try { + x = db.runCommand( "forceerror" ) +} +catch ( e ){ + x = e; +} +try { + y = s._connections[0].getDB( "test" ).runCommand( "forceerror" ); +} +catch ( e ){ + y = e; +} + +assert.eq( x , y , "assert format" ) + s.stop(); diff --git a/jstests/sharding/features3.js b/jstests/sharding/features3.js new file mode 100644 index 0000000..4ab75ee --- /dev/null +++ b/jstests/sharding/features3.js @@ -0,0 +1,86 @@ + +s = new ShardingTest( "features3" , 2 , 1 , 1 ); +s.adminCommand( { enablesharding : "test" } ); + +a = s._connections[0].getDB( "test" ); +b = s._connections[1].getDB( "test" ); + +db = s.getDB( "test" ); + +// ---------- load some data ----- + +s.adminCommand( { shardcollection : "test.foo" , key : { _id : 1 } } ); +N = 10000; +s.adminCommand( { split : "test.foo" , middle : { _id : N/2 } } ) +s.adminCommand( { moveChunk : "test.foo", find : { _id : 3 } ,to : s.getNonPrimaries( "test" )[0] } ) + +for ( i=0; i= 0 , "fsync not on admin should fail : " + tojson( x ) ) + +x = db._adminCommand( "fsync" ) +assert( x.ok == 1 && x.numFiles > 0 , "fsync failed : " + tojson( x ) ) + +x = db._adminCommand( { "fsync" :1, lock:true } ) +assert( ! x.ok , "lock should fail: " + tojson( x ) ) + +s.stop() diff --git a/jstests/sharding/findandmodify1.js b/jstests/sharding/findandmodify1.js index 774701f..437ec81 100644 --- a/jstests/sharding/findandmodify1.js +++ b/jstests/sharding/findandmodify1.js @@ -1,53 +1,51 @@ -s = new ShardingTest( "find_and_modify_sharded" , 2 ); +s = new ShardingTest( "find_and_modify_sharded" , 2 , 2); s.adminCommand( { enablesharding : "test" } ); db = s.getDB( "test" ); primary = s.getServer( "test" ).getDB( "test" ); -seconday = s.getOther( primary ).getDB( "test" ); +secondary = s.getOther( primary ).getDB( "test" ); numObjs = 20; s.adminCommand( { shardcollection : "test.stuff" , key : {_id:1} } ); +// pre-split the collection so to avoid interference from balancer +s.adminCommand( { split: "test.stuff" , middle : { _id : numObjs/2 } } ); +s.adminCommand( { movechunk : "test.stuff" , find : { _id : numObjs/2 } , to : secondary.getMongo().name } ) ; + for (var i=0; i < numObjs; i++){ db.stuff.insert({_id: i}); } +db.getLastError() -for (var i=0; i < numObjs; i+=2){ +// put two docs in each chunk (avoid the split in 0, since there are no docs less than 0) +for (var i=2; i < numObjs; i+=2){ + if (i == numObjs/2) + continue; s.adminCommand( { split: "test.stuff" , middle : {_id: i} } ); } -for (var i=0; i < numObjs; i+=4){ - s.adminCommand( { movechunk : "test.stuff" , find : {_id: i} , to : seconday.getMongo().name } ); -} - -//sorted update -for (var i=0; i < numObjs; i++){ - assert.eq(db.stuff.count({a:1}), i, "1 A"); - - var out = db.stuff.findAndModify({query: {a:null}, update: {$set: {a:1}}, sort: {_id:1}}); - - assert.eq(db.stuff.count({a:1}), i+1, "1 B"); - assert.eq(db.stuff.findOne({_id:i}).a, 1, "1 C"); - assert.eq(out._id, i, "1 D"); -} +s.printChunks(); +assert.eq( numObjs/2, s.config.chunks.count(), "split failed" ); +assert.eq( numObjs/4, s.config.chunks.count({ shard: "shard0000" }) ); +assert.eq( numObjs/4, s.config.chunks.count({ shard: "shard0001" }) ); -// unsorted update +// update for (var i=0; i < numObjs; i++){ assert.eq(db.stuff.count({b:1}), i, "2 A"); - var out = db.stuff.findAndModify({query: {b:null}, update: {$set: {b:1}}}); + var out = db.stuff.findAndModify({query: {_id:i, b:null}, update: {$set: {b:1}}}); + assert.eq(out._id, i, "2 E"); assert.eq(db.stuff.count({b:1}), i+1, "2 B"); - assert.eq(db.stuff.findOne({_id:out._id}).a, 1, "2 C"); } -//sorted remove (no query) +// remove for (var i=0; i < numObjs; i++){ assert.eq(db.stuff.count(), numObjs - i, "3 A"); assert.eq(db.stuff.count({_id: i}), 1, "3 B"); - var out = db.stuff.findAndModify({remove: true, sort: {_id:1}}); + var out = db.stuff.findAndModify({remove: true, query: {_id:i}}); assert.eq(db.stuff.count(), numObjs - i - 1, "3 C"); assert.eq(db.stuff.count({_id: i}), 0, "3 D"); diff --git a/jstests/sharding/key_many.js b/jstests/sharding/key_many.js index d1644ac..1e0ba9d 100644 --- a/jstests/sharding/key_many.js +++ b/jstests/sharding/key_many.js @@ -1,14 +1,18 @@ // key_many.js // values have to be sorted +// you must have exactly 6 values in each array types = [ { name : "string" , values : [ "allan" , "bob" , "eliot" , "joe" , "mark" , "sara" ] , keyfield: "k" } , { name : "double" , values : [ 1.2 , 3.5 , 4.5 , 4.6 , 6.7 , 9.9 ] , keyfield : "a" } , { name : "date" , values : [ new Date( 1000000 ) , new Date( 2000000 ) , new Date( 3000000 ) , new Date( 4000000 ) , new Date( 5000000 ) , new Date( 6000000 ) ] , keyfield : "a" } , { name : "string_id" , values : [ "allan" , "bob" , "eliot" , "joe" , "mark" , "sara" ] , keyfield : "_id" }, - { name : "embedded" , values : [ "allan" , "bob" , "eliot" , "joe" , "mark" , "sara" ] , keyfield : "a.b" } , + { name : "embedded 1" , values : [ "allan" , "bob" , "eliot" , "joe" , "mark" , "sara" ] , keyfield : "a.b" } , { name : "embedded 2" , values : [ "allan" , "bob" , "eliot" , "joe" , "mark" , "sara" ] , keyfield : "a.b.c" } , { name : "object" , values : [ {a:1, b:1.2}, {a:1, b:3.5}, {a:1, b:4.5}, {a:2, b:1.2}, {a:2, b:3.5}, {a:2, b:4.5} ] , keyfield : "o" } , + { name : "compound" , values : [ {a:1, b:1.2}, {a:1, b:3.5}, {a:1, b:4.5}, {a:2, b:1.2}, {a:2, b:3.5}, {a:2, b:4.5} ] , keyfield : "o" , compound : true } , + { name : "oid_id" , values : [ ObjectId() , ObjectId() , ObjectId() , ObjectId() , ObjectId() , ObjectId() ] , keyfield : "_id" } , + { name : "oid_other" , values : [ ObjectId() , ObjectId() , ObjectId() , ObjectId() , ObjectId() , ObjectId() ] , keyfield : "o" } , ] s = new ShardingTest( "key_many" , 2 ); @@ -20,7 +24,18 @@ seconday = s.getOther( primary ).getDB( "test" ); function makeObjectDotted( v ){ var o = {}; - o[curT.keyfield] = v; + if (curT.compound){ + var prefix = curT.keyfield + '.'; + if (typeof(v) == 'object'){ + for (key in v) + o[prefix + key] = v[key]; + } else { + for (key in curT.values[0]) + o[prefix + key] = v; + } + } else { + o[curT.keyfield] = v; + } return o; } @@ -39,6 +54,15 @@ function makeObject( v ){ return o; } +function makeInQuery(){ + if (curT.compound){ + // cheating a bit... + return {'o.a': {$in: [1,2]}}; + } else { + return makeObjectDotted({$in: curT.values}); + } +} + function getKey( o ){ var keys = curT.keyfield.split('.'); for(var i=0; i 0 ) + s += ","; + s += a[i]; + } + return s; +} + +forward = terse(forward); +backward = terse(backward); + +assert.eq( forward , getSorted( "num" , "num" , 1 ) , "D1" ) +assert.eq( backward , getSorted( "num" , "num" , -1 ) , "D2" ) + +assert.eq( backward , getSorted( "x" , "num" , 1 ) , "D3" ) +assert.eq( forward , getSorted( "x" , "num" , -1 ) , "D4" ) + +assert.eq( backward , getSorted( "x" , "num" , 1 , { num : 1 } ) , "D5" ) +assert.eq( forward , getSorted( "x" , "num" , -1 , { num : 1 } ) , "D6" ) + + +s.stop(); diff --git a/jstests/sharding/splitpick.js b/jstests/sharding/splitpick.js index ad27645..3733906 100644 --- a/jstests/sharding/splitpick.js +++ b/jstests/sharding/splitpick.js @@ -17,17 +17,23 @@ for ( var i=1; i<20; i++ ){ c.save( { a : i } ); } c.save( { a : 99 } ); +db.getLastError(); -assert.eq( s.admin.runCommand( { splitvalue : "test.foo" , find : { a : 1 } } ).middle.a , 1 , "splitvalue 1" ); -assert.eq( s.admin.runCommand( { splitvalue : "test.foo" , find : { a : 3 } } ).middle.a , 1 , "splitvalue 2" ); +function checkSplit( f, want , num ){ + x = s.admin.runCommand( { splitvalue : "test.foo" , find : { a : f } } ); + assert.eq( want, x.middle ? x.middle.a : null , "splitvalue " + num + " " + tojson( x ) ); +} + +checkSplit( 1 , 1 , "1" ) +checkSplit( 3 , 1 , "2" ) s.adminCommand( { split : "test.foo" , find : { a : 1 } } ); -assert.eq( s.admin.runCommand( { splitvalue : "test.foo" , find : { a : 3 } } ).middle.a , 99 , "splitvalue 3" ); +checkSplit( 3 , 99 , "3" ) s.adminCommand( { split : "test.foo" , find : { a : 99 } } ); assert.eq( s.config.chunks.count() , 3 ); s.printChunks(); -assert.eq( s.admin.runCommand( { splitvalue : "test.foo" , find : { a : 50 } } ).middle.a , 10 , "splitvalue 4 " ); +checkSplit( 50 , 10 , "4" ) s.stop(); diff --git a/jstests/sharding/stats.js b/jstests/sharding/stats.js new file mode 100644 index 0000000..c75d208 --- /dev/null +++ b/jstests/sharding/stats.js @@ -0,0 +1,60 @@ +s = new ShardingTest( "stats" , 2 , 1 , 1 ); +s.adminCommand( { enablesharding : "test" } ); + +a = s._connections[0].getDB( "test" ); +b = s._connections[1].getDB( "test" ); + +db = s.getDB( "test" ); + +function numKeys(o){ + var num = 0; + for (var x in o) + num++; + return num; +} + +// ---------- load some data ----- + +// need collections sharded before and after main collection for proper test +s.adminCommand( { shardcollection : "test.aaa" , key : { _id : 1 } } ); +s.adminCommand( { shardcollection : "test.foo" , key : { _id : 1 } } ); // this collection is actually used +s.adminCommand( { shardcollection : "test.zzz" , key : { _id : 1 } } ); + + +N = 10000; +s.adminCommand( { split : "test.foo" , middle : { _id : N/2 } } ) +s.adminCommand( { moveChunk : "test.foo", find : { _id : 3 } ,to : s.getNonPrimaries( "test" )[0] } ) + +for ( i=0; i 0 , "blah 1" ); -assert( s._connections[1].getDB( "test" ).foo.find().toArray().length > 0 , "blah 2" ); +assert( s._connections[0].getDB( "test" ).foo.find().toArray().length > 0 , "shard 0 request" ); +assert( s._connections[1].getDB( "test" ).foo.find().toArray().length > 0 , "shard 1 request" ); assert.eq( 7 , s._connections[0].getDB( "test" ).foo.find().toArray().length + - s._connections[1].getDB( "test" ).foo.find().toArray().length , "blah 3" ); + s._connections[1].getDB( "test" ).foo.find().toArray().length , "combined shards" ); assert.eq( 7 , s.getDB( "test" ).foo.find().toArray().length , "normal B" ); assert.eq( 7 , s2.getDB( "test" ).foo.find().toArray().length , "other B" ); @@ -45,4 +45,54 @@ for ( var i=0; i<10; i++ ){ assert.eq( 7 , s2.getDB( "test" ).foo.find().toArray().length , "other B " + i ); } +assert.eq( 0 , s.config.big.find().itcount() , "C1" ); +for ( i=0; i<50; i++ ){ + s.config.big.insert( { _id : i } ); +} +s.config.getLastError(); +assert.eq( 50 , s.config.big.find().itcount() , "C2" ); +assert.eq( 50 , s.config.big.find().count() , "C3" ); +assert.eq( 50 , s.config.big.find().batchSize(5).itcount() , "C4" ); + + +hashes = [] + +for ( i=0; i<3; i++ ){ + print( i ); + s._connections[i].getDB( "config" ).chunks.find( {} , { lastmod : 1 } ).forEach( printjsononeline ); + hashes[i] = s._connections[i].getDB( "config" ).runCommand( "dbhash" ); +} + +printjson( hashes ); + +for ( i=1; i>>>>>>>>>>>>>> skipping " + x.name); + return; + } + + // Notes: + + // apply_ops1: nothing works, dunno why yet. SERVER-1439 + + // copydb, copydb2: copyDatabase seems not to work at all in + // the ShardingTest setup. SERVER-1440 + + // cursor8: cursorInfo different/meaningless(?) in mongos + // closeAllDatabases may not work through mongos + // SERVER-1441 + // deal with cursorInfo in mongos SERVER-1442 + + // dbcase: Database names are case-insensitive under ShardingTest? + // SERVER-1443 + + // These are all SERVER-1444 + // count5: limit() and maybe skip() may be unreliable + // geo3: limit() not working, I think + // or4: skip() not working? + + // shellkillop: dunno yet. SERVER-1445 + + // These should simply not be run under sharding: + // dbadmin: Uncertain Cut-n-pasting its contents into mongo worked. + // error1: getpreverror not supported under sharding + // fsync, fsync2: isn't supported through mongos + // remove5: getpreverror, I think. don't run + // update4: getpreverror don't run + + // Around July 20, command passthrough went away, and these + // commands weren't implemented: + // clean cloneCollectionAsCapped copydbgetnonce dataSize + // datasize dbstats deleteIndexes dropIndexes forceerror + // getnonce logout medianKey profile reIndex repairDatabase + // reseterror splitVector validate + + /* missing commands : + * forceerror and switchtoclienterrors + * cloneCollectionAsCapped + * splitvector + * profile (apitest_db, cursor6, evalb) + * copydbgetnonce + * dbhash + * medianKey + * clean (apitest_dbcollection) + * logout and getnonce + */ + if (/[\/\\](error3|capped.*|splitvector|apitest_db|cursor6|copydb-auth|profile1|dbhash|median|apitest_dbcollection|evalb|auth1|auth2)\.js$/.test(x.name)) { + print(" !!!!!!!!!!!!!!! skipping test that has failed under sharding but might not anymore " + x.name) + return; + } + // These are bugs (some might be fixed now): + if (/[\/\\](apply_ops1|count5|cursor8|or4|shellkillop|update4)\.js$/.test(x.name)) { + print(" !!!!!!!!!!!!!!! skipping test that has failed under sharding but might not anymore " + x.name) + return; + } + // These aren't supposed to get run under sharding: + if (/[\/\\](dbadmin|error1|fsync|fsync2|geo.*|indexh|remove5|update4)\.js$/.test(x.name)) { + print(" >>>>>>>>>>>>>>> skipping test that would fail under sharding " + x.name) + return; + } + + print(" *******************************************"); + print(" Test : " + x.name + " ..."); + print(" " + Date.timeFunc( + function() { + load(x.name); + }, 1) + "ms"); + + } +); + + +var runnerEnd = new Date() + +print( "total runner time: " + ( ( runnerEnd.getTime() - runnerStart.getTime() ) / 1000 ) + "secs" ) diff --git a/jstests/slowNightly/sharding_balance1.js b/jstests/slowNightly/sharding_balance1.js new file mode 100644 index 0000000..840aaff --- /dev/null +++ b/jstests/slowNightly/sharding_balance1.js @@ -0,0 +1,55 @@ +// sharding_balance1.js + + +s = new ShardingTest( "slow_sharding_balance1" , 2 , 2 , 1 , { chunksize : 1 } ) + +s.adminCommand( { enablesharding : "test" } ); + +s.config.settings.find().forEach( printjson ) + +db = s.getDB( "test" ); + +bigString = "" +while ( bigString.length < 10000 ) + bigString += "asdasdasdasdadasdasdasdasdasdasdasdasda"; + +inserted = 0; +num = 0; +while ( inserted < ( 20 * 1024 * 1024 ) ){ + db.foo.insert( { _id : num++ , s : bigString } ); + inserted += bigString.length; +} + +db.getLastError(); +s.adminCommand( { shardcollection : "test.foo" , key : { _id : 1 } } ); +assert.lt( 20 , s.config.chunks.count() , "setup2" ); + +function diff(){ + var x = s.chunkCounts( "foo" ); + printjson( x ) + return Math.max( x.shard0000 , x.shard0001 ) - Math.min( x.shard0000 , x.shard0001 ); +} + +function sum(){ + var x = s.chunkCounts( "foo" ); + return x.shard0000 + x.shard0001; +} + +assert.lt( 20 , diff() , "big differential here" ); +print( diff() ) + +assert.soon( function(){ + var d = diff(); + return d < 5; +} , "balance didn't happen" , 1000 * 60 * 3 , 5000 ); + +var chunkCount = sum(); +s.adminCommand( { removeshard: "shard0000" } ); + +assert.soon( function(){ + printjson(s.chunkCounts( "foo" )); + s.config.shards.find().forEach(function(z){printjson(z);}); + return chunkCount == s.config.chunks.count({shard: "shard0001"}); +} , "removeshard didn't happen" , 1000 * 60 * 3 , 5000 ); + +s.stop(); diff --git a/jstests/slowNightly/sharding_balance2.js b/jstests/slowNightly/sharding_balance2.js new file mode 100644 index 0000000..c94e256 --- /dev/null +++ b/jstests/slowNightly/sharding_balance2.js @@ -0,0 +1,54 @@ +// sharding_balance2.js + +s = new ShardingTest( "slow_sharding_balance2" , 2 , 2 , 1 , { chunksize : 1 , manualAddShard : true } ) + +names = s.getConnNames(); +for ( var i=0; i .99 ){ + db.getLastError() + check(); // SERVER-1430 TODO + } + + var x = dist(); + if ( Math.random() > .999 ) + printjson( x ) + return Math.max( x.shard0000 , x.shard0001 ) - Math.min( x.shard0000 , x.shard0001 ); +} + +function sum(){ + var x = dist(); + return x.shard0000 + x.shard0001; +} + +assert.lt( 20 , diff() ,"initial load" ); +print( diff() ) + +assert.soon( function(){ + + var d = diff(); + return d < 5; +} , "balance didn't happen" , 1000 * 60 * 3 , 1 ); + + +s.stop(); diff --git a/jstests/slowNightly/sharding_cursors1.js b/jstests/slowNightly/sharding_cursors1.js new file mode 100644 index 0000000..307e8d7 --- /dev/null +++ b/jstests/slowNightly/sharding_cursors1.js @@ -0,0 +1,71 @@ +s = new ShardingTest( "cursors1" , 2 , 0 , 1 , { chunksize : 1 } ) + +s.adminCommand( { enablesharding : "test" } ); + +s.config.settings.find().forEach( printjson ) + +db = s.getDB( "test" ); + +bigString = "x" +while (bigString.length < 1024) + bigString += bigString; +assert.eq(bigString.length, 1024, 'len'); + +s.adminCommand( { shardcollection : "test.foo" , key : { _id : 1 } } ); + +toInsert = ( 1 * 1000 * 1000 ); +for (var i=0; i < toInsert; i++ ){ + db.foo.insert( { i: i, r: Math.random(), s: bigString } ); + assert.eq(db.getLastError(), null, 'no error'); //SERVER-1541 +} + +inserted = toInsert; +for (var i=0; i < 10; i++ ){ + //assert.gte(db.foo.count(), toInsert, 'inserted enough'); //sometimes fails + assert.gte(db.foo.count(), toInsert - 100, 'inserted enough'); + inserted = Math.min(inserted, db.foo.count()) + sleep (100); +} + +print("\n\n\n **** inserted: " + inserted + '\n\n\n'); + +/* + +var line = 0; +try { + assert.gte(db.foo.find({}, {_id:1}).itcount(), inserted, 'itcount check - no sort - _id only'); + line = 1; + assert.gte(db.foo.find({}, {_id:1}).sort({_id:1}).itcount(), inserted, 'itcount check - _id sort - _id only'); + line = 2; + + db.foo.ensureIndex({i:1}); + db.foo.ensureIndex({r:1}); + db.getLastError(); + line = 3; + + assert.gte(db.foo.find({}, {i:1}).sort({i:1}).itcount(), inserted, 'itcount check - i sort - i only'); + line = 4; + assert.gte(db.foo.find({}, {_id:1}).sort({i:1}).itcount(), inserted, 'itcount check - i sort - _id only'); + line = 5; + + assert.gte(db.foo.find({}, {r:1}).sort({r:1}).itcount(), inserted, 'itcount check - r sort - r only'); + line = 6; + assert.gte(db.foo.find({}, {_id:1}).sort({r:1}).itcount(), inserted, 'itcount check - r sort - _id only'); + line = 7; + + assert.gte(db.foo.find().itcount(), inserted, 'itcount check - no sort - full'); + line = 8; + assert.gte(db.foo.find().sort({_id:1}).itcount(), inserted, 'itcount check - _id sort - full'); + line = 9; + assert.gte(db.foo.find().sort({i:1}).itcount(), inserted, 'itcount check - i sort - full'); + line = 10; + assert.gte(db.foo.find().sort({r:1}).itcount(), inserted, 'itcount check - r sort - full'); + line = 11; +} catch (e) { + print("***** finished through line " + line + " before exception"); + throw e; +} + +*/ + +s.stop(); diff --git a/jstests/slowNightly/sharding_rs1.js b/jstests/slowNightly/sharding_rs1.js new file mode 100644 index 0000000..3769e32 --- /dev/null +++ b/jstests/slowNightly/sharding_rs1.js @@ -0,0 +1,61 @@ +// tests sharding with replica sets + +s = new ShardingTest( "rs1" , 3 , 1 , 2 , { rs : true , chunksize : 1 } ) + +s.adminCommand( { enablesharding : "test" } ); + +s.config.settings.find().forEach( printjson ) + +db = s.getDB( "test" ); + +bigString = "" +while ( bigString.length < 10000 ) + bigString += "asdasdasdasdadasdasdasdasdasdasdasdasda"; + +inserted = 0; +num = 0; +while ( inserted < ( 20 * 1024 * 1024 ) ){ + db.foo.insert( { _id : num++ , s : bigString } ); + inserted += bigString.length; +} + +db.getLastError(); +s.adminCommand( { shardcollection : "test.foo" , key : { _id : 1 } } ); +assert.lt( 20 , s.config.chunks.count() , "setup2" ); + +function diff(){ + var x = s.chunkCounts( "foo" ); + var total = 0; + var min = 1000000000; + var max = 0; + for ( var sn in x ){ + total += x[sn]; + if ( x[sn] < min ) + min = x[sn]; + if ( x[sn] > max ) + max = x[sn]; + } + + print( tojson(x) + " total: " + total + " min: " + min + " max: " + max ) + return max - min; +} + +assert.lt( 20 , diff() , "big differential here" ); +print( diff() ) + +assert.soon( function(){ + var d = diff(); + return d < 5; +} , "balance didn't happen" , 1000 * 60 * 3 , 5000 ); + + +for ( i=0; i 2000 ) + break; + + N *= 2; +} + +// --- test 1 + +assert.eq( 0, db.currentOp().inprog.length , "setup broken" ); + +join = startParallelShell( "print( 0 == db.query_yield1.find( function(){ var x=this.n; for ( var i=0; i<500; i++ ){ x = x * 2; } return false; } ).itcount() ); " ) + +assert.soon( + function(){ + var x = db.currentOp().inprog; + return x.length > 0; + } , "never doing query" , 2000 , 1 +); + +print( "start query" ); + +num = 0; +start = new Date(); +while ( ( (new Date()).getTime() - start ) < ( time * 2 ) ){ + var me = Date.timeFunc( function(){ t.insert( { x : 1 } ); db.getLastError(); } ) + var x = db.currentOp() + + if ( num++ == 0 ){ + assert.eq( 1 , x.inprog.length , "nothing in prog" ); + } + + assert.gt( 50 , me ); + + if ( x.inprog.length == 0 ) + break; + +} + +join(); + +var x = db.currentOp() +assert.eq( 0 , x.inprog.length , "weird 2" ); + diff --git a/jstests/slowWeekly/query_yield2.js b/jstests/slowWeekly/query_yield2.js new file mode 100644 index 0000000..e13fabe --- /dev/null +++ b/jstests/slowWeekly/query_yield2.js @@ -0,0 +1,73 @@ + +t = db.query_yield2; +t.drop() + +N = 100; +i = 0; + +q = function(){ var x=this.n; for ( var i=0; i<50000; i++ ){ x = x * 2; } return false; } + +while ( true ){ + function fill(){ + for ( ; i 2000 ) + break; + + N *= 2; +} + +// --- test 1 + +assert.eq( 0, db.currentOp().inprog.length , "setup broken" ); + +join = startParallelShell( "print( 0 == db.query_yield2.find( function(){ var x=this.n; for ( var i=0; i<50000; i++ ){ x = x * 2; } return false; } ).itcount() ); " ) + +assert.soon( + function(){ + var x = db.currentOp().inprog; + return x.length > 0; + } , "never doing query" , 2000 , 1 +); + +print( "start query" ); + +num = 0; +start = new Date(); +while ( ( (new Date()).getTime() - start ) < ( time * 2 ) ){ + var me = Date.timeFunc( function(){ t.insert( { x : 1 } ); db.getLastError(); } ) + var x = db.currentOp() + + if ( num++ == 0 ){ + assert.eq( 1 , x.inprog.length , "nothing in prog" ); + } + + assert.gt( 75 , me ); + + if ( x.inprog.length == 0 ) + break; + +} + +join(); + +var x = db.currentOp() +assert.eq( 0 , x.inprog.length , "weird 2" ); + diff --git a/jstests/slowWeekly/update_yield1.js b/jstests/slowWeekly/update_yield1.js new file mode 100644 index 0000000..2e63690 --- /dev/null +++ b/jstests/slowWeekly/update_yield1.js @@ -0,0 +1,78 @@ + +t = db.update_yield1; +t.drop() + +N = 10000; +i = 0; + +while ( true ){ + function fill(){ + for ( ; i 2000 ) + break; + + N *= 2; +} + +// --- test 1 + +join = startParallelShell( "db.update_yield1.update( {} , { $inc : { n : 1 } } , false , true ); db.getLastError()" ); + +assert.soon( + function(){ + return db.currentOp().inprog.length > 0; + } , "never doing update" +); + +num = 0; +start = new Date(); +while ( ( (new Date()).getTime() - start ) < ( time * 2 ) ){ + var me = Date.timeFunc( function(){ t.findOne(); } ); + + if ( num++ == 0 ){ + var x = db.currentOp() + assert.eq( 1 , x.inprog.length , "nothing in prog" ); + } + + assert.gt( 50 , me ); +} + +join(); + +var x = db.currentOp() +assert.eq( 0 , x.inprog.length , "weird 2" ); + +// --- test 2 + +join = startParallelShell( "db.update_yield1.update( { $atomic : true } , { $inc : { n : 1 } } , false , true ); db.getLastError()" ); + +assert.soon( + function(){ + return db.currentOp().inprog.length > 0; + } , "never doing update 2" +); + +t.findOne(); +var x = db.currentOp() +assert.eq( 0 , x.inprog.length , "should have been atomic" ); + +join(); diff --git a/jstests/splitvector.js b/jstests/splitvector.js new file mode 100644 index 0000000..8d86319 --- /dev/null +++ b/jstests/splitvector.js @@ -0,0 +1,81 @@ +// ------------------------- +// SPLITVECTOR TEST UTILS +// ------------------------- + +// ------------------------- +// assertChunkSizes verifies that a given 'splitVec' divides the 'test.jstest_splitvector' +// collection in 'maxChunkSize' approximately-sized chunks. Its asserts fail otherwise. +// @param splitVec: an array with keys for field 'x' +// e.g. [ { x : 1927 }, { x : 3855 }, ... +// @param numDocs: domain of 'x' field +// e.g. 20000 +// @param maxChunkSize is in MBs. +// +assertChunkSizes = function ( splitVec , numDocs , maxChunkSize ){ + splitVec = [{ x: -1 }].concat( splitVec ); + splitVec.push( { x: numDocs+1 } ); + for ( i=0; i