/*jshint globalstrict:false, strict:false, maxlen: 500 */ /*global assertEqual */ //////////////////////////////////////////////////////////////////////////////// /// @brief tests for query language, functions /// /// @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 internal = require("internal"); var errors = internal.errors; var jsunity = require("jsunity"); var helper = require("org/arangodb/aql-helper"); var getQueryResults = helper.getQueryResults; var assertQueryError = helper.assertQueryError; var assertQueryWarningAndNull = helper.assertQueryWarningAndNull; //////////////////////////////////////////////////////////////////////////////// /// @brief test suite //////////////////////////////////////////////////////////////////////////////// function ahuacatlCallApplyTestSuite () { return { //////////////////////////////////////////////////////////////////////////////// /// @brief test call function //////////////////////////////////////////////////////////////////////////////// testCall : function () { var data = [ [ "foo bar", [ "TRIM", " foo bar " ] ], [ "foo bar", [ "TRIM", " foo bar ", "\r\n \t" ] ], [ "..foo bar..", [ "TRIM", " ..foo bar.. " ] ], [ "foo bar", [ "TRIM", " ..foo bar.. ", ". " ] ], [ "foo", [ "LEFT", "foobarbaz", 3 ] ], [ "fooba", [ "LEFT", "foobarbaz", 5 ] ], [ "foob", [ "SUBSTRING", "foobarbaz", 0, 4 ] ], [ "oob", [ "SUBSTRING", "foobarbaz", 1, 3 ] ], [ "barbaz", [ "SUBSTRING", "foobarbaz", 3 ] ], [ "FOOBARBAZ", [ "UPPER", "foobarbaz" ] ], [ "foobarbaz", [ "lower", "FOOBARBAZ" ] ], [ "abcfood", [ "concat", "a", "b", "c", "foo", "d" ] ], [ 1, [ "flOoR", 1.6 ] ], [ 17, [ "MIN", [ 23, 42, 17 ] ] ], [ [ 1, 2, 3, 4, 7, 9, 10, 12 ], [ "UNION_DISTINCT", [ 1, 2, 3, 4 ], [ 9, 12 ], [ 2, 9, 7, 10 ] ] ], [ { a: true, b: false, c: null }, [ "ZIP", [ "a", "b", "c" ], [ true, false, null ] ] ] ]; data.forEach(function (d) { var actual = getQueryResults("RETURN CALL(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")"); assertEqual(d[0], actual[0], d); }); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test call function //////////////////////////////////////////////////////////////////////////////// testCallDynamic1 : function () { var actual = getQueryResults("FOR func IN [ 'TRIM', 'LOWER', 'UPPER' ] RETURN CALL(func, ' foObAr ')"); assertEqual(actual, [ 'foObAr', ' foobar ', ' FOOBAR ' ]); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test call function //////////////////////////////////////////////////////////////////////////////// testCallDynamic2 : function () { var actual = getQueryResults("FOR doc IN [ { value: ' foobar', func: 'TRIM' }, { value: 'FOOBAR', func: 'LOWER' }, { value: 'foobar', func: 'UPPER' } ] RETURN CALL(doc.func, doc.value)"); assertEqual(actual, [ 'foobar', 'foobar', 'FOOBAR' ]); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test call function //////////////////////////////////////////////////////////////////////////////// testCallNonExisting : function () { assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN CALL()"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('nono-existing', [ 'baz' ])"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('foobar', 'baz')"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL(' trim', 'baz')"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('foo::bar::baz', 'baz')"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL(123, 'baz')"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL([ ], 'baz')"); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test call function //////////////////////////////////////////////////////////////////////////////// testCallDisallowed : function () { assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN CALL('CALL')"); assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN CALL('APPLY')"); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test apply function //////////////////////////////////////////////////////////////////////////////// testApply : function () { var data = [ [ "foo bar", [ "TRIM", " foo bar " ] ], [ "foo bar", [ "TRIM", " foo bar ", "\r\n \t" ] ], [ "..foo bar..", [ "TRIM", " ..foo bar.. " ] ], [ "foo bar", [ "TRIM", " ..foo bar.. ", ". " ] ], [ "foo", [ "LEFT", "foobarbaz", 3 ] ], [ "fooba", [ "LEFT", "foobarbaz", 5 ] ], [ "foob", [ "SUBSTRING", "foobarbaz", 0, 4 ] ], [ "oob", [ "SUBSTRING", "foobarbaz", 1, 3 ] ], [ "barbaz", [ "SUBSTRING", "foobarbaz", 3 ] ], [ "FOOBARBAZ", [ "UPPER", "foobarbaz" ] ], [ "foobarbaz", [ "lower", "FOOBARBAZ" ] ], [ "abcfood", [ "concat", "a", "b", "c", "foo", "d" ] ], [ 1, [ "flOoR", 1.6 ] ], [ 17, [ "MIN", [ 23, 42, 17 ] ] ], [ [ 1, 2, 3, 4, 7, 9, 10, 12 ], [ "UNION_DISTINCT", [ 1, 2, 3, 4 ], [ 9, 12 ], [ 2, 9, 7, 10 ] ] ], [ { a: true, b: false, c: null }, [ "ZIP", [ "a", "b", "c" ], [ true, false, null ] ] ] ]; data.forEach(function (d) { var args = [ ]; for (var i = 1; i < d[1].length; ++i) { args.push(d[1][i]); } var actual = getQueryResults("RETURN APPLY(" + JSON.stringify(d[1][0]) + ", " + JSON.stringify(args) + ")"); assertEqual(d[0], actual[0], d); }); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test apply function //////////////////////////////////////////////////////////////////////////////// testApplyDynamic1 : function () { var actual = getQueryResults("FOR func IN [ 'TRIM', 'LOWER', 'UPPER' ] RETURN APPLY(func, [ ' foObAr ' ])"); assertEqual(actual, [ 'foObAr', ' foobar ', ' FOOBAR ' ]); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test apply function //////////////////////////////////////////////////////////////////////////////// testApplyDynamic2 : function () { var actual = getQueryResults("FOR doc IN [ { value: ' foobar', func: 'TRIM' }, { value: 'FOOBAR', func: 'LOWER' }, { value: 'foobar', func: 'UPPER' } ] RETURN APPLY(doc.func, [ doc.value ])"); assertEqual(actual, [ 'foobar', 'foobar', 'FOOBAR' ]); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test apply function //////////////////////////////////////////////////////////////////////////////// testApplyNonExisting : function () { assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPLY()"); assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN APPLY('TRIM', 1, 2)"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('nono-existing', [ 'baz' ])"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('foobar', [ 'baz' ])"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY(' trim', [ 'baz' ])"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('foo::bar::baz', [ 'baz' ])"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY(123, [ 'baz' ])"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY([ ], [ 'baz' ])"); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test apply function //////////////////////////////////////////////////////////////////////////////// testApplyDisallowed : function () { assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN APPLY('CALL')"); assertQueryError(errors.ERROR_QUERY_DISALLOWED_DYNAMIC_CALL.code, "RETURN APPLY('APPLY')"); } }; } //////////////////////////////////////////////////////////////////////////////// /// @brief test suite //////////////////////////////////////////////////////////////////////////////// function ahuacatlCallUserDefinedTestSuite () { var aqlfunctions = require("org/arangodb/aql/functions"); return { //////////////////////////////////////////////////////////////////////////////// /// @brief set up //////////////////////////////////////////////////////////////////////////////// setUp : function () { [ "add3", "add2", "call", "throwing" ].forEach(function (f) { try { aqlfunctions.unregister("UnitTests::func::" + f); } catch (err) { } }); aqlfunctions.register("UnitTests::func::add3", function (a, b, c) { return a + b + c; }); aqlfunctions.register("UnitTests::func::add2", function (a, b) { return a + b; }); aqlfunctions.register("UnitTests::func::call", function () { return undefined; }); aqlfunctions.register("UnitTests::func::throwing", function () { throw "doh!"; }); }, //////////////////////////////////////////////////////////////////////////////// /// @brief tear down //////////////////////////////////////////////////////////////////////////////// tearDown : function () { [ "add3", "add2", "call", "throwing" ].forEach(function (f) { try { aqlfunctions.unregister("UnitTests::func::" + f); } catch (err) { } }); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test call function //////////////////////////////////////////////////////////////////////////////// testCall : function () { var data = [ [ null, [ "UnitTests::func::call", 1234 ] ], [ null, [ "UnitTests::func::call", "foo", "bar" ] ], [ null, [ "UnitTests::func::add2" ] ], [ null, [ "UnitTests::func::add2", 23 ] ], [ 23, [ "UnitTests::func::add2", 23, null ] ], [ 65, [ "UnitTests::func::add2", 23, 42 ] ], [ null, [ "UnitTests::func::add3", 23 ] ], [ null, [ "UnitTests::func::add3", 23, 42 ] ], [ 65, [ "UnitTests::func::add3", 23, 42, null ] ], [ 120, [ "UnitTests::func::add3", 23, 42, 55 ] ], [ "65foo", [ "UnitTests::func::add3", 23, 42, "foo" ] ], [ "bar4213", [ "UnitTests::func::add3", "bar", 42, 13 ] ], [ 96, [ "UNITTESTS::FUNC::aDD3", -1, 42, 55 ] ], [ 96, [ "unittests::func::ADD3", -1, 42, 55 ] ] ]; data.forEach(function (d) { var actual = getQueryResults("RETURN CALL(" + d[1].map(function (v) { return JSON.stringify(v); }).join(", ") + ")"); assertEqual(d[0], actual[0], d); }); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test apply function //////////////////////////////////////////////////////////////////////////////// testApply : function () { var data = [ [ null, [ "UnitTests::func::call", 1234 ] ], [ null, [ "UnitTests::func::call", "foo", "bar" ] ], [ null, [ "UnitTests::func::add2" ] ], [ null, [ "UnitTests::func::add2", 23 ] ], [ 23, [ "UnitTests::func::add2", 23, null ] ], [ 65, [ "UnitTests::func::add2", 23, 42 ] ], [ null, [ "UnitTests::func::add3", 23 ] ], [ null, [ "UnitTests::func::add3", 23, 42 ] ], [ 65, [ "UnitTests::func::add3", 23, 42, null ] ], [ 120, [ "UnitTests::func::add3", 23, 42, 55 ] ], [ "65foo", [ "UnitTests::func::add3", 23, 42, "foo" ] ], [ "bar4213", [ "UnitTests::func::add3", "bar", 42, 13 ] ], [ 96, [ "UNITTESTS::FUNC::aDD3", -1, 42, 55 ] ], [ 96, [ "unittests::func::ADD3", -1, 42, 55 ] ] ]; data.forEach(function (d) { var args = [ ]; for (var i = 1; i < d[1].length; ++i) { args.push(d[1][i]); } var actual = getQueryResults("RETURN APPLY(" + JSON.stringify(d[1][0]) + ", " + JSON.stringify(args) + ")"); assertEqual(d[0], actual[0], d); }); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test non-existing functions //////////////////////////////////////////////////////////////////////////////// testNonExisting : function () { assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN CALL('UNITTESTS::FUNC::MEOW', 'baz')"); assertQueryError(errors.ERROR_QUERY_FUNCTION_NOT_FOUND.code, "RETURN APPLY('UNITTESTS::FUNC::MEOW', [ 'baz' ])"); }, //////////////////////////////////////////////////////////////////////////////// /// @brief test throwing function //////////////////////////////////////////////////////////////////////////////// testThrows : function () { assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN CALL('UNITTESTS::FUNC::THROWING')"); assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_RUNTIME_ERROR.code, "RETURN APPLY('UNITTESTS::FUNC::THROWING', [ ])"); } }; } //////////////////////////////////////////////////////////////////////////////// /// @brief executes the test suite //////////////////////////////////////////////////////////////////////////////// jsunity.run(ahuacatlCallApplyTestSuite); jsunity.run(ahuacatlCallUserDefinedTestSuite); return jsunity.done(); // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" // End: