~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/mongo/dbtests/jstests.cpp

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
#include "pch.h"
21
 
#include "../db/instance.h"
 
21
 
 
22
#include "mongo/db/instance.h"
 
23
#include "mongo/scripting/engine.h"
 
24
#include "mongo/util/timer.h"
 
25
#include "mongo/dbtests/dbtests.h"
22
26
#include "mongo/db/json.h"
23
27
 
24
 
#include "../pch.h"
25
 
#include "../scripting/engine.h"
26
 
#include "../util/timer.h"
27
 
 
28
 
#include "dbtests.h"
29
 
 
30
28
namespace mongo {
31
29
    bool dbEval(const string& dbName , BSONObj& cmd, BSONObjBuilder& result, string& errmsg);
32
30
} // namespace mongo
33
31
 
34
32
namespace JSTests {
35
33
 
36
 
    class Fundamental {
 
34
    class BuiltinTests {
37
35
    public:
38
36
        void run() {
39
 
            // By calling JavaJSImpl() inside run(), we ensure the unit test framework's
40
 
            // signal handlers are pre-installed from JNI's perspective.  This allows
41
 
            // JNI to catch signals generated within the JVM and forward other signals
42
 
            // as appropriate.
43
 
            ScriptEngine::setup();
 
37
            // Run any tests included with the scripting engine
44
38
            globalScriptEngine->runTest();
45
39
        }
46
40
    };
48
42
    class BasicScope {
49
43
    public:
50
44
        void run() {
51
 
            auto_ptr<Scope> s;
 
45
            scoped_ptr<Scope> s;
52
46
            s.reset( globalScriptEngine->newScope() );
53
47
 
54
48
            s->setNumber( "x" , 5 );
63
57
            s->setBoolean( "b" , true );
64
58
            ASSERT( s->getBoolean( "b" ) );
65
59
 
66
 
            if ( 0 ) {
67
 
                s->setBoolean( "b" , false );
68
 
                ASSERT( ! s->getBoolean( "b" ) );
69
 
            }
 
60
            s->setBoolean( "b" , false );
 
61
            ASSERT( ! s->getBoolean( "b" ) );
70
62
        }
71
63
    };
72
64
 
73
65
    class ResetScope {
74
66
    public:
75
67
        void run() {
76
 
            // Not worrying about this for now SERVER-446.
77
 
            /*
 
68
            /* Currently reset does not clear data in v8 or spidermonkey scopes.  See SECURITY-10
78
69
            auto_ptr<Scope> s;
79
70
            s.reset( globalScriptEngine->newScope() );
80
71
 
90
81
    class FalseTests {
91
82
    public:
92
83
        void run() {
93
 
            Scope * s = globalScriptEngine->newScope();
94
 
 
95
 
            ASSERT( ! s->getBoolean( "x" ) );
96
 
 
97
 
            s->setString( "z" , "" );
98
 
            ASSERT( ! s->getBoolean( "z" ) );
99
 
 
100
 
 
101
 
            delete s ;
 
84
            // Test falsy javascript values
 
85
            scoped_ptr<Scope> s;
 
86
            s.reset( globalScriptEngine->newScope() );
 
87
 
 
88
            ASSERT( ! s->getBoolean( "notSet" ) );
 
89
 
 
90
            s->setString( "emptyString" , "" );
 
91
            ASSERT( ! s->getBoolean( "emptyString" ) );
 
92
 
 
93
            s->setNumber( "notANumberVal" , std::numeric_limits<double>::quiet_NaN());
 
94
            ASSERT( ! s->getBoolean( "notANumberVal" ) );
 
95
 
 
96
            s->setElement( "nullVal" , BSONObjBuilder().appendNull("null").obj().getField("null") );
 
97
            ASSERT( ! s->getBoolean( "nullVal" ) );
 
98
 
 
99
            s->setNumber( "zeroVal" , 0 );
 
100
            ASSERT( ! s->getBoolean( "zeroVal" ) );
102
101
        }
103
102
    };
104
103
 
111
110
            ASSERT( 5 == s->getNumber( "x" ) );
112
111
 
113
112
            s->invoke( "return 17;" , 0, 0 );
114
 
            ASSERT( 17 == s->getNumber( "return" ) );
 
113
            ASSERT( 17 == s->getNumber( "__returnValue" ) );
115
114
 
116
115
            s->invoke( "function(){ return 17; }" , 0, 0 );
117
 
            ASSERT( 17 == s->getNumber( "return" ) );
 
116
            ASSERT( 17 == s->getNumber( "__returnValue" ) );
118
117
 
119
118
            s->setNumber( "x" , 1.76 );
120
119
            s->invoke( "return x == 1.76; " , 0, 0 );
121
 
            ASSERT( s->getBoolean( "return" ) );
 
120
            ASSERT( s->getBoolean( "__returnValue" ) );
122
121
 
123
122
            s->setNumber( "x" , 1.76 );
124
123
            s->invoke( "return x == 1.79; " , 0, 0 );
125
 
            ASSERT( ! s->getBoolean( "return" ) );
 
124
            ASSERT( ! s->getBoolean( "__returnValue" ) );
126
125
 
127
126
            BSONObj obj = BSON( "" << 11.0 );
128
127
            s->invoke( "function( z ){ return 5 + z; }" , &obj, 0 );
129
 
            ASSERT_EQUALS( 16 , s->getNumber( "return" ) );
 
128
            ASSERT_EQUALS( 16 , s->getNumber( "__returnValue" ) );
130
129
 
131
130
            delete s;
132
131
        }
194
193
            ASSERT( !_logger.logged() );
195
194
 
196
195
            // An error is logged for an invalid statement.
197
 
            ASSERT_NOT_EQUALS( 0, scope->invoke( "notAFunction()", 0, 0 ) );
 
196
            try {
 
197
                scope->invoke( "notAFunction()", 0, 0 );
 
198
            }
 
199
            catch(const DBException&) {
 
200
                // ignore the exception; just test that we logged something
 
201
            }
198
202
            ASSERT( _logger.logged() );
199
203
        }
200
204
    private:
210
214
            s->setObject( "blah" , o );
211
215
 
212
216
            s->invoke( "return blah.x;" , 0, 0 );
213
 
            ASSERT_EQUALS( 17 , s->getNumber( "return" ) );
 
217
            ASSERT_EQUALS( 17 , s->getNumber( "__returnValue" ) );
214
218
            s->invoke( "return blah.y;" , 0, 0 );
215
 
            ASSERT_EQUALS( "eliot" , s->getString( "return" ) );
 
219
            ASSERT_EQUALS( "eliot" , s->getString( "__returnValue" ) );
216
220
 
217
221
            s->invoke( "return this.z;" , 0, &o );
218
 
            ASSERT_EQUALS( "sara" , s->getString( "return" ) );
 
222
            ASSERT_EQUALS( "sara" , s->getString( "__returnValue" ) );
219
223
 
220
224
            s->invoke( "return this.z == 'sara';" , 0, &o );
221
 
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
225
            ASSERT_EQUALS( true , s->getBoolean( "__returnValue" ) );
222
226
 
223
227
            s->invoke( "this.z == 'sara';" , 0, &o );
224
 
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
228
            ASSERT_EQUALS( true , s->getBoolean( "__returnValue" ) );
225
229
 
226
230
            s->invoke( "this.z == 'asara';" , 0, &o );
227
 
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
231
            ASSERT_EQUALS( false , s->getBoolean( "__returnValue" ) );
228
232
 
229
233
            s->invoke( "return this.x == 17;" , 0, &o );
230
 
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
234
            ASSERT_EQUALS( true , s->getBoolean( "__returnValue" ) );
231
235
 
232
236
            s->invoke( "return this.x == 18;" , 0, &o );
233
 
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
237
            ASSERT_EQUALS( false , s->getBoolean( "__returnValue" ) );
234
238
 
235
239
            s->invoke( "function(){ return this.x == 17; }" , 0, &o );
236
 
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
240
            ASSERT_EQUALS( true , s->getBoolean( "__returnValue" ) );
237
241
 
238
242
            s->invoke( "function(){ return this.x == 18; }" , 0, &o );
239
 
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
243
            ASSERT_EQUALS( false , s->getBoolean( "__returnValue" ) );
240
244
 
241
245
            s->invoke( "function (){ return this.x == 17; }" , 0, &o );
242
 
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
246
            ASSERT_EQUALS( true , s->getBoolean( "__returnValue" ) );
243
247
 
244
248
            s->invoke( "function z(){ return this.x == 18; }" , 0, &o );
245
 
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
249
            ASSERT_EQUALS( false , s->getBoolean( "__returnValue" ) );
246
250
 
247
251
            s->invoke( "function (){ this.x == 17; }" , 0, &o );
248
 
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
252
            ASSERT_EQUALS( false , s->getBoolean( "__returnValue" ) );
249
253
 
250
254
            s->invoke( "function z(){ this.x == 18; }" , 0, &o );
251
 
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
255
            ASSERT_EQUALS( false , s->getBoolean( "__returnValue" ) );
252
256
 
253
257
            s->invoke( "x = 5; for( ; x <10; x++){ a = 1; }" , 0, &o );
254
258
            ASSERT_EQUALS( 10 , s->getNumber( "x" ) );
399
403
                s->setObject( "x" , o );
400
404
 
401
405
                s->invoke( "return x.d.getTime() != 12;" , 0, 0 );
402
 
                ASSERT_EQUALS( true, s->getBoolean( "return" ) );
 
406
                ASSERT_EQUALS( true, s->getBoolean( "__returnValue" ) );
403
407
 
404
408
                s->invoke( "z = x.d.getTime();" , 0, 0 );
405
409
                ASSERT_EQUALS( 123456789 , s->getNumber( "z" ) );
448
452
                ASSERT_EQUALS( Array, out.firstElement().type() );
449
453
            }
450
454
 
 
455
            // symbol
 
456
            {
 
457
                // test mutable object with symbol type
 
458
                BSONObjBuilder builder;
 
459
                builder.appendSymbol("sym", "value");
 
460
                BSONObj in = builder.done();
 
461
                s->setObject( "x", in, false );
 
462
                BSONObj out = s->getObject( "x" );
 
463
                ASSERT_EQUALS( Symbol, out.firstElement().type() );
 
464
 
 
465
                // readonly
 
466
                s->setObject( "x", in, true );
 
467
                out = s->getObject( "x" );
 
468
                ASSERT_EQUALS( Symbol, out.firstElement().type() );
 
469
            }
 
470
 
451
471
            delete s;
452
472
        }
453
473
    };
507
527
 
508
528
            s->setObject( "z" , o );
509
529
            s->invoke( "return z" , 0, 0 );
510
 
            BSONObj out = s->getObject( "return" );
 
530
            BSONObj out = s->getObject( "__returnValue" );
511
531
            ASSERT_EQUALS( 5 , out["a"].number() );
512
532
            ASSERT_EQUALS( 5.6 , out["b"].number() );
513
533
 
525
545
 
526
546
            s->setObject( "z" , o , false );
527
547
            s->invoke( "return z" , 0, 0 );
528
 
            out = s->getObject( "return" );
 
548
            out = s->getObject( "__returnValue" );
529
549
            ASSERT_EQUALS( 5 , out["a"].number() );
530
550
            ASSERT_EQUALS( 5.6 , out["b"].number() );
531
551
 
575
595
//
576
596
//            s->setObject( "z" , o , false );
577
597
//            s->invoke( "return z" , BSONObj() );
578
 
//            out = s->getObject( "return" );
 
598
//            out = s->getObject( "__returnValue" );
579
599
//            ASSERT_EQUALS( 3 , out["a"].number() );
580
600
//            ASSERT_EQUALS( 4.5 , out["b"].number() );
581
601
//
751
771
        }
752
772
    };
753
773
 
 
774
    /**
 
775
     * Test exec() timeout value terminates execution (SERVER-8053)
 
776
     */
 
777
    class ExecTimeout {
 
778
    public:
 
779
        void run() {
 
780
            scoped_ptr<Scope> scope(globalScriptEngine->newScope());
 
781
            scope->localConnect("ExecTimeoutDB");
 
782
            // assert timeout occured
 
783
            ASSERT(!scope->exec("var a = 1; while (true) { ; }",
 
784
                                "ExecTimeout", false, true, false, 1));
 
785
        }
 
786
    };
 
787
 
 
788
    /**
 
789
     * Test exec() timeout value terminates execution (SERVER-8053)
 
790
     */
 
791
    class ExecNoTimeout {
 
792
    public:
 
793
        void run() {
 
794
            scoped_ptr<Scope> scope(globalScriptEngine->newScope());
 
795
            scope->localConnect("ExecNoTimeoutDB");
 
796
            // assert no timeout occured
 
797
            ASSERT(scope->exec("var a = function() { return 1; }",
 
798
                               "ExecNoTimeout", false, true, false, 5 * 60 * 1000));
 
799
        }
 
800
    };
 
801
 
 
802
    /**
 
803
     * Test invoke() timeout value terminates execution (SERVER-8053)
 
804
     */
 
805
    class InvokeTimeout {
 
806
    public:
 
807
        void run() {
 
808
            scoped_ptr<Scope> scope(globalScriptEngine->newScope());
 
809
            scope->localConnect("InvokeTimeoutDB");
 
810
 
 
811
            // scope timeout after 500ms
 
812
            bool caught = false;
 
813
            try {
 
814
                scope->invokeSafe("function() {         "
 
815
                                  "    while (true) { } "
 
816
                                  "}                    ",
 
817
                                  0, 0, 1);
 
818
            } catch (const DBException&) {
 
819
                caught = true;
 
820
            }
 
821
            ASSERT(caught);
 
822
        }
 
823
    };
 
824
 
 
825
    /**
 
826
     * Test invoke() timeout value does not terminate execution (SERVER-8053)
 
827
     */
 
828
    class InvokeNoTimeout {
 
829
    public:
 
830
        void run() {
 
831
            scoped_ptr<Scope> scope(globalScriptEngine->newScope());
 
832
            scope->localConnect("InvokeTimeoutDB");
 
833
 
 
834
            // invoke completes before timeout
 
835
            scope->invokeSafe("function() { "
 
836
                              "  for (var i=0; i<1; i++) { ; } "
 
837
                              "} ",
 
838
                              0, 0, 5 * 60 * 1000);
 
839
        }
 
840
    };
 
841
 
754
842
 
755
843
    void dummy_function_to_force_dbeval_cpp_linking() {
756
844
        BSONObj cmd;
867
955
        }
868
956
    };
869
957
 
870
 
    class DBRefTest {
871
 
    public:
872
 
        DBRefTest() {
873
 
            _a = "unittest.dbref.a";
874
 
            _b = "unittest.dbref.b";
875
 
            reset();
876
 
        }
877
 
        ~DBRefTest() {
878
 
            //reset();
879
 
        }
880
 
 
881
 
        void run() {
882
 
 
883
 
            client.insert( _a , BSON( "a" << "17" ) );
884
 
 
885
 
            {
886
 
                BSONObj fromA = client.findOne( _a , BSONObj() );
887
 
                verify( fromA.valid() );
888
 
                //cout << "Froma : " << fromA << endl;
889
 
                BSONObjBuilder b;
890
 
                b.append( "b" , 18 );
891
 
                b.appendDBRef( "c" , "dbref.a" , fromA["_id"].__oid() );
892
 
                client.insert( _b , b.obj() );
893
 
            }
894
 
 
895
 
            ASSERT( client.eval( "unittest" , "x = db.dbref.b.findOne(); assert.eq( 17 , x.c.fetch().a , 'ref working' );" ) );
896
 
 
897
 
            // BSON DBRef <=> JS DBPointer
898
 
            ASSERT( client.eval( "unittest", "x = db.dbref.b.findOne(); db.dbref.b.drop(); x.c = new DBPointer( x.c.ns, x.c.id ); db.dbref.b.insert( x );" ) );
899
 
            ASSERT_EQUALS( DBRef, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() );
900
 
 
901
 
            // BSON Object <=> JS DBRef
902
 
            ASSERT( client.eval( "unittest", "x = db.dbref.b.findOne(); db.dbref.b.drop(); x.c = new DBRef( x.c.ns, x.c.id ); db.dbref.b.insert( x );" ) );
903
 
            ASSERT_EQUALS( Object, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() );
904
 
            ASSERT_EQUALS( string( "dbref.a" ), client.findOne( "unittest.dbref.b", "" )[ "c" ].embeddedObject().getStringField( "$ref" ) );
905
 
        }
906
 
 
907
 
        void reset() {
908
 
            client.dropCollection( _a );
909
 
            client.dropCollection( _b );
910
 
        }
911
 
 
912
 
        const char * _a;
913
 
        const char * _b;
914
 
    };
915
 
 
916
 
    class InformalDBRef {
917
 
    public:
918
 
        void run() {
919
 
            client.insert( ns(), BSON( "i" << 1 ) );
920
 
            BSONObj obj = client.findOne( ns(), BSONObj() );
921
 
            client.remove( ns(), BSONObj() );
922
 
            client.insert( ns(), BSON( "r" << BSON( "$ref" << "jstests.informaldbref" << "$id" << obj["_id"].__oid() << "foo" << "bar" ) ) );
923
 
            obj = client.findOne( ns(), BSONObj() );
924
 
            ASSERT_EQUALS( "bar", obj[ "r" ].embeddedObject()[ "foo" ].str() );
925
 
 
926
 
            ASSERT( client.eval( "unittest", "x = db.jstests.informaldbref.findOne(); y = { r:x.r }; db.jstests.informaldbref.drop(); y.r[ \"a\" ] = \"b\"; db.jstests.informaldbref.save( y );" ) );
927
 
            obj = client.findOne( ns(), BSONObj() );
928
 
            ASSERT_EQUALS( "bar", obj[ "r" ].embeddedObject()[ "foo" ].str() );
929
 
            ASSERT_EQUALS( "b", obj[ "r" ].embeddedObject()[ "a" ].str() );
930
 
        }
931
 
    private:
932
 
        static const char *ns() { return "unittest.jstests.informaldbref"; }
933
 
    };
 
958
    namespace RoundTripTests {
 
959
 
 
960
        // Inherit from this class to test round tripping of JSON objects
 
961
        class TestRoundTrip {
 
962
        public:
 
963
            virtual ~TestRoundTrip() {}
 
964
            void run() {
 
965
 
 
966
                // Insert in Javascript -> Find using DBDirectClient
 
967
 
 
968
                // Drop the collection
 
969
                client.dropCollection( "unittest.testroundtrip" );
 
970
 
 
971
                // Insert in Javascript
 
972
                stringstream jsInsert;
 
973
                jsInsert << "db.testroundtrip.insert(" << jsonIn() << ")";
 
974
                ASSERT_TRUE( client.eval( "unittest" , jsInsert.str() ) );
 
975
 
 
976
                // Find using DBDirectClient
 
977
                BSONObj excludeIdProjection = BSON( "_id" << 0 );
 
978
                BSONObj directFind = client.findOne( "unittest.testroundtrip",
 
979
                                                                "",
 
980
                                                                &excludeIdProjection);
 
981
                bsonEquals( bson(), directFind );
 
982
 
 
983
 
 
984
                // Insert using DBDirectClient -> Find in Javascript
 
985
 
 
986
                // Drop the collection
 
987
                client.dropCollection( "unittest.testroundtrip" );
 
988
 
 
989
                // Insert using DBDirectClient
 
990
                client.insert( "unittest.testroundtrip" , bson() );
 
991
 
 
992
                // Find in Javascript
 
993
                stringstream jsFind;
 
994
                jsFind << "dbref = db.testroundtrip.findOne( { } , { _id : 0 } )\n"
 
995
                                << "assert.eq(dbref, " << jsonOut() << ")";
 
996
                ASSERT_TRUE( client.eval( "unittest" , jsFind.str() ) );
 
997
            }
 
998
        protected:
 
999
 
 
1000
            // Methods that must be defined by child classes
 
1001
            virtual BSONObj bson() const = 0;
 
1002
            virtual string json() const = 0;
 
1003
 
 
1004
            // This can be overriden if a different meaning of equality besides woCompare is needed
 
1005
            virtual void bsonEquals( const BSONObj &expected, const BSONObj &actual ) {
 
1006
                if ( expected.woCompare( actual ) ) {
 
1007
                    out() << "want:" << expected.jsonString() << " size: " << expected.objsize() << endl;
 
1008
                    out() << "got :" << actual.jsonString() << " size: " << actual.objsize() << endl;
 
1009
                    out() << expected.hexDump() << endl;
 
1010
                    out() << actual.hexDump() << endl;
 
1011
                }
 
1012
                ASSERT( !expected.woCompare( actual ) );
 
1013
            }
 
1014
 
 
1015
            // This can be overriden if the JSON representation is altered on the round trip
 
1016
            virtual string jsonIn() const {
 
1017
                return json();
 
1018
            }
 
1019
            virtual string jsonOut() const {
 
1020
                return json();
 
1021
            }
 
1022
        };
 
1023
 
 
1024
        class DBRefTest : public TestRoundTrip {
 
1025
            virtual BSONObj bson() const {
 
1026
                BSONObjBuilder b;
 
1027
                OID o;
 
1028
                memset( &o, 0, 12 );
 
1029
                BSONObjBuilder subBuilder(b.subobjStart("a"));
 
1030
                subBuilder.append("$ref", "ns");
 
1031
                subBuilder.append("$id", o);
 
1032
                subBuilder.done();
 
1033
                return b.obj();
 
1034
            }
 
1035
            virtual string json() const {
 
1036
                return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
 
1037
            }
 
1038
 
 
1039
            // A "fetch" function is added to the DBRef object when it is inserted using the
 
1040
            // constructor, so we need to compare the fields individually
 
1041
            virtual void bsonEquals( const BSONObj &expected, const BSONObj &actual ) {
 
1042
                ASSERT_EQUALS( expected["a"].type() , actual["a"].type() );
 
1043
                ASSERT_EQUALS( expected["a"]["$id"].OID() , actual["a"]["$id"].OID() );
 
1044
                ASSERT_EQUALS( expected["a"]["$ref"].String() , actual["a"]["$ref"].String() );
 
1045
            }
 
1046
        };
 
1047
 
 
1048
        class DBPointerTest : public TestRoundTrip {
 
1049
            virtual BSONObj bson() const {
 
1050
                BSONObjBuilder b;
 
1051
                OID o;
 
1052
                memset( &o, 0, 12 );
 
1053
                b.appendDBRef( "a" , "ns" , o );
 
1054
                return b.obj();
 
1055
            }
 
1056
            virtual string json() const {
 
1057
                return "{ \"a\" : DBPointer( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
 
1058
            }
 
1059
        };
 
1060
 
 
1061
        class InformalDBRefTest : public TestRoundTrip {
 
1062
            virtual BSONObj bson() const {
 
1063
                BSONObjBuilder b;
 
1064
                BSONObjBuilder subBuilder(b.subobjStart("a"));
 
1065
                subBuilder.append("$ref", "ns");
 
1066
                subBuilder.append("$id", "000000000000000000000000");
 
1067
                subBuilder.done();
 
1068
                return b.obj();
 
1069
            }
 
1070
 
 
1071
            // Don't need to return anything because we are overriding both jsonOut and jsonIn
 
1072
            virtual string json() const { return ""; }
 
1073
 
 
1074
            // Need to override these because the JSON doesn't actually round trip.
 
1075
            // An object with "$ref" and "$id" fields is handled specially and different on the way out.
 
1076
            virtual string jsonOut() const {
 
1077
                return "{ \"a\" : DBRef( \"ns\", \"000000000000000000000000\" ) }";
 
1078
            }
 
1079
            virtual string jsonIn() const {
 
1080
                stringstream ss;
 
1081
                ss << "{ \"a\" : { \"$ref\" : \"ns\" , " <<
 
1082
                                "\"$id\" : \"000000000000000000000000\" } }";
 
1083
                return ss.str();
 
1084
            }
 
1085
        };
 
1086
 
 
1087
        class InformalDBRefOIDTest : public TestRoundTrip {
 
1088
            virtual BSONObj bson() const {
 
1089
                BSONObjBuilder b;
 
1090
                OID o;
 
1091
                memset( &o, 0, 12 );
 
1092
                BSONObjBuilder subBuilder(b.subobjStart("a"));
 
1093
                subBuilder.append("$ref", "ns");
 
1094
                subBuilder.append("$id", o);
 
1095
                subBuilder.done();
 
1096
                return b.obj();
 
1097
            }
 
1098
 
 
1099
            // Don't need to return anything because we are overriding both jsonOut and jsonIn
 
1100
            virtual string json() const { return ""; }
 
1101
 
 
1102
            // Need to override these because the JSON doesn't actually round trip.
 
1103
            // An object with "$ref" and "$id" fields is handled specially and different on the way out.
 
1104
            virtual string jsonOut() const {
 
1105
                return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
 
1106
            }
 
1107
            virtual string jsonIn() const {
 
1108
                stringstream ss;
 
1109
                ss << "{ \"a\" : { \"$ref\" : \"ns\" , " <<
 
1110
                                "\"$id\" : ObjectId( \"000000000000000000000000\" ) } }";
 
1111
                return ss.str();
 
1112
            }
 
1113
        };
 
1114
 
 
1115
        class InformalDBRefExtraFieldTest : public TestRoundTrip {
 
1116
            virtual BSONObj bson() const {
 
1117
                BSONObjBuilder b;
 
1118
                OID o;
 
1119
                memset( &o, 0, 12 );
 
1120
                BSONObjBuilder subBuilder(b.subobjStart("a"));
 
1121
                subBuilder.append("$ref", "ns");
 
1122
                subBuilder.append("$id", o);
 
1123
                subBuilder.append("otherfield", "value");
 
1124
                subBuilder.done();
 
1125
                return b.obj();
 
1126
            }
 
1127
 
 
1128
            // Don't need to return anything because we are overriding both jsonOut and jsonIn
 
1129
            virtual string json() const { return ""; }
 
1130
 
 
1131
            // Need to override these because the JSON doesn't actually round trip.
 
1132
            // An object with "$ref" and "$id" fields is handled specially and different on the way out.
 
1133
            virtual string jsonOut() const {
 
1134
                return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
 
1135
            }
 
1136
            virtual string jsonIn() const {
 
1137
                stringstream ss;
 
1138
                ss << "{ \"a\" : { \"$ref\" : \"ns\" , " <<
 
1139
                                "\"$id\" : ObjectId( \"000000000000000000000000\" ) , " <<
 
1140
                                "\"otherfield\" : \"value\" } }";
 
1141
                return ss.str();
 
1142
            }
 
1143
        };
 
1144
 
 
1145
    } // namespace RoundTripTests
934
1146
 
935
1147
    class BinDataType {
936
1148
    public:
1021
1233
 
1022
1234
            Timer t;
1023
1235
            double n = 0;
1024
 
            for ( ; n < 100000; n++ ) {
 
1236
            for ( ; n < 10000 ; n++ ) {
1025
1237
                s->invoke( f , &empty, &start );
1026
 
                ASSERT_EQUALS( 11 , s->getNumber( "return" ) );
 
1238
                ASSERT_EQUALS( 11 , s->getNumber( "__returnValue" ) );
1027
1239
            }
1028
1240
            //cout << "speed1: " << ( n / t.millis() ) << " ops/ms" << endl;
1029
1241
        }
1100
1312
    class All : public Suite {
1101
1313
    public:
1102
1314
        All() : Suite( "js" ) {
 
1315
            // Initialize the Javascript interpreter
 
1316
            ScriptEngine::setup();
1103
1317
        }
1104
1318
 
1105
1319
        void setupTests() {
1106
 
            add< Fundamental >();
 
1320
            add< BuiltinTests >();
1107
1321
            add< BasicScope >();
1108
1322
            add< ResetScope >();
1109
1323
            add< FalseTests >();
1110
1324
            add< SimpleFunctions >();
1111
1325
            add< ExecLogError >();
1112
1326
            add< InvokeLogError >();
 
1327
            add< ExecTimeout >();
 
1328
            add< ExecNoTimeout >();
 
1329
            add< InvokeTimeout >();
 
1330
            add< InvokeNoTimeout >();
1113
1331
 
1114
1332
            add< ObjectMapping >();
1115
1333
            add< ObjectDecoding >();
1125
1343
 
1126
1344
            add< WeirdObjects >();
1127
1345
            add< CodeTests >();
1128
 
            add< DBRefTest >();
1129
 
            add< InformalDBRef >();
1130
1346
            add< BinDataType >();
1131
1347
 
1132
1348
            add< VarTests >();
1139
1355
 
1140
1356
            add< ScopeOut >();
1141
1357
            add< InvalidStoredJS >();
 
1358
 
 
1359
            add< RoundTripTests::DBRefTest >();
 
1360
            add< RoundTripTests::DBPointerTest >();
 
1361
            add< RoundTripTests::InformalDBRefTest >();
 
1362
            add< RoundTripTests::InformalDBRefOIDTest >();
 
1363
            add< RoundTripTests::InformalDBRefExtraFieldTest >();
1142
1364
        }
1143
1365
    } myall;
1144
1366