1
0
Fork 0
arangodb/tests/js/server/aql/aql-dynamic-attributes.js

336 lines
15 KiB
JavaScript

/*jshint globalstrict:false, strict:false, maxlen: 500 */
/*global assertEqual, AQL_EXECUTE, AQL_EXPLAIN, AQL_EXECUTEJSON */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for dynamic attributes
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens 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 triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlDynamicAttributesTestSuite () {
function checkResult(query, expected) {
let q = "RETURN NOOPT(" + query + ")";
assertEqual(expected, AQL_EXECUTE(q).json[0]);
assertEqual("simple", AQL_EXPLAIN(q).plan.nodes[1].expressionType);
q = "RETURN " + query;
assertEqual(expected, AQL_EXECUTE(q).json[0]);
assertEqual("simple", AQL_EXPLAIN(q).plan.nodes[1].expressionType);
}
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with non-string values
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesNonStringNames : function () {
var expected = { "" : 7, "true" : 12, "false" : 15, "123" : 21, "-42.5" : 99, "[]" : 117, "[1]" : 121, "[1,2,3,4]" : 131, "{\"a\":1}" : 149 };
var query = "{ [ PASSTHRU(null) ] : 7, [ PASSTHRU(true) ] : 12, [ PASSTHRU(false) ] : 15, [ PASSTHRU(123) ] : 21, [ PASSTHRU(-42.5) ] : 99, [ PASSTHRU([ ]) ] : 117, [ PASSTHRU([ 1 ]) ] : 121, [ PASSTHRU([ 1, 2, 3, 4 ]) ] : 131, [ PASSTHRU({ a: 1 }) ] : 149 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with keyword names
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesReservedNames : function () {
var expected = { LET: "LET", FILTER: "FILTER", SORT: "SORT", FOR: "FOR", "return": "RETURN" };
var actual = AQL_EXECUTE("RETURN { [ UPPER('let') ] : 'LET', [ 'FILTER' ] : 'FILTER', [ PASSTHRU('SORT') ] : 'SORT', [ CONCAT('F', 'O', 'R') ] : 'FOR', [ PASSTHRU(LOWER('RETURN')) ] : 'RETURN' }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with special characters
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesWhitespace : function () {
var expected = { "1" : "one", " 1" : "one-1", "1 " : "1-one", " 1 " : "one-1-one" };
var query = "{ [ '1' ] : 'one', [ ' 1' ] : 'one-1', [ '1 ' ] : '1-one', [ ' 1 ' ] : 'one-1-one' }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with special characters
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesWhitespacePassthru : function () {
var expected = { "1" : "one", " 1" : "one-1", "1 " : "1-one", " 1 " : "one-1-one" };
var actual = AQL_EXECUTE("RETURN { [ PASSTHRU('1') ] : 'one', [ PASSTHRU(' 1') ] : 'one-1', [ PASSTHRU('1 ') ] : '1-one', [ PASSTHRU(' 1 ') ] : 'one-1-one' }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with special characters
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesSpecialCharacters : function () {
var expected = { "" : "empty", " " : "space", " " : "two", "_" : "underscore", "\\" : "backslash", "\n" : "linebreak", "\t" : "tab!", "$" : "dollar", "1" : "one" };
var actual = AQL_EXECUTE("RETURN { [ '' ] : 'empty', [ ' ' ] : 'space', [ ' ' ] : 'two', [ '_' ] : 'underscore', [ '\\\\'] : 'backslash', '\\n' : 'linebreak', '\\t' : 'tab!', '$' : 'dollar', '1' : 'one' }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with bind parameter-like names
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesWithBindParameterLikeNames : function () {
var expected = { "@abc": "abc", "@@a": "a", "@bc": "bc", "@ax": "ax" };
var actual = AQL_EXECUTE("RETURN { [ '@abc' ] : 'abc', [ '@@a' ] : 'a', [ CONCAT('@', 'bc') ] : 'bc', [ PASSTHRU('@ax') ] : 'ax' }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with bind parameters
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesWithBindParameters : function () {
var expected = { "bind-abc": "xabc", "bind-a": "xa", "bind-bcde": "xbcde", "bind-ax": "xax" };
var actual = AQL_EXECUTE("RETURN { [ @abc ] : 'xabc', [ @a ] : 'xa', [ CONCAT(@bc, 'de') ] : 'xbcde', [ PASSTHRU(@ax) ] : 'xax' }", { abc: "bind-abc", "a" : "bind-a", "bc" : "bind-bc", "ax" : "bind-ax" });
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with Unicode
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesUmlaut : function () {
var expected = { "KÖTÖR": "kötör", "trötör": "tröt!", "mÄgensÄftwürzgemösch": "möglich", "FöR": "FöR", "sörtierung": "sörtierung" };
var actual = AQL_EXECUTE("RETURN { [ UPPER('kötör') ] : 'kötör', [ 'trötör' ] : 'tröt!', [ PASSTHRU('mÄgensÄftwürzgemösch') ] : 'möglich', [ CONCAT('F', 'ö', 'R') ] : 'FöR', [ PASSTHRU(LOWER('SÖRTIERUNG')) ] : 'sörtierung' }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with Unicode
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesHangul : function () {
var expected = { "코리아닷컴" : 1, "메일알리미" : 2 };
var query = "{ [ PASSTHRU('코리아닷컴') ] : 1, [ PASSTHRU('메일알리미') ] : 2 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with Unicode
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesChinese : function () {
var expected = { "中华网以中国的市场为核心" : 23, "致力为当地用户提供流动增值服务" : 99 };
var query = "{ [ PASSTHRU('中华网以中国的市场为核心') ] : 23, [ PASSTHRU('致力为当地用户提供流动增值服务') ] : 99 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with Unicode
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesRussian : function () {
var expected = { "Голкипер" : 1, "мадридского" : 2, "Икер Касильяс призвал" : 3 };
var query = "{ [ PASSTHRU('Голкипер') ] : 1, [ PASSTHRU('мадридского') ] : 2, [ PASSTHRU('Икер Касильяс призвал') ] : 3 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with Unicode
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesUnicodeMixed : function () {
var expected = { "დახმარებისთვის" : 1, "töröö !" : 2, "ジャパン は、イギリスのニュー・ウェーヴバンド。デヴィッド" : 3 };
var actual = AQL_EXECUTE("RETURN { [ PASSTHRU('დახმარებისთვის') ] : 1, [ PASSTHRU('töröö !') ] : 2, [ PASSTHRU('ジャパン は、イギリスのニュー・ウェーヴバンド。デヴィッド') ] : 3 }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with repeated attributes
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesRepeated : function () {
var expected = { FOO: 123, bar: 19 };
var query = "{ [ 'FOO' ] : 123, [ PASSTHRU('FOO') ] : 42, [ 'bar' ] : 19, [ PASSTHRU('FOO') ] : 23 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic mixed with regular
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesMixedWithRegular : function () {
var expected = { foo: 1, FOO: 2, bar: 3, baR: 4, foobar: 6 };
var query = "{ 'foo' : 1, [ 'FOO' ] : 2, 'bar' : 3, [ PASSTHRU('baR') ] : 4, [ PASSTHRU('bar') ] : 5, 'foobar' : 6 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test regular overwritten by dynamic
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesOverwritingRegular : function () {
var expected = { FOO: 2 };
var query = "{ FOO : 2, [ PASSTHRU('FOO') ] : 1 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic overwritten by regular
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesOverwrittenByRegular : function () {
var expected = { FOO: 1 };
var query = "{ [ PASSTHRU('FOO') ] : 1, FOO : 2 }";
checkResult(query, expected);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with for loop
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesWithFor : function () {
var expected = [ ];
for (var i = 1; i <= 100; ++i) {
var doc = { };
doc["test-value-" + i] = i;
expected.push(doc);
}
let actual = AQL_EXECUTE("FOR i IN 1..100 RETURN { [ CONCAT('test-value-', i) ] : i }");
assertEqual(expected, actual.json);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with for loop
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesWithNestedFor : function () {
var expected = [ ];
for (var i = 1; i <= 10; ++i) {
var doc = { };
doc["one-" + i] = i;
doc["two-23"] = 23;
expected.push(doc);
var doc2 = { };
doc2["one-" + i] = i;
doc2["two-42"] = 42;
expected.push(doc2);
}
var actual = AQL_EXECUTE("FOR i IN 1..10 FOR j IN [ 23, 42 ] RETURN { [ CONCAT('one-', i) ] : i, [ CONCAT('two-', j) ] : j }");
assertEqual(expected, actual.json);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test nested
////////////////////////////////////////////////////////////////////////////////
testNestedObjectsWithDynamicAttributes : function () {
var expected = {
foo: "bar",
bazbar: {
foo2: "foobar",
bazbar: {
2: 42,
4: 23
},
BAZBAR: "foofoofoo"
},
lastone: "done"
};
var actual = AQL_EXECUTE("RETURN { [ 'foo' ] : 'bar', [ CONCAT('baz', 'bar') ] : { foo2: 'foobar', [ 'bazbar' ] : { [ 1 + 1 ] : 42, [ 2 + 2 ] : 23 }, [ UPPER('bazbar') ] : LOWER('FOOFOOFOO') }, [ CONCAT('last', 'one') ] : 'done' }");
assertEqual(expected, actual.json[0]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic with conditional
////////////////////////////////////////////////////////////////////////////////
testDynamicAttributesConditional : function () {
var expected = [ ];
for (var i = 1; i <= 100; ++i) {
var doc = { };
if (i < 50) {
doc["whatever" + i] = i;
}
else {
doc[i + "something-completely-different"] = i * 2;
}
expected.push(doc);
}
var actual = AQL_EXECUTE("FOR i IN 1..100 RETURN { [ i < 50 ? CONCAT('whatever', i) : CONCAT(i, 'something-completely-different') ] : i < 50 ? i : i * 2 }");
assertEqual(expected, actual.json);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test dynamic explain
////////////////////////////////////////////////////////////////////////////////
testDynamicExplain : function () {
var expected = [ ];
for (var i = 1; i <= 100; ++i) {
var doc = { };
if (i < 50) {
doc["whatever" + i] = i;
}
else {
doc[i + "something-completely-different"] = i * 2;
}
expected.push(doc);
}
var plan = AQL_EXPLAIN("FOR i IN 1..100 RETURN { [ i < 50 ? CONCAT('whatever', i) : CONCAT(i, 'something-completely-different') ] : i < 50 ? i : i * 2 }", { }, { verbosePlans: true }).plan;
var actual = AQL_EXECUTEJSON(plan);
assertEqual(expected, actual.json);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlDynamicAttributesTestSuite);
return jsunity.done();