1
0
Fork 0
arangodb/js/client/tests/agency/agency-test.js

488 lines
22 KiB
JavaScript

/*jshint globalstrict:false, strict:true */
/*global assertEqual, ARGUMENTS */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for client-specific functionality
///
/// @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 Max Neunhoeffer
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var wait = require("internal").wait;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function agencyTestSuite () {
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// @brief the agency servers
////////////////////////////////////////////////////////////////////////////////
var agencyServers = ARGUMENTS[0].split(" ");
var whoseTurn = 0;
var request = require("@arangodb/request");
function readAgency(list) {
// We simply try all agency servers in turn until one gives us an HTTP
// response:
var res = request({url: agencyServers[whoseTurn] + "/_api/agency/read", method: "POST",
followRedirects: true, body: JSON.stringify(list),
headers: {"Content-Type": "application/json"}});
res.bodyParsed = JSON.parse(res.body);
return res;
}
function writeAgency(list) {
// We simply try all agency servers in turn until one gives us an HTTP
// response:
var res = request({url: agencyServers[whoseTurn] + "/_api/agency/write", method: "POST",
followRedirects: true, body: JSON.stringify(list),
headers: {"Content-Type": "application/json",
"x-arangodb-agency-mode": "waitForCommitted"}});
res.bodyParsed = JSON.parse(res.body);
return res;
}
function readAndCheck(list) {
var res = readAgency(list);
assertEqual(res.statusCode, 200);
return res.bodyParsed;
}
function writeAndCheck(list) {
var res = writeAgency(list);
assertEqual(res.statusCode, 200);
}
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test to write a single top level key
////////////////////////////////////////////////////////////////////////////////
testSingleTopLevel : function () {
wait(2);
assertEqual(readAndCheck([["/x"]]), [{}]);
writeAndCheck([[{x:12}]]);
assertEqual(readAndCheck([["/x"]]), [{x:12}]);
writeAndCheck([[{x:{"op":"delete"}}]]);
assertEqual(readAndCheck([["/x"]]), [{}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test to write a single non-top level key
////////////////////////////////////////////////////////////////////////////////
testSingleNonTopLevel : function () {
assertEqual(readAndCheck([["/x/y"]]), [{}]);
writeAndCheck([[{"x/y":12}]]);
assertEqual(readAndCheck([["/x/y"]]), [{x:{y:12}}]);
writeAndCheck([[{"x/y":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/x"]]), [{x:{}}]);
writeAndCheck([[{"x":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/x"]]), [{}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test preconditions
////////////////////////////////////////////////////////////////////////////////
testPrecondition : function () {
writeAndCheck([[{"/a":12}]]);
assertEqual(readAndCheck([["/a"]]), [{a:12}]);
writeAndCheck([[{"/a":13},{"/a":12}]]);
assertEqual(readAndCheck([["/a"]]), [{a:13}]);
var res = writeAgency([[{"/a":14},{"/a":12}]]); // fail precond {a:12}
assertEqual(res.statusCode, 412);
assertEqual(res.bodyParsed, {"results":[0]});
writeAndCheck([[{a:{op:"delete"}}]]);
// fail precond oldEmpty
res = writeAgency([[{"a":14},{"a":{"oldEmpty":false}}]]);
assertEqual(res.statusCode, 412);
assertEqual(res.bodyParsed, {"results":[0]});
writeAndCheck([[{"a":14},{"a":{"oldEmpty":true}}]]); // precond oldEmpty
writeAndCheck([[{"a":14},{"a":{"old":14}}]]); // precond old
// fail precond old
res = writeAgency([[{"a":14},{"a":{"old":13}}]]);
assertEqual(res.statusCode, 412);
assertEqual(res.bodyParsed, {"results":[0]});
writeAndCheck([[{"a":14},{"a":{"isArray":false}}]]); // precond isArray
// fail precond isArray
res = writeAgency([[{"a":14},{"a":{"isArray":true}}]]);
assertEqual(res.statusCode, 412);
assertEqual(res.bodyParsed, {"results":[0]});
// check object precondition
res = writeAgency([[{"/a/b/c":{"op":"set","new":12}}]]);
res = writeAgency([[{"/a/b/c":{"op":"set","new":13}},{"a":{"b":{"c":12}}}]]);
assertEqual(res.statusCode, 200);
res = writeAgency([[{"/a/b/c":{"op":"set","new":14}},{"/a":{"old":{"b":{"c":12}}}}]]);
assertEqual(res.statusCode, 412);
res = writeAgency([[{"/a/b/c":{"op":"set","new":14}},{"/a":{"old":{"b":{"c":13}}}}]]);
assertEqual(res.statusCode, 200);
// multiple preconditions
res = writeAgency([[{"/a":1,"/b":true,"/c":"c"},{"/a":{"oldEmpty":false}}]]);
assertEqual(readAndCheck([["/a","/b","c"]]), [{a:1,b:true,c:"c"}]);
res = writeAgency([[{"/a":2},{"/a":{"oldEmpty":false},"/b":{"oldEmpty":true}}]]);
assertEqual(res.statusCode, 412);
assertEqual(readAndCheck([["/a"]]), [{a:1}]);
res = writeAgency([[{"/a":2},{"/a":{"oldEmpty":true},"/b":{"oldEmpty":false}}]]);
assertEqual(res.statusCode, 412);
assertEqual(readAndCheck([["/a"]]), [{a:1}]);
res = writeAgency([[{"/a":2},{"/a":{"oldEmpty":false},"/b":{"oldEmpty":false},"/c":{"oldEmpty":true}}]]);
assertEqual(res.statusCode, 412);
assertEqual(readAndCheck([["/a"]]), [{a:1}]);
res = writeAgency([[{"/a":2},{"/a":{"oldEmpty":false},"/b":{"oldEmpty":false},"/c":{"oldEmpty":false}}]]);
assertEqual(res.statusCode, 200);
assertEqual(readAndCheck([["/a"]]), [{a:2}]);
res = writeAgency([[{"/a":3},{"/a":{"old":2},"/b":{"oldEmpty":false},"/c":{"oldEmpty":false}}]]);
assertEqual(res.statusCode, 200);
assertEqual(readAndCheck([["/a"]]), [{a:3}]);
res = writeAgency([[{"/a":2},{"/a":{"old":2},"/b":{"oldEmpty":false},"/c":{"oldEmpty":false}}]]);
assertEqual(res.statusCode, 412);
assertEqual(readAndCheck([["/a"]]), [{a:3}]);
res = writeAgency([[{"/a":2},{"/a":{"old":3},"/b":{"oldEmpty":false},"/c":{"isArray":true}}]]);
assertEqual(res.statusCode, 412);
assertEqual(readAndCheck([["/a"]]), [{a:3}]);
res = writeAgency([[{"/a":2},{"/a":{"old":3},"/b":{"oldEmpty":false},"/c":{"isArray":false}}]]);
assertEqual(res.statusCode, 200);
assertEqual(readAndCheck([["/a"]]), [{a:2}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test document/transaction assignment
////////////////////////////////////////////////////////////////////////////////
testDocument : function () {
writeAndCheck([[{"a":{"b":{"c":[1,2,3]},"e":12},"d":false}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test multiple transaction
////////////////////////////////////////////////////////////////////////////////
testTransaction : function () {
writeAndCheck([[{"a":{"b":{"c":[1,2,4]},"e":12},"d":false}],
[{"a":{"b":{"c":[1,2,3]}}}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "new" operator
////////////////////////////////////////////////////////////////////////////////
testOpSetNew : function () {
writeAndCheck([[{"a/z":{"op":"set","new":12}}]]);
assertEqual(readAndCheck([["a/z"]]), [{"a":{"z":12}}]);
writeAndCheck([[{"a/y":{"op":"set","new":12, "ttl": 1}}]]);
assertEqual(readAndCheck([["a/y"]]), [{"a":{"y":12}}]);
wait(1.250);
assertEqual(readAndCheck([["a/y"]]), [{a:{}}]);
writeAndCheck([[{"a/y":{"op":"set","new":12, "ttl": 1}}]]);
writeAndCheck([[{"a/y":{"op":"set","new":12}}]]);
assertEqual(readAndCheck([["a/y"]]), [{"a":{"y":12}}]);
wait(1.250);
assertEqual(readAndCheck([["a/y"]]), [{"a":{"y":12}}]);
writeAndCheck([[{"foo/bar":{"op":"set","new":{"baz":12}}}]]);
assertEqual(readAndCheck([["/foo/bar/baz"]]), [{"foo":{"bar":{"baz":12}}}]);
assertEqual(readAndCheck([["/foo/bar"]]), [{"foo":{"bar":{"baz":12}}}]);
assertEqual(readAndCheck([["/foo"]]), [{"foo":{"bar":{"baz":12}}}]);
writeAndCheck([[{"foo/bar":{"op":"set","new":{"baz":12},"ttl":1}}]]);
wait(1.250);
assertEqual(readAndCheck([["/foo"]]), [{"foo":{}}]);
assertEqual(readAndCheck([["/foo/bar"]]), [{"foo":{}}]);
assertEqual(readAndCheck([["/foo/bar/baz"]]), [{"foo":{}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "push" operator
////////////////////////////////////////////////////////////////////////////////
testOpPush : function () {
writeAndCheck([[{"/a/b/c":{"op":"push","new":"max"}}]]);
assertEqual(readAndCheck([["/a/b/c"]]), [{a:{b:{c:[1,2,3,"max"]}}}]);
writeAndCheck([[{"/a/euler":{"op":"push","new":2.71828182845904523536}}]]);
assertEqual(readAndCheck([["/a/euler"]]),
[{a:{euler:[2.71828182845904523536]}}]);
writeAndCheck([[{"/a/euler":{"op":"set","new":2.71828182845904523536}}]]);
assertEqual(readAndCheck([["/a/euler"]]),
[{a:{euler:2.71828182845904523536}}]);
writeAndCheck([[{"/a/euler":{"op":"push","new":2.71828182845904523536}}]]);
assertEqual(readAndCheck([["/a/euler"]]),
[{a:{euler:[2.71828182845904523536]}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "remove" operator
////////////////////////////////////////////////////////////////////////////////
testOpRemove : function () {
writeAndCheck([[{"/a/euler":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/a/euler"]]), [{a:{}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "prepend" operator
////////////////////////////////////////////////////////////////////////////////
testOpPrepend : function () {
writeAndCheck([[{"/a/b/c":{"op":"prepend","new":3.141592653589793}}]]);
assertEqual(readAndCheck([["/a/b/c"]]),
[{a:{b:{c:[3.141592653589793,1,2,3,"max"]}}}]);
writeAndCheck(
[[{"/a/euler":{"op":"prepend","new":2.71828182845904523536}}]]);
assertEqual(readAndCheck([["/a/euler"]]),
[{a:{euler:[2.71828182845904523536]}}]);
writeAndCheck(
[[{"/a/euler":{"op":"set","new":2.71828182845904523536}}]]);
assertEqual(readAndCheck([["/a/euler"]]),
[{a:{euler:2.71828182845904523536}}]);
writeAndCheck(
[[{"/a/euler":{"op":"prepend","new":2.71828182845904523536}}]]);
assertEqual(readAndCheck(
[["/a/euler"]]), [{a:{euler:[2.71828182845904523536]}}]);
writeAndCheck([[{"/a/euler":{"op":"prepend","new":1.25}}]]);
assertEqual(readAndCheck([["/a/euler"]]),
[{a:{euler:[1.25,2.71828182845904523536]}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "shift" operator
////////////////////////////////////////////////////////////////////////////////
testOpShift : function () {
writeAndCheck([[{"/a/f":{"op":"shift"}}]]); // none before
assertEqual(readAndCheck([["/a/f"]]), [{a:{f:[]}}]);
writeAndCheck([[{"/a/e":{"op":"shift"}}]]); // on empty array
assertEqual(readAndCheck([["/a/f"]]), [{a:{f:[]}}]);
writeAndCheck([[{"/a/b/c":{"op":"shift"}}]]); // on existing array
assertEqual(readAndCheck([["/a/b/c"]]), [{a:{b:{c:[1,2,3,"max"]}}}]);
writeAndCheck([[{"/a/b/d":{"op":"shift"}}]]); // on existing scalar
assertEqual(readAndCheck([["/a/b/d"]]), [{a:{b:{d:[]}}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "pop" operator
////////////////////////////////////////////////////////////////////////////////
testOpPop : function () {
writeAndCheck([[{"/a/f":{"op":"pop"}}]]); // none before
assertEqual(readAndCheck([["/a/f"]]), [{a:{f:[]}}]);
writeAndCheck([[{"/a/e":{"op":"pop"}}]]); // on empty array
assertEqual(readAndCheck([["/a/f"]]), [{a:{f:[]}}]);
writeAndCheck([[{"/a/b/c":{"op":"pop"}}]]); // on existing array
assertEqual(readAndCheck([["/a/b/c"]]), [{a:{b:{c:[1,2,3]}}}]);
writeAndCheck([[{"a/b/d":1}]]); // on existing scalar
writeAndCheck([[{"/a/b/d":{"op":"pop"}}]]); // on existing scalar
assertEqual(readAndCheck([["/a/b/d"]]), [{a:{b:{d:[]}}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "increment" operator
////////////////////////////////////////////////////////////////////////////////
testOpIncrement : function () {
writeAndCheck([[{"/version":{"op":"delete"}}]]);
writeAndCheck([[{"/version":{"op":"increment"}}]]); // none before
assertEqual(readAndCheck([["version"]]), [{version:1}]);
writeAndCheck([[{"/version":{"op":"increment"}}]]); // int before
assertEqual(readAndCheck([["version"]]), [{version:2}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "decrement" operator
////////////////////////////////////////////////////////////////////////////////
testOpDecrement : function () {
writeAndCheck([[{"/version":{"op":"delete"}}]]);
writeAndCheck([[{"/version":{"op":"decrement"}}]]); // none before
assertEqual(readAndCheck([["version"]]), [{version:-1}]);
writeAndCheck([[{"/version":{"op":"decrement"}}]]); // int before
assertEqual(readAndCheck([["version"]]), [{version:-2}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test "op" keyword in other places than as operator
////////////////////////////////////////////////////////////////////////////////
testOpInStrangePlaces : function () {
writeAndCheck([[{"/op":12}]]);
assertEqual(readAndCheck([["/op"]]), [{op:12}]);
writeAndCheck([[{"/op":{op:"delete"}}]]);
writeAndCheck([[{"/op/a/b/c":{"op":"set","new":{"op":13}}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:13}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"increment"}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:14}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"decrement"}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:13}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"pop"}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:[]}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"increment"}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:1}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"shift"}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:[]}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"decrement"}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:-1}}}}}]);
writeAndCheck([[{"/op/a/b/c/op":{"op":"push","new":-1}}]]);
assertEqual(readAndCheck([["/op/a/b/c"]]), [{op:{a:{b:{c:{op:[-1]}}}}}]);
writeAndCheck([[{"/op/a/b/d":{"op":"set","new":{"ttl":14}}}]]);
assertEqual(readAndCheck([["/op/a/b/d"]]), [{op:{a:{b:{d:{ttl:14}}}}}]);
writeAndCheck([[{"/op/a/b/d/ttl":{"op":"increment"}}]]);
assertEqual(readAndCheck([["/op/a/b/d"]]), [{op:{a:{b:{d:{ttl:15}}}}}]);
writeAndCheck([[{"/op/a/b/d/ttl":{"op":"decrement"}}]]);
assertEqual(readAndCheck([["/op/a/b/d"]]), [{op:{a:{b:{d:{ttl:14}}}}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief op delete on top node
////////////////////////////////////////////////////////////////////////////////
testOperatorsOnRootNode : function () {
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
writeAndCheck([[{"/":{"op":"increment"}}]]);
assertEqual(readAndCheck([["/"]]), [1]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck([[{"/":{"op":"decrement"}}]]);
assertEqual(readAndCheck([["/"]]), [-1]);
writeAndCheck([[{"/":{"op":"push","new":"Hello"}}]]);
assertEqual(readAndCheck([["/"]]), [["Hello"]]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck([[{"/":{"op":"push","new":"Hello"}}]]);
assertEqual(readAndCheck([["/"]]), [["Hello"]]);
writeAndCheck([[{"/":{"op":"pop"}}]]);
assertEqual(readAndCheck([["/"]]), [[]]);
writeAndCheck([[{"/":{"op":"pop"}}]]);
assertEqual(readAndCheck([["/"]]), [[]]);
writeAndCheck([[{"/":{"op":"push","new":"Hello"}}]]);
assertEqual(readAndCheck([["/"]]), [["Hello"]]);
writeAndCheck([[{"/":{"op":"shift"}}]]);
assertEqual(readAndCheck([["/"]]), [[]]);
writeAndCheck([[{"/":{"op":"shift"}}]]);
assertEqual(readAndCheck([["/"]]), [[]]);
writeAndCheck([[{"/":{"op":"prepend","new":"Hello"}}]]);
assertEqual(readAndCheck([["/"]]), [["Hello"]]);
writeAndCheck([[{"/":{"op":"shift"}}]]);
assertEqual(readAndCheck([["/"]]), [[]]);
writeAndCheck([[{"/":{"op":"pop"}}]]);
assertEqual(readAndCheck([["/"]]), [[]]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
assertEqual(readAndCheck([["/"]]), [{}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test that order should not matter
////////////////////////////////////////////////////////////////////////////////
testOrder : function () {
writeAndCheck([[{"a":{"b":{"c":[1,2,3]},"e":12},"d":false}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck([[{"d":false, "a":{"b":{"c":[1,2,3]},"e":12}}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
writeAndCheck([[{"d":false, "a":{"e":12,"b":{"c":[1,2,3]}}}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
writeAndCheck([[{"d":false, "a":{"e":12,"b":{"c":[1,2,3]}}}]]);
assertEqual(readAndCheck([["a/e"],["a/b","d"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test nasty willful attempt to break
////////////////////////////////////////////////////////////////////////////////
testOrderEvil : function () {
writeAndCheck([[{"a":{"b":{"c":[1,2,3]},"e":12},"d":false}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck([[{"d":false, "a":{"b":{"c":[1,2,3]},"e":12}}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
writeAndCheck([[{"d":false, "a":{"e":12,"b":{"c":[1,2,3]}}}]]);
assertEqual(readAndCheck([["a/e"],[ "d","a/b"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
writeAndCheck([[{"d":false, "a":{"e":12,"b":{"c":[1,2,3]}}}]]);
assertEqual(readAndCheck([["a/e"],["a/b","d"]]),
[{a:{e:12}},{a:{b:{c:[1,2,3]},d:false}}]);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief Test nasty willful attempt to break
////////////////////////////////////////////////////////////////////////////////
testSlashORama : function () {
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck([[{"//////////////////////a/////////////////////b//":
{"b///////c":4}}]]);
assertEqual(readAndCheck([["/"]]), [{a:{b:{b:{c:4}}}}]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck([[{"////////////////////////": "Hi there!"}]]);
assertEqual(readAndCheck([["/"]]), ["Hi there!"]);
writeAndCheck([[{"/":{"op":"delete"}}]]);
writeAndCheck(
[[{"/////////////////\\/////a/////////////^&%^&$^&%$////////b\\\n//":
{"b///////c":4}}]]);
assertEqual(readAndCheck([["/"]]),
[{"\\":{"a":{"^&%^&$^&%$":{"b\\\n":{"b":{"c":4}}}}}}]);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(agencyTestSuite);
return jsunity.done();