/*jshint globalstrict:false, strict:false, maxlen: 500 */ /*global assertEqual, assertNotEqual, assertTrue, assertFalse, assertNull, assertMatch, fail, AQL_EXECUTE */ //////////////////////////////////////////////////////////////////////////////// /// @brief tests for query language, modification blocks /// /// @file /// /// DISCLAIMER /// /// Copyright 2018-2018 ArangoDB GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Michael Hackstein /// @author Copyright 2018, ArangoDB GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// const internal = require("internal"); const db = require("@arangodb").db; const jsunity = require("jsunity"); const helper = require("@arangodb/aql-helper"); const errors = internal.errors; const collectionName = "UnitTestAqlModify"; let col; //////////////////////////////////////////////////////////////////////////////// /// @brief helper functions //////////////////////////////////////////////////////////////////////////////// let invCounter = 0; const genInvalidValue = function () { ++invCounter; return `invalid${invCounter}`; }; const setUp = function () { tearDown(); col = db._create(collectionName, { numberOfShards: 3 }); let list = []; for (let i = 0; i < 2000; ++i) { list.push({ val: i }); } col.save(list); assertEqual(2000, col.count()); }; const tearDown = function () { db._drop(collectionName); col = null; }; const buildSetOfDocs = function (count = 0) { if (count <= 0 || count >= 2000) { return new Set(col.toArray()); } const query = `FOR d IN ${collectionName} LIMIT ${count} RETURN d`; return new Set(db._query(query).toArray()); }; const validateDocsAreUpdated = function (docs, invalid, areUpdated) { for (let d of docs) { const nowStored = col.document(d._key); if (areUpdated) { assertEqual(invalid, nowStored.val, `Did not update ${JSON.stringify(d)} using wrong _rev value`); } else { assertNotEqual(invalid, nowStored.val, `Updated ${JSON.stringify(d)} using wrong _rev value`); } } }; //////////////////////////////////////////////////////////////////////////////// /// @brief test suite //////////////////////////////////////////////////////////////////////////////// function aqlUpdateOptionsSuite() { return { setUp, tearDown, testUpdateSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, { key: d._key }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } validateDocsAreUpdated(docs, invalid, false); }, testUpdateManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, { docs: [...docs] }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testUpdateEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testUpdateSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testUpdateSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testUpdateSingleWithValidRev: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: @rev, val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key, rev: d._rev }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateManyWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: doc._rev, val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateEnumerationWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: doc._rev, val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, }; }; function aqlUpdateWithOptionsSuite() { return { setUp, tearDown, testUpdateWithSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, { key: d._key }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } validateDocsAreUpdated(docs, invalid, false); }, testUpdateWithManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, { docs: [...docs] }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testUpdateWithEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testUpdateWithSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: "invalid"} WITH {val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithSingleWithValidRev: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key, _rev: @rev} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key, rev: d._rev }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithManyWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key, _rev: doc._rev} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithEnumerationWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key, _rev: doc._rev} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, }; }; function aqlUpdateWithRevOptionsSuite() { return { setUp, tearDown, testUpdateWithRevSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `UPDATE {_key: @key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPDATE {_key: doc._key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testUpdateWithRevEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPDATE {_key: doc._key} WITH {_rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); } }; }; function aqlReplaceOptionsSuite() { return { setUp, tearDown, testReplaceSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, { key: d._key }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } validateDocsAreUpdated(docs, invalid, false); }, testReplaceManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, { docs: [...docs] }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testReplaceEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testReplaceSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testReplaceSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testReplaceSingleWithValidRev: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: @rev, val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key, rev: d._rev }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceManyWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: doc._rev, val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceEnumerationWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: doc._rev, val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, }; }; function aqlReplaceWithOptionsSuite() { return { setUp, tearDown, testReplaceWithSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, { key: d._key }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } validateDocsAreUpdated(docs, invalid, false); }, testReplaceWithManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, { docs: [...docs] }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testReplaceWithEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } validateDocsAreUpdated(docs, invalid, false); }, testReplaceWithSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: "invalid"} WITH { val: "${invalid}" } IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithSingleWithValidRev: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key, _rev: @rev} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key, rev: d._rev }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithManyWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key, _rev: doc._rev} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithEnumerationWithValidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key, _rev: doc._rev} WITH {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, }; }; function aqlReplaceWithRevOptionsSuite() { return { setUp, tearDown, testReplaceWithRevSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `REPLACE {_key: @key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REPLACE {_key: doc._key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); validateDocsAreUpdated(docs, invalid, true); }, testReplaceWithRevEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REPLACE {_key: doc._key} WITH { _rev: "invalid", val: "${invalid}" } IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); validateDocsAreUpdated(docs, invalid, true); } }; }; //////////////////////////////////////////////////////////////////////////////// /// @brief test suite //////////////////////////////////////////////////////////////////////////////// function aqlRemoveOptionsSuite() { return { setUp, tearDown, testRemoveSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `REMOVE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, { key: d._key }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } assertEqual(2000, col.count(), `We removed the document`); }, testRemoveManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REMOVE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, { docs: [...docs] }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } assertEqual(2000, col.count(), `We removed the document`); }, testRemoveEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REMOVE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } assertEqual(2000, col.count(), `We removed the document`); }, testRemoveSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `REMOVE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } assertEqual(2000 - 1, col.count(), `We did not remove the document`); }, testRemoveManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REMOVE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); assertEqual(2000 - 10, col.count(), `We did not remove the document`); }, testRemoveEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REMOVE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); assertEqual(0, col.count(), `We did not remove the document`); }, testRemoveSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `REMOVE {_key: @key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } assertEqual(2000 - 1, col.count(), `We did not remove the document`); }, testRemoveManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs REMOVE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); assertEqual(2000 - 10, col.count(), `We did not remove the document`); }, testRemoveEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} REMOVE {_key: doc._key, _rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); assertEqual(0, col.count(), `We did not remove the document`); } }; }; //////////////////////////////////////////////////////////////////////////////// /// @brief test suite //////////////////////////////////////////////////////////////////////////////// function aqlUpsertOptionsSuite() { return { setUp, tearDown, testUpsertSingleWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `UPSERT {_key: @key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, { key: d._key }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, false); }, testUpsertManyWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPSERT {_key: doc._key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, { docs: [...docs] }); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, false); }, testUpsertEnumerationWithInvalidRev: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPSERT {_key: doc._key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, false); }, testUpsertSingleWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `UPSERT {_key: @key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertManyWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPSERT {_key: doc._key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertEnumerationWithInvalidRevIgnore: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPSERT {_key: doc._key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertSingleWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `UPSERT {_key: @key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, { key: d._key }); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertManyWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPSERT {_key: doc._key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, { docs: [...docs] }); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertEnumerationWithInvalidRevDefault: function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPSERT {_key: doc._key} INSERT {} UPDATE {_rev: "invalid", val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertEmptyObject: function () { let NEW, OLD, res; col.insert({ "value1": "find me" }); // before "find me" was found because the empty object // was ignored now we will insert instead let q1 = `UPSERT { "value1" : "find me", "value2" : {} } INSERT { "value1" : "find me", "value2" : {} } UPDATE { "value1" : "not gonna happen" } IN ${collectionName} RETURN [$OLD, $NEW]`; res = db._query(q1).toArray(); OLD = res[0][0]; NEW = res[0][1]; assertEqual(NEW.value1, "find me"); assertEqual(NEW.value2, {}); // now we update the exact doucment let q2 = `UPSERT { "value1" : "find me", "value2" : {} } INSERT { "value1" : "not gonna happen" } UPDATE { "value1" : "update" } IN ${collectionName} RETURN [$OLD, $NEW]`; res = db._query(q2).toArray(); OLD = res[0][0]; NEW = res[0][1]; assertEqual(NEW.value1, "update"); assertEqual(NEW.value2, {}); }, /* We cannot yet solve this. If you need to ensure _rev value checks put them in the UPDATE {} clause testUpsertSingleWithInvalidRevInMatch : function () { const invalid = genInvalidValue(); let q = `UPSERT {_key: @key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; db._explain(q, {key: "1"}); let docs = buildSetOfDocs(1); for (let d of docs) { try { db._query(q, {key: d._key}); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, false); }, testUpsertManyWithInvalidRevInMatch : function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPSERT {_key: doc._key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(10); try { db._query(q, {docs: [...docs]}); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, false); }, testUpsertEnumerationWithInvalidRevInMatch : function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPSERT {_key: doc._key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: false}`; let docs = buildSetOfDocs(); try { db._query(q); fail(); } catch (err) { assertEqual(err.errorNum, errors.ERROR_ARANGO_CONFLICT.code); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, false); }, testUpsertSingleWithInvalidRevIgnoreInMatch : function () { const invalid = genInvalidValue(); let q = `UPSERT {_key: @key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, {key: d._key}); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertManyWithInvalidRevIgnoreInMatch : function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPSERT {_key: doc._key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(10); db._query(q, {docs: [...docs]}); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertEnumerationWithInvalidRevIgnoreInMatch : function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPSERT {_key: doc._key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName} OPTIONS {ignoreRevs: true}`; let docs = buildSetOfDocs(); db._query(q); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertSingleWithInvalidRevDefaultInMatch : function () { const invalid = genInvalidValue(); let q = `UPSERT {_key: @key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(1); for (let d of docs) { db._query(q, {key: d._key}); } assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertManyWithInvalidRevDefaultInMatch : function () { const invalid = genInvalidValue(); let q = `FOR doc IN @docs UPSERT {_key: doc._key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(10); db._query(q, {docs: [...docs]}); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, testUpsertEnumerationWithInvalidRevDefaultInMatch : function () { const invalid = genInvalidValue(); let q = `FOR doc IN ${collectionName} UPSERT {_key: doc._key, _rev: "invalid"} INSERT {} UPDATE {val: "${invalid}"} IN ${collectionName}`; let docs = buildSetOfDocs(); db._query(q); assertEqual(2000, col.count(), `We falsely triggered an INSERT`); validateDocsAreUpdated(docs, invalid, true); }, */ }; }; //////////////////////////////////////////////////////////////////////////////// /// @brief executes the test suites //////////////////////////////////////////////////////////////////////////////// jsunity.run(aqlUpdateOptionsSuite); jsunity.run(aqlUpdateWithOptionsSuite); jsunity.run(aqlUpdateWithRevOptionsSuite); jsunity.run(aqlReplaceOptionsSuite); jsunity.run(aqlReplaceWithOptionsSuite); jsunity.run(aqlReplaceWithRevOptionsSuite); jsunity.run(aqlRemoveOptionsSuite); jsunity.run(aqlUpsertOptionsSuite); return jsunity.done();