summaryrefslogtreecommitdiff
path: root/jstests/aggregation/bugs/substr.js
blob: 0d4eb72e6918872d5056b2ccc4538ac348c6a95a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Aggregation $substr tests.

t = db.jstests_aggregation_substr;
t.drop();

t.save( {} );

function assertSubstring( expected, str, offset, len ) {
    assert.eq( expected,
               t.aggregate( { $project:{ a:{ $substr:[ str, offset, len ] } } } ).toArray()[ 0 ].a );
}

function assertArgsException( args ) {
    assert.commandFailed(t.runCommand('aggregate', {pipeline: [{$substr: args}]}));
}

function assertException( str, offset, len ) {
    assertArgsException([str, offset, len]);
}

// Wrong number of arguments.
assertArgsException( [] );
assertArgsException( [ 'foo' ] );
assertArgsException( [ 'foo', 1 ] );
assertArgsException( [ 'foo', 1, 1, 1 ] );

// Basic offset / length checks.
assertSubstring( 'abcd', 'abcd', 0, 4 );
assertSubstring( 'abcd', 'abcd', 0, 5 );
assertSubstring( '', 'abcd', -1 /* unsigned */, 4 );
assertSubstring( 'a', 'abcd', 0, 1 );
assertSubstring( 'ab', 'abcd', 0, 2 );
assertSubstring( 'b', 'abcd', 1, 1 );
assertSubstring( 'd', 'abcd', 3, 1 );
assertSubstring( '', 'abcd', 4, 1 );
assertSubstring( '', 'abcd', 3, 0 );
assertSubstring( 'cd', 'abcd', 2, -1 /* unsigned */ );

// See server6186.js for additional offset / length checks.

// Additional numeric types for offset / length.
assertSubstring( 'bc', 'abcd', 1, 2 );
assertSubstring( 'bc', 'abcd', 1.0, 2.0 );
assertSubstring( 'bc', 'abcd', NumberInt( 1 ), NumberInt( 2 ) );
assertSubstring( 'bc', 'abcd', NumberLong( 1 ), NumberLong( 2 ) );
assertSubstring( 'bc', 'abcd', NumberInt( 1 ), NumberLong( 2 ) );
assertSubstring( 'bc', 'abcd', NumberLong( 1 ), NumberInt( 2 ) );
// Integer component is used.
assertSubstring( 'bc', 'abcd', 1.2, 2.2 );
assertSubstring( 'bc', 'abcd', 1.9, 2.9 );

// Non numeric types for offset / length.
assertException( 'abcd', false, 2 );
assertException( 'abcd', 1, true );
assertException( 'abcd', 'q', 2 );
assertException( 'abcd', 1, 'r' );
assertException( 'abcd', null, 3 );
assertException( 'abcd', 1, undefined );

// String coercion.
assertSubstring( '123', 123, 0, 3 );
assertSubstring( '2', 123, 1, 1 );
assertSubstring( '1970', new Date( 0 ), 0, 4 );
assertSubstring( '', null, 0, 4 );
assertException( /abc/, 0, 4 );

// Field path like string.
assertSubstring( '$a', 'a$a', 1, 2 );

// Multi byte utf-8.
assertSubstring( '\u0080', '\u0080', 0, 2 );

assertException( '\u0080', 0, 1 );
assertException( '\u0080', 1, 1 );

assertSubstring( '\u0080', '\u0080\u20ac', 0, 2 );
assertSubstring( '\u20ac', '\u0080\u20ac', 2, 3 );

assertException( '\u0080\u20ac', 1, 3 );
assertException( '\u0080\u20ac', 1, 4 );
assertException( '\u0080\u20ac', 0, 3 );

assertSubstring( '\u0044\u20ac', '\u0080\u0044\u20ac', 2, 4 );
assertSubstring( '\u0044', '\u0080\u0044\u20ac', 2, 1 );

// The four byte utf-8 character 𝌆 (have to represent in surrogate halves).
assertSubstring( '\uD834\uDF06', '\uD834\uDF06', 0, 4 );

assertException( '\uD834\uDF06', '\uD834\uDF06', 1, 4 );
assertException( '\uD834\uDF06', '\uD834\uDF06', 0, 3 );

// Operands from document.
t.drop();
t.save( { x:'a', y:'abc', z:'abcde', a:0, b:1, c:2, d:3, e:4, f:5 } );
assertSubstring( 'a', '$x', '$a', '$b' );
assertSubstring( 'a', '$x', '$a', '$f' );
assertSubstring( 'b', '$y', '$b', '$b' );
assertSubstring( 'b', '$z', '$b', '$b' );
assertSubstring( 'bcd', '$z', '$b', '$d' );
assertSubstring( 'cde', '$z', '$c', '$f' );
assertSubstring( 'c', '$y', '$c', '$f' );

// Computed operands.
assertSubstring( 'cde', '$z', { $add:[ '$b', '$b' ] }, { $add:[ '$c', '$d' ] } );
assertSubstring( 'cde', '$z', { $add:[ '$b', 1 ] }, { $add:[ 2, '$d' ] } );

// Nested.
assert.eq( 'e',
          t.aggregate( { $project:{ a:
                      { $substr:
                       [ { $substr:
                        [ { $substr:
                         [ { $substr:[ 'abcdefghij', 1, 6 ]
                          }, 2, 5 ]
                         }, 0, 3 ]
                        }, 1, 1 ]
                      } } } ).toArray()[ 0 ].a );