~ubuntu-branches/ubuntu/trusty/mongodb/trusty-proposed

« back to all changes in this revision

Viewing changes to dbtests/jstests.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Antonin Kral
  • Date: 2010-01-29 19:48:45 UTC
  • Revision ID: james.westby@ubuntu.com-20100129194845-8wbmkf626fwcavc9
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// javajstests.cpp 
 
2
//
 
3
 
 
4
/**
 
5
 *    Copyright (C) 2009 10gen Inc.
 
6
 *
 
7
 *    This program is free software: you can redistribute it and/or  modify
 
8
 *    it under the terms of the GNU Affero General Public License, version 3,
 
9
 *    as published by the Free Software Foundation.
 
10
 *
 
11
 *    This program is distributed in the hope that it will be useful,
 
12
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *    GNU Affero General Public License for more details.
 
15
 *
 
16
 *    You should have received a copy of the GNU Affero General Public License
 
17
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include "stdafx.h"
 
21
#include "../db/instance.h"
 
22
 
 
23
#include "../stdafx.h"
 
24
#include "../scripting/engine.h"
 
25
 
 
26
#include "dbtests.h"
 
27
 
 
28
namespace mongo {
 
29
    bool dbEval(const char *ns, BSONObj& cmd, BSONObjBuilder& result, string& errmsg);
 
30
} // namespace mongo
 
31
 
 
32
namespace JSTests {
 
33
    
 
34
    class Fundamental {
 
35
    public:
 
36
        void run() {
 
37
            // By calling JavaJSImpl() inside run(), we ensure the unit test framework's
 
38
            // signal handlers are pre-installed from JNI's perspective.  This allows
 
39
            // JNI to catch signals generated within the JVM and forward other signals
 
40
            // as appropriate.
 
41
            ScriptEngine::setup();
 
42
            globalScriptEngine->runTest();
 
43
        }
 
44
    };
 
45
    
 
46
    class BasicScope {
 
47
    public:
 
48
        void run(){
 
49
            auto_ptr<Scope> s;
 
50
            s.reset( globalScriptEngine->newScope() );
 
51
 
 
52
            s->setNumber( "x" , 5 );
 
53
            ASSERT( 5 == s->getNumber( "x" ) );
 
54
            
 
55
            s->setNumber( "x" , 1.67 );
 
56
            ASSERT( 1.67 == s->getNumber( "x" ) );
 
57
 
 
58
            s->setString( "s" , "eliot was here" );
 
59
            ASSERT( "eliot was here" == s->getString( "s" ) );
 
60
            
 
61
            s->setBoolean( "b" , true );
 
62
            ASSERT( s->getBoolean( "b" ) );
 
63
 
 
64
            if ( 0 ){
 
65
                s->setBoolean( "b" , false );
 
66
                ASSERT( ! s->getBoolean( "b" ) );
 
67
            }
 
68
        }
 
69
    };
 
70
 
 
71
    class ResetScope {
 
72
    public:
 
73
        void run(){
 
74
            // Not worrying about this for now SERVER-446.
 
75
            /*
 
76
            auto_ptr<Scope> s;
 
77
            s.reset( globalScriptEngine->newScope() );
 
78
            
 
79
            s->setBoolean( "x" , true );
 
80
            ASSERT( s->getBoolean( "x" ) );
 
81
 
 
82
            s->reset();
 
83
            ASSERT( !s->getBoolean( "x" ) );
 
84
            */
 
85
        }
 
86
    };
 
87
    
 
88
    class FalseTests {
 
89
    public:
 
90
        void run(){
 
91
            Scope * s = globalScriptEngine->newScope();
 
92
 
 
93
            ASSERT( ! s->getBoolean( "x" ) );
 
94
            
 
95
            s->setString( "z" , "" );
 
96
            ASSERT( ! s->getBoolean( "z" ) );
 
97
            
 
98
            
 
99
            delete s ;
 
100
        }
 
101
    };
 
102
 
 
103
    class SimpleFunctions {
 
104
    public:
 
105
        void run(){
 
106
            Scope * s = globalScriptEngine->newScope();
 
107
 
 
108
            s->invoke( "x=5;" , BSONObj() );
 
109
            ASSERT( 5 == s->getNumber( "x" ) );
 
110
            
 
111
            s->invoke( "return 17;" , BSONObj() );
 
112
            ASSERT( 17 == s->getNumber( "return" ) );
 
113
            
 
114
            s->invoke( "function(){ return 17; }" , BSONObj() );
 
115
            ASSERT( 17 == s->getNumber( "return" ) );
 
116
            
 
117
            s->setNumber( "x" , 1.76 );
 
118
            s->invoke( "return x == 1.76; " , BSONObj() );
 
119
            ASSERT( s->getBoolean( "return" ) );
 
120
 
 
121
            s->setNumber( "x" , 1.76 );
 
122
            s->invoke( "return x == 1.79; " , BSONObj() );
 
123
            ASSERT( ! s->getBoolean( "return" ) );
 
124
            
 
125
            s->invoke( "function( z ){ return 5 + z; }" , BSON( "" << 11 ) );
 
126
            ASSERT_EQUALS( 16 , s->getNumber( "return" ) );
 
127
 
 
128
            delete s;
 
129
        }
 
130
    };
 
131
 
 
132
    class ObjectMapping {
 
133
    public:
 
134
        void run(){
 
135
            Scope * s = globalScriptEngine->newScope();
 
136
            
 
137
            BSONObj o = BSON( "x" << 17 << "y" << "eliot" << "z" << "sara" );
 
138
            s->setObject( "blah" , o );
 
139
 
 
140
            s->invoke( "return blah.x;" , BSONObj() );
 
141
            ASSERT_EQUALS( 17 , s->getNumber( "return" ) );
 
142
            s->invoke( "return blah.y;" , BSONObj() );
 
143
            ASSERT_EQUALS( "eliot" , s->getString( "return" ) );
 
144
 
 
145
            s->setThis( & o );
 
146
            s->invoke( "return this.z;" , BSONObj() );
 
147
            ASSERT_EQUALS( "sara" , s->getString( "return" ) );
 
148
 
 
149
            s->invoke( "return this.z == 'sara';" , BSONObj() );
 
150
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
151
 
 
152
            s->invoke( "this.z == 'sara';" , BSONObj() );
 
153
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
154
 
 
155
            s->invoke( "this.z == 'asara';" , BSONObj() );
 
156
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
157
            
 
158
            s->invoke( "return this.x == 17;" , BSONObj() );
 
159
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
160
 
 
161
            s->invoke( "return this.x == 18;" , BSONObj() );
 
162
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
163
 
 
164
            s->invoke( "function(){ return this.x == 17; }" , BSONObj() );
 
165
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
166
 
 
167
            s->invoke( "function(){ return this.x == 18; }" , BSONObj() );
 
168
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
169
 
 
170
            s->invoke( "function (){ return this.x == 17; }" , BSONObj() );
 
171
            ASSERT_EQUALS( true , s->getBoolean( "return" ) );
 
172
            
 
173
            s->invoke( "function z(){ return this.x == 18; }" , BSONObj() );
 
174
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
175
 
 
176
            s->invoke( "function (){ this.x == 17; }" , BSONObj() );
 
177
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
178
            
 
179
            s->invoke( "function z(){ this.x == 18; }" , BSONObj() );
 
180
            ASSERT_EQUALS( false , s->getBoolean( "return" ) );
 
181
 
 
182
            s->invoke( "x = 5; for( ; x <10; x++){ a = 1; }" , BSONObj() );
 
183
            ASSERT_EQUALS( 10 , s->getNumber( "x" ) );
 
184
            
 
185
            delete s;
 
186
        }
 
187
    };
 
188
 
 
189
    class ObjectDecoding {
 
190
    public:
 
191
        void run(){
 
192
            Scope * s = globalScriptEngine->newScope();
 
193
            
 
194
            s->invoke( "z = { num : 1 };" , BSONObj() );
 
195
            BSONObj out = s->getObject( "z" );
 
196
            ASSERT_EQUALS( 1 , out["num"].number() );
 
197
            ASSERT_EQUALS( 1 , out.nFields() );
 
198
 
 
199
            s->invoke( "z = { x : 'eliot' };" , BSONObj() );
 
200
            out = s->getObject( "z" );
 
201
            ASSERT_EQUALS( (string)"eliot" , out["x"].valuestr() );
 
202
            ASSERT_EQUALS( 1 , out.nFields() );
 
203
                           
 
204
            BSONObj o = BSON( "x" << 17 );
 
205
            s->setObject( "blah" , o );   
 
206
            out = s->getObject( "blah" );
 
207
            ASSERT_EQUALS( 17 , out["x"].number() );
 
208
            
 
209
            delete s;
 
210
        }
 
211
    };
 
212
    
 
213
    class JSOIDTests {
 
214
    public:
 
215
        void run(){
 
216
#ifdef MOZJS
 
217
            Scope * s = globalScriptEngine->newScope();
 
218
            
 
219
            s->localConnect( "blah" );
 
220
            
 
221
            s->invoke( "z = { _id : new ObjectId() , a : 123 };" , BSONObj() );
 
222
            BSONObj out = s->getObject( "z" );
 
223
            ASSERT_EQUALS( 123 , out["a"].number() );
 
224
            ASSERT_EQUALS( jstOID , out["_id"].type() );
 
225
            
 
226
            OID save = out["_id"].__oid();
 
227
            
 
228
            s->setObject( "a" , out );
 
229
            
 
230
            s->invoke( "y = { _id : a._id , a : 124 };" , BSONObj() );            
 
231
            out = s->getObject( "y" );
 
232
            ASSERT_EQUALS( 124 , out["a"].number() );
 
233
            ASSERT_EQUALS( jstOID , out["_id"].type() );            
 
234
            ASSERT_EQUALS( out["_id"].__oid().str() , save.str() );
 
235
 
 
236
            s->invoke( "y = { _id : new ObjectId( a._id ) , a : 125 };" , BSONObj() );            
 
237
            out = s->getObject( "y" );
 
238
            ASSERT_EQUALS( 125 , out["a"].number() );
 
239
            ASSERT_EQUALS( jstOID , out["_id"].type() );            
 
240
            ASSERT_EQUALS( out["_id"].__oid().str() , save.str() );
 
241
 
 
242
            delete s;
 
243
#endif
 
244
        }
 
245
    };
 
246
 
 
247
    class SetImplicit {
 
248
    public:
 
249
        void run() {
 
250
            Scope *s = globalScriptEngine->newScope();
 
251
 
 
252
            BSONObj o = BSON( "foo" << "bar" );
 
253
            s->setObject( "a.b", o );
 
254
            ASSERT( s->getObject( "a" ).isEmpty() );
 
255
 
 
256
            BSONObj o2 = BSONObj();
 
257
            s->setObject( "a", o2 );
 
258
            s->setObject( "a.b", o );
 
259
            ASSERT( s->getObject( "a" ).isEmpty() );
 
260
 
 
261
            o2 = fromjson( "{b:{}}" );
 
262
            s->setObject( "a", o2 );
 
263
            s->setObject( "a.b", o );
 
264
            ASSERT( !s->getObject( "a" ).isEmpty() );
 
265
        }
 
266
    };
 
267
 
 
268
    class ObjectModReadonlyTests {
 
269
    public:
 
270
        void run(){
 
271
            Scope * s = globalScriptEngine->newScope();
 
272
            
 
273
            BSONObj o = BSON( "x" << 17 << "y" << "eliot" << "z" << "sara" << "zz" << BSONObj() );
 
274
            s->setObject( "blah" , o , true );
 
275
 
 
276
            s->invoke( "blah.y = 'e'", BSONObj() );
 
277
            BSONObj out = s->getObject( "blah" );
 
278
            ASSERT( strlen( out["y"].valuestr() ) > 1 );
 
279
 
 
280
            s->invoke( "blah.a = 19;" , BSONObj() );
 
281
            out = s->getObject( "blah" );
 
282
            ASSERT( out["a"].eoo() );
 
283
 
 
284
            s->invoke( "blah.zz.a = 19;" , BSONObj() );
 
285
            out = s->getObject( "blah" );
 
286
            ASSERT( out["zz"].embeddedObject()["a"].eoo() );
 
287
 
 
288
            s->setObject( "blah.zz", BSON( "a" << 19 ) );
 
289
            out = s->getObject( "blah" );
 
290
            ASSERT( out["zz"].embeddedObject()["a"].eoo() );
 
291
            
 
292
            s->invoke( "delete blah['x']" , BSONObj() );
 
293
            out = s->getObject( "blah" );
 
294
            ASSERT( !out["x"].eoo() );
 
295
            
 
296
            // read-only object itself can be overwritten
 
297
            s->invoke( "blah = {}", BSONObj() );
 
298
            out = s->getObject( "blah" );
 
299
            ASSERT( out.isEmpty() );
 
300
            
 
301
            // test array - can't implement this in v8
 
302
//            o = fromjson( "{a:[1,2,3]}" );
 
303
//            s->setObject( "blah", o, true );
 
304
//            out = s->getObject( "blah" );
 
305
//            s->invoke( "blah.a[ 0 ] = 4;", BSONObj() );
 
306
//            s->invoke( "delete blah['a'][ 2 ];", BSONObj() );
 
307
//            out = s->getObject( "blah" );
 
308
//            ASSERT_EQUALS( 1.0, out[ "a" ].embeddedObject()[ 0 ].number() );
 
309
//            ASSERT_EQUALS( 3.0, out[ "a" ].embeddedObject()[ 2 ].number() );
 
310
            
 
311
            delete s;
 
312
        }
 
313
    };
 
314
 
 
315
    class OtherJSTypes {
 
316
    public:
 
317
        void run(){
 
318
            Scope * s = globalScriptEngine->newScope();
 
319
            
 
320
            { // date
 
321
                BSONObj o;
 
322
                { 
 
323
                    BSONObjBuilder b;
 
324
                    b.appendDate( "d" , 123456789 );
 
325
                    o = b.obj();
 
326
                }
 
327
                s->setObject( "x" , o );
 
328
                
 
329
                s->invoke( "return x.d.getTime() != 12;" , BSONObj() );
 
330
                ASSERT_EQUALS( true, s->getBoolean( "return" ) );
 
331
                
 
332
                s->invoke( "z = x.d.getTime();" , BSONObj() );
 
333
                ASSERT_EQUALS( 123456789 , s->getNumber( "z" ) );
 
334
                
 
335
                s->invoke( "z = { z : x.d }" , BSONObj() );
 
336
                BSONObj out = s->getObject( "z" );
 
337
                ASSERT( out["z"].type() == Date );
 
338
            }
 
339
 
 
340
            { // regex
 
341
                BSONObj o;
 
342
                { 
 
343
                    BSONObjBuilder b;
 
344
                    b.appendRegex( "r" , "^a" , "i" );
 
345
                    o = b.obj();
 
346
                }
 
347
                s->setObject( "x" , o );
 
348
                
 
349
                s->invoke( "z = x.r.test( 'b' );" , BSONObj() );
 
350
                ASSERT_EQUALS( false , s->getBoolean( "z" ) );
 
351
 
 
352
                s->invoke( "z = x.r.test( 'a' );" , BSONObj() );
 
353
                ASSERT_EQUALS( true , s->getBoolean( "z" ) );
 
354
 
 
355
                s->invoke( "z = x.r.test( 'ba' );" , BSONObj() );
 
356
                ASSERT_EQUALS( false , s->getBoolean( "z" ) );
 
357
 
 
358
                s->invoke( "z = { a : x.r };" , BSONObj() );
 
359
 
 
360
                BSONObj out = s->getObject("z");
 
361
                ASSERT_EQUALS( (string)"^a" , out["a"].regex() );
 
362
                ASSERT_EQUALS( (string)"i" , out["a"].regexFlags() );
 
363
 
 
364
            }
 
365
            
 
366
            // array
 
367
            {
 
368
                BSONObj o = fromjson( "{r:[1,2,3]}" );
 
369
                s->setObject( "x", o, false );                
 
370
                BSONObj out = s->getObject( "x" );
 
371
                ASSERT_EQUALS( Array, out.firstElement().type() );
 
372
 
 
373
                s->setObject( "x", o, true );                
 
374
                out = s->getObject( "x" );
 
375
                ASSERT_EQUALS( Array, out.firstElement().type() );
 
376
            }
 
377
            
 
378
            delete s;
 
379
        }
 
380
    };
 
381
 
 
382
    class SpecialDBTypes {
 
383
    public:
 
384
        void run(){
 
385
            Scope * s = globalScriptEngine->newScope();
 
386
 
 
387
            BSONObjBuilder b;
 
388
            b.appendTimestamp( "a" , 123456789 );
 
389
            b.appendMinKey( "b" );
 
390
            b.appendMaxKey( "c" );
 
391
            b.appendTimestamp( "d" , 1234000 , 9876 );
 
392
            
 
393
 
 
394
            {
 
395
                BSONObj t = b.done();
 
396
                ASSERT_EQUALS( 1234000U , t["d"].timestampTime() );
 
397
                ASSERT_EQUALS( 9876U , t["d"].timestampInc() );
 
398
            }
 
399
 
 
400
            s->setObject( "z" , b.obj() );
 
401
            
 
402
            ASSERT( s->invoke( "y = { a : z.a , b : z.b , c : z.c , d: z.d }" , BSONObj() ) == 0 );
 
403
 
 
404
            BSONObj out = s->getObject( "y" );
 
405
            ASSERT_EQUALS( Timestamp , out["a"].type() );
 
406
            ASSERT_EQUALS( MinKey , out["b"].type() );
 
407
            ASSERT_EQUALS( MaxKey , out["c"].type() );
 
408
            ASSERT_EQUALS( Timestamp , out["d"].type() );
 
409
 
 
410
            ASSERT_EQUALS( 9876U , out["d"].timestampInc() );
 
411
            ASSERT_EQUALS( 1234000U , out["d"].timestampTime() );
 
412
            ASSERT_EQUALS( 123456789U , out["a"].date() );
 
413
 
 
414
            delete s;
 
415
        }
 
416
    };
 
417
    
 
418
    class TypeConservation {
 
419
    public:
 
420
        void run(){
 
421
            Scope * s = globalScriptEngine->newScope();
 
422
            
 
423
            //  --  A  --
 
424
            
 
425
            BSONObj o;
 
426
            {
 
427
                BSONObjBuilder b ;
 
428
                b.append( "a" , (int)5 );
 
429
                b.append( "b" , 5.6 );
 
430
                o = b.obj();
 
431
            }
 
432
            ASSERT_EQUALS( NumberInt , o["a"].type() );
 
433
            ASSERT_EQUALS( NumberDouble , o["b"].type() );
 
434
            
 
435
            s->setObject( "z" , o );
 
436
            s->invoke( "return z" , BSONObj() );
 
437
            BSONObj out = s->getObject( "return" );
 
438
            ASSERT_EQUALS( 5 , out["a"].number() );
 
439
            ASSERT_EQUALS( 5.6 , out["b"].number() );
 
440
 
 
441
            ASSERT_EQUALS( NumberDouble , out["b"].type() );
 
442
            ASSERT_EQUALS( NumberInt , out["a"].type() );
 
443
 
 
444
            //  --  B  --
 
445
            
 
446
            {
 
447
                BSONObjBuilder b ;
 
448
                b.append( "a" , (int)5 );
 
449
                b.append( "b" , 5.6 );
 
450
                o = b.obj();
 
451
            }
 
452
 
 
453
            s->setObject( "z" , o , false );
 
454
            s->invoke( "return z" , BSONObj() );
 
455
            out = s->getObject( "return" );
 
456
            ASSERT_EQUALS( 5 , out["a"].number() );
 
457
            ASSERT_EQUALS( 5.6 , out["b"].number() );
 
458
 
 
459
            ASSERT_EQUALS( NumberDouble , out["b"].type() );
 
460
            ASSERT_EQUALS( NumberInt , out["a"].type() );
 
461
 
 
462
            
 
463
            //  -- C --
 
464
            
 
465
            {
 
466
                BSONObjBuilder b ;
 
467
                
 
468
                {
 
469
                    BSONObjBuilder c;
 
470
                    c.append( "0" , 5.5 );
 
471
                    c.append( "1" , 6 );
 
472
                    b.appendArray( "a" , c.obj() );
 
473
                }
 
474
                
 
475
                o = b.obj();
 
476
            }
 
477
            
 
478
            ASSERT_EQUALS( NumberDouble , o["a"].embeddedObjectUserCheck()["0"].type() );
 
479
            ASSERT_EQUALS( NumberInt , o["a"].embeddedObjectUserCheck()["1"].type() );
 
480
            
 
481
            s->setObject( "z" , o , false );
 
482
            out = s->getObject( "z" );
 
483
 
 
484
            ASSERT_EQUALS( NumberDouble , out["a"].embeddedObjectUserCheck()["0"].type() );
 
485
            ASSERT_EQUALS( NumberInt , out["a"].embeddedObjectUserCheck()["1"].type() );
 
486
            
 
487
            s->invokeSafe( "z.z = 5;" , BSONObj() );
 
488
            out = s->getObject( "z" );
 
489
            ASSERT_EQUALS( 5 , out["z"].number() );
 
490
            ASSERT_EQUALS( NumberDouble , out["a"].embeddedObjectUserCheck()["0"].type() );
 
491
            // Commenting so that v8 tests will work
 
492
//            ASSERT_EQUALS( NumberDouble , out["a"].embeddedObjectUserCheck()["1"].type() ); // TODO: this is technically bad, but here to make sure that i understand the behavior
 
493
 
 
494
 
 
495
            // Eliot says I don't have to worry about this case
 
496
            
 
497
//            // -- D --
 
498
//            
 
499
//            o = fromjson( "{a:3.0,b:4.5}" );
 
500
//            ASSERT_EQUALS( NumberDouble , o["a"].type() );
 
501
//            ASSERT_EQUALS( NumberDouble , o["b"].type() );
 
502
//
 
503
//            s->setObject( "z" , o , false );
 
504
//            s->invoke( "return z" , BSONObj() );
 
505
//            out = s->getObject( "return" );
 
506
//            ASSERT_EQUALS( 3 , out["a"].number() );
 
507
//            ASSERT_EQUALS( 4.5 , out["b"].number() );
 
508
//            
 
509
//            ASSERT_EQUALS( NumberDouble , out["b"].type() );
 
510
//            ASSERT_EQUALS( NumberDouble , out["a"].type() );
 
511
//            
 
512
            
 
513
            delete s;
 
514
        }
 
515
        
 
516
    };
 
517
    
 
518
    class WeirdObjects {
 
519
    public:
 
520
 
 
521
        BSONObj build( int depth ){
 
522
            BSONObjBuilder b;
 
523
            b.append( "0" , depth );
 
524
            if ( depth > 0 )
 
525
                b.appendArray( "1" , build( depth - 1 ) );
 
526
            return b.obj();
 
527
        }
 
528
        
 
529
        void run(){
 
530
            Scope * s = globalScriptEngine->newScope();
 
531
 
 
532
            s->localConnect( "blah" );
 
533
            
 
534
            for ( int i=5; i<100 ; i += 10 ){
 
535
                s->setObject( "a" , build(i) , false );
 
536
                s->invokeSafe( "tojson( a )" , BSONObj() );
 
537
                
 
538
                s->setObject( "a" , build(5) , true );
 
539
                s->invokeSafe( "tojson( a )" , BSONObj() );
 
540
            }
 
541
 
 
542
            delete s;
 
543
        }
 
544
    };
 
545
 
 
546
 
 
547
    void dummy_function_to_force_dbeval_cpp_linking() {
 
548
        BSONObj cmd;
 
549
        BSONObjBuilder result;
 
550
        string errmsg;
 
551
        dbEval( "", cmd, result, errmsg);
 
552
    }
 
553
 
 
554
    DBDirectClient client;
 
555
    
 
556
    class Utf8Check {
 
557
    public:
 
558
        Utf8Check() { reset(); }
 
559
        ~Utf8Check() { reset(); }
 
560
        void run() {
 
561
            if( !globalScriptEngine->utf8Ok() ) {
 
562
                log() << "warning: utf8 not supported" << endl;
 
563
                return;
 
564
            }
 
565
            string utf8ObjSpec = "{'_id':'\\u0001\\u007f\\u07ff\\uffff'}";
 
566
            BSONObj utf8Obj = fromjson( utf8ObjSpec );
 
567
            client.insert( ns(), utf8Obj );
 
568
            client.eval( "unittest", "v = db.jstests.utf8check.findOne(); db.jstests.utf8check.remove( {} ); db.jstests.utf8check.insert( v );" );
 
569
            check( utf8Obj, client.findOne( ns(), BSONObj() ) );
 
570
        }
 
571
    private:
 
572
        void check( const BSONObj &one, const BSONObj &two ) {
 
573
            if ( one.woCompare( two ) != 0 ) {
 
574
                static string fail = string( "Assertion failure expected " ) + string( one ) + ", got " + string( two );
 
575
                FAIL( fail.c_str() );
 
576
            }
 
577
        }
 
578
        void reset() {
 
579
            client.dropCollection( ns() );
 
580
        }        
 
581
        static const char *ns() { return "unittest.jstests.utf8check"; }
 
582
    };
 
583
 
 
584
    class LongUtf8String {
 
585
    public:
 
586
        LongUtf8String() { reset(); }
 
587
        ~LongUtf8String() { reset(); }
 
588
        void run() {
 
589
            if( !globalScriptEngine->utf8Ok() )
 
590
                return;
 
591
            client.eval( "unittest", "db.jstests.longutf8string.save( {_id:'\\uffff\\uffff\\uffff\\uffff'} )" );
 
592
        }
 
593
    private:
 
594
        void reset() {
 
595
            client.dropCollection( ns() );
 
596
        }        
 
597
        static const char *ns() { return "unittest.jstests.longutf8string"; }
 
598
    };
 
599
    
 
600
    class CodeTests {
 
601
    public:
 
602
        void run(){
 
603
            Scope * s = globalScriptEngine->newScope();
 
604
            
 
605
            {
 
606
                BSONObjBuilder b;
 
607
                b.append( "a" , 1 );
 
608
                b.appendCode( "b" , "function(){ out.b = 11; }" );
 
609
                b.appendCodeWScope( "c" , "function(){ out.c = 12; }" , BSONObj() );
 
610
                b.appendCodeWScope( "d" , "function(){ out.d = 13 + bleh; }" , BSON( "bleh" << 5 ) );
 
611
                s->setObject( "foo" , b.obj() );
 
612
            }
 
613
            
 
614
            s->invokeSafe( "out = {}; out.a = foo.a; foo.b(); foo.c();" , BSONObj() );
 
615
            BSONObj out = s->getObject( "out" );
 
616
            
 
617
            ASSERT_EQUALS( 1 , out["a"].number() );
 
618
            ASSERT_EQUALS( 11 , out["b"].number() );
 
619
            ASSERT_EQUALS( 12 , out["c"].number() );
 
620
 
 
621
            // Guess we don't care about this
 
622
            //s->invokeSafe( "foo.d() " , BSONObj() );
 
623
            //out = s->getObject( "out" );
 
624
            //ASSERT_EQUALS( 18 , out["d"].number() );
 
625
            
 
626
 
 
627
            delete s;
 
628
        }
 
629
    };
 
630
 
 
631
    class DBRefTest {
 
632
    public:
 
633
        DBRefTest(){
 
634
            _a = "unittest.dbref.a";
 
635
            _b = "unittest.dbref.b";
 
636
            reset();
 
637
        }
 
638
        ~DBRefTest(){
 
639
            //reset();
 
640
        }
 
641
        
 
642
        void run(){
 
643
 
 
644
            client.insert( _a , BSON( "a" << "17" ) );
 
645
            
 
646
            {
 
647
                BSONObj fromA = client.findOne( _a , BSONObj() );
 
648
                cout << "Froma : " << fromA << endl;
 
649
                BSONObjBuilder b;
 
650
                b.append( "b" , 18 );
 
651
                b.appendDBRef( "c" , "dbref.a" , fromA["_id"].__oid() );
 
652
                client.insert( _b , b.obj() );
 
653
            }
 
654
            
 
655
            ASSERT( client.eval( "unittest" , "x = db.dbref.b.findOne(); assert.eq( 17 , x.c.fetch().a , 'ref working' );" ) );
 
656
            
 
657
            // BSON DBRef <=> JS DBPointer
 
658
            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 );" ) );
 
659
            ASSERT_EQUALS( DBRef, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() );
 
660
            
 
661
            // BSON Object <=> JS DBRef
 
662
            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 );" ) );
 
663
            ASSERT_EQUALS( Object, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() );
 
664
            ASSERT_EQUALS( string( "dbref.a" ), client.findOne( "unittest.dbref.b", "" )[ "c" ].embeddedObject().getStringField( "$ref" ) );
 
665
        }
 
666
        
 
667
        void reset(){
 
668
            client.dropCollection( _a );
 
669
            client.dropCollection( _b );
 
670
        }
 
671
        
 
672
        const char * _a;
 
673
        const char * _b;
 
674
    };
 
675
    
 
676
    class BinDataType {
 
677
    public:
 
678
        
 
679
        void pp( const char * s , BSONElement e ){
 
680
            int len;
 
681
            const char * data = e.binData( len );
 
682
            cout << s << ":" << e.binDataType() << "\t" << len << endl;
 
683
            cout << "\t";
 
684
            for ( int i=0; i<len; i++ )
 
685
                cout << (int)(data[i]) << " ";
 
686
            cout << endl;
 
687
        }
 
688
 
 
689
        void run(){
 
690
            Scope * s = globalScriptEngine->newScope();
 
691
            s->localConnect( "asd" );
 
692
            const char * foo = "asdas\0asdasd";
 
693
 
 
694
            
 
695
            BSONObj in;
 
696
            {
 
697
                BSONObjBuilder b;
 
698
                b.append( "a" , 7 );
 
699
                b.appendBinData( "b" , 12 , ByteArray , foo );
 
700
                in = b.obj();
 
701
                s->setObject( "x" , in );
 
702
            }
 
703
            
 
704
            s->invokeSafe( "myb = x.b; print( myb ); printjson( myb );" , BSONObj() );
 
705
            s->invokeSafe( "y = { c : myb };" , BSONObj() );
 
706
            
 
707
            BSONObj out = s->getObject( "y" );
 
708
            ASSERT_EQUALS( BinData , out["c"].type() );
 
709
            //blah( "in " , in["b"] );
 
710
            //blah( "out" , out["c"] );
 
711
            ASSERT_EQUALS( 0 , in["b"].woCompare( out["c"] , false ) );
 
712
 
 
713
            // check that BinData js class is utilized
 
714
            s->invokeSafe( "q = tojson( x.b );", BSONObj() );
 
715
            ASSERT_EQUALS( "BinData", s->getString( "q" ).substr( 0, 7 ) );
 
716
            
 
717
            delete s;
 
718
        }
 
719
    };
 
720
 
 
721
    class VarTests {
 
722
    public:
 
723
        void run(){
 
724
            Scope * s = globalScriptEngine->newScope();
 
725
            
 
726
            ASSERT( s->exec( "a = 5;" , "a" , false , true , false ) );
 
727
            ASSERT_EQUALS( 5 , s->getNumber("a" ) );
 
728
 
 
729
            ASSERT( s->exec( "var b = 6;" , "b" , false , true , false ) );
 
730
            ASSERT_EQUALS( 6 , s->getNumber("b" ) );
 
731
            delete s;
 
732
        }
 
733
    };
 
734
 
 
735
    class All : public Suite {
 
736
    public:
 
737
        All() : Suite( "js" ) {
 
738
        }
 
739
        
 
740
        void setupTests(){
 
741
            add< Fundamental >();
 
742
            add< BasicScope >();
 
743
            add< ResetScope >();
 
744
            add< FalseTests >();
 
745
            add< SimpleFunctions >();
 
746
 
 
747
            add< ObjectMapping >();
 
748
            add< ObjectDecoding >();
 
749
            add< JSOIDTests >();
 
750
            add< SetImplicit >();
 
751
            add< ObjectModReadonlyTests >();
 
752
            add< OtherJSTypes >();
 
753
            add< SpecialDBTypes >();
 
754
            add< TypeConservation >();
 
755
 
 
756
            add< WeirdObjects >();
 
757
            add< Utf8Check >();
 
758
            add< LongUtf8String >();
 
759
            add< CodeTests >();
 
760
            add< DBRefTest >();
 
761
            add< BinDataType >();
 
762
 
 
763
            add< VarTests >();
 
764
        }
 
765
    } myall;
 
766
    
 
767
} // namespace JavaJSTests
 
768