summaryrefslogtreecommitdiff
path: root/jstests/aggregation/bugs/server3253.js
blob: 51e355cad0bed67c41d192d0db113ae60e3ede73 (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
// Cannot implicitly shard accessed collections because unsupported use of sharded collection
// for output collection of aggregation pipeline.
// @tags: [assumes_unsharded_collection]

// server-3253 Unsharded support for $out
load('jstests/aggregation/extras/utils.js');

var input = db.server3253_in;
var inputDoesntExist = db.server3253_doesnt_exist;
var output = db.server3253_out;
var cappedOutput = db.server3253_out_capped;

input.drop();
inputDoesntExist.drop();  // never created
output.drop();

function collectionExists(coll) {
    return Array.contains(coll.getDB().getCollectionNames(), coll.getName());
}

function getOutputIndexes() {
    return output.getIndexes().sort(function(a, b) {
        if (a.name < b.name) {
            return -1;
        } else {
            return 1;
        }
    });
}

function test(input, pipeline, expected) {
    pipeline.push({$out: output.getName()});
    var indexes = getOutputIndexes();

    var cursor = input.aggregate(pipeline);

    assert.eq(cursor.itcount(), 0);                // empty cursor returned
    assert.eq(output.find().toArray(), expected);  // correct results
    var outputIndexes = getOutputIndexes();
    assert.eq(outputIndexes.length, indexes.length);  // number of indexes maintained
    for (var i = 0; i < outputIndexes.length; i++) {
        assert.docEq(outputIndexes[i], indexes[i]);
    }

    assert(collectionExists(output));
}

function listCollections(name) {
    var collectionInfosCursor = db.runCommand("listCollections", {filter: {name: name}});
    return new DBCommandCursor(db, collectionInfosCursor).toArray();
}

input.insert({_id: 1});
input.insert({_id: 2});
input.insert({_id: 3});

// insert into output so that the index exists and test() does not fail the first time around
output.insert({_id: 1});

// ensure there are no tmp agg_out collections before we begin
assert.eq([], listCollections(/tmp\.agg_out/));

// basic test
test(input,
     [{$project: {a: {$add: ['$_id', '$_id']}}}],
     [{_id: 1, a: 2}, {_id: 2, a: 4}, {_id: 3, a: 6}]);

// test with indexes
assert.eq(output.getIndexes().length, 1);
output.ensureIndex({a: 1});
assert.eq(output.getIndexes().length, 2);
test(input,
     [{$project: {a: {$multiply: ['$_id', '$_id']}}}],
     [{_id: 1, a: 1}, {_id: 2, a: 4}, {_id: 3, a: 9}]);

// test with empty result set and make sure old result is gone, but indexes remain
test(input, [{$match: {_id: 11}}], []);
assert.eq(output.getIndexes().length, 2);

// test with geo index
output.ensureIndex({b: "2d"});
assert.eq(output.getIndexes().length, 3);
test(input, [{$project: {b: "$_id"}}], [{_id: 1, b: 1}, {_id: 2, b: 2}, {_id: 3, b: 3}]);

// test with full text index
output.ensureIndex({c: "text"});
assert.eq(output.getIndexes().length, 4);
test(input, [{$project: {c: {$concat: ["hello there ", "_id"]}}}], [
    {_id: 1, c: "hello there _id"},
    {_id: 2, c: "hello there _id"},
    {_id: 3, c: "hello there _id"}
]);

// test with capped collection, skip for mobile SE as it doesn't support capped collections.
if (jsTest.options().storageEngine !== "mobile") {
    cappedOutput.drop();
    db.createCollection(cappedOutput.getName(), {capped: true, size: 2});
    assertErrorCode(input, {$out: cappedOutput.getName()}, 17152);
}

// ensure everything works even if input doesn't exist.
test(inputDoesntExist, [], []);

// ensure we cant do dangerous things to system collections
var outputInSystem = db.system.server3253_out;
assertErrorCode(input, {$out: outputInSystem.getName()}, 17385);
assert(!collectionExists(outputInSystem));

// shoudn't leave temp collections laying around
assert.eq([], listCollections(/tmp\.agg_out/));