1
0
Fork 0
arangodb/js/server/tests/shell/shell-cluster-agency-commun...

1379 lines
44 KiB
JavaScript

/*jshint globalstrict:false, strict:false */
/*global fail, assertEqual, assertTrue, assertFalse, assertUndefined, assertNotUndefined*/
////////////////////////////////////////////////////////////////////////////////
/// @brief test the agency communication layer
///
/// @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 Michael Hackstein
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var _ = require("lodash");
var createResult = function(prefixes, list) {
'use strict';
var prefix = prefixes.join("/") + "/";
var res = {};
_.each(list, function(v, k) {
res[prefix + k] = v;
});
return res;
};
var Communication = require("@arangodb/cluster/agency-communication");
var comm;
var dummy;
var ips;
var agencyRoutes = {
vision: "Vision",
target: "Target",
plan: "Plan",
current: "Current",
sync: "Sync",
sub: {
servers: "DBServers",
databases: "Databases",
coords: "Coordinators",
colls: "Collections",
mapToE: "MapIDToEndpoint",
registered: "ServersRegistered",
beat: "ServerStates",
interval: "HeartbeatIntervalMs"
}
};
var resetToDefault = function() {
'use strict';
var dbServers = {
"pavel": "sandro",
"paul": "sally",
"patricia": "sandra"
};
var coordinators = {
"cindy": "none",
"carlos": "none",
"charly": "none"
};
var databases = ["_system", "z_db", "a_db", "b_db"];
var vInfo = {
status: "loaded",
shardKeys: ["_key"],
name: "v",
shards: {
v1: "pavel",
v2: "paul",
v3: "patricia",
v4: "pavel",
v5: "patricia",
v6: "pavel"
}
};
var collections = {
_system: {
"98213": {name: "_graphs"},
"87123": vInfo,
"89123": {name: "e"}
},
a_db: {
"11235": {name: "s"},
"6512": {name: "a"},
"123": {name: "d"}
},
current: {
_system: {
"98213": {
"sg1": {},
"sg2": {},
"sg3": {}
},
"87123": {
"sv1": {},
"sv2": {},
"sv3": {}
},
"89123": {
"se1": {},
"se2": {},
"se3": {}
}
},
a_db: {
"11235": {
"s01": {},
"s02": {},
"s03": {}
},
"6512": {
"s11": {},
"s12": {},
"s13": {}
},
"123": {
"s21": {},
"s22": {},
"s23": {}
}
}
}
};
ips = {
"pavel": {endpoint: "tcp://192.168.0.1:8529"},
"paul": {endpoint: "tcp://192.168.0.2:8529"},
"patricia": {endpoint: "tcp://192.168.0.3:8529"},
"sandro": {endpoint: "tcp://192.168.0.4:8529"},
"sally": {endpoint: "tcp://192.168.0.5:8529"},
"sandra": {endpoint: "tcp://192.168.0.6:8529"},
"carlos": {endpoint: "tcp://192.168.1.1:8529"},
"charly": {endpoint: "tcp://192.168.1.2:8529"},
"cindy": {endpoint: "tcp://192.168.1.3:8529"}
};
var heartbeats = {
pavel: {
status: "SERVINGSYNC",
time: (new Date()).toISOString()
},
paul: {
status: "SERVINGSYNC",
time: (new Date()).toISOString()
},
patricia: {
status: "SERVINGASYNC",
time: (new Date()).toISOString()
},
sandro: {
status: "INSYNC",
time: (new Date()).toISOString()
},
sandra: {
status: "SYNCING",
time: (new Date()).toISOString()
},
sally: {
status: "INSYNC",
time: (new Date()).toISOString()
}
};
dummy = {};
dummy.target = {};
dummy.target.servers = createResult([agencyRoutes.target, agencyRoutes.sub.servers], dbServers);
dummy.target.coordinators = createResult([agencyRoutes.target, agencyRoutes.sub.coords], coordinators);
dummy.target.databases = databases;
dummy.target.syscollections = createResult([agencyRoutes.target,
agencyRoutes.sub.databases,
agencyRoutes.sub.colls,
"_system"], collections._system);
dummy.target.acollections = createResult([agencyRoutes.target,
agencyRoutes.sub.databases,
agencyRoutes.sub.colls,
"a_db"],
collections.a_db);
dummy.target.vInfo = vInfo;
dummy.plan = {};
dummy.plan.servers = createResult([agencyRoutes.plan, agencyRoutes.sub.servers], dbServers);
dummy.plan.coordinators = createResult([agencyRoutes.plan, agencyRoutes.sub.coords], coordinators);
dummy.plan.databases = databases;
dummy.plan.syscollections = createResult([agencyRoutes.plan,
agencyRoutes.sub.databases,
agencyRoutes.sub.colls,
"_system"],
collections._system);
dummy.plan.acollections = createResult([agencyRoutes.plan,
agencyRoutes.sub.databases,
agencyRoutes.sub.colls,
"a_db"],
collections.a_db);
dummy.plan.vInfo = vInfo;
dummy.current = {};
dummy.current.servers = createResult([agencyRoutes.current, agencyRoutes.sub.servers], dbServers);
dummy.current.coordinators = createResult([agencyRoutes.current, agencyRoutes.sub.coords], coordinators);
dummy.current.registered = createResult([agencyRoutes.current, agencyRoutes.sub.registered], ips);
dummy.current.databases = databases;
dummy.current.syscollections = createResult([agencyRoutes.current,
agencyRoutes.sub.databases,
agencyRoutes.sub.colls,
"_system"],
collections.current._system);
dummy.current.acollections = createResult([agencyRoutes.current,
agencyRoutes.sub.databases,
agencyRoutes.sub.colls,
"a_db"],
collections.current.a_db);
dummy.current.vInfo = vInfo;
dummy.sync = {};
dummy.sync.heartbeats = heartbeats;
dummy.sync.heartbeats = createResult([agencyRoutes.registered, agencyRoutes.sub.beat], heartbeats);
dummy.sync.interval = "1000";
};
var setup = function() {
'use strict';
resetToDefault();
comm = new Communication.Communication();
};
var teardown = function() {};
var agencyMock = {
get: function(route, recursive) {
'use strict';
var parts = route.split("/");
var res;
var returnResult = function(base) {
if (parts[1] === agencyRoutes.sub.servers && recursive) {
return base.servers;
}
if (parts[1] === agencyRoutes.sub.coords && recursive) {
return base.coordinators;
}
if (parts[1] === agencyRoutes.sub.colls) {
if (recursive) {
if (parts[2] === "_system") {
return base.syscollections;
}
if (parts[2] === "a_db") {
return base.acollections;
}
if (parts[2] === "b_db") {
return {};
}
if (parts[2] === "z_db") {
return {};
}
} else {
if (parts[2] === "_system" && parts[3] === "87123") {
var internalResult = {};
internalResult[route] = base.vInfo;
return internalResult;
}
}
}
};
switch (parts[0]) {
case agencyRoutes.target:
if (parts[1] === agencyRoutes.sub.mapToE) {
res = ips[parts[2]];
if (!res) {
fail("Could not find IP of: " + parts[2]);
}
return res;
}
res = returnResult(dummy.target);
if (res) {
return res;
}
break;
case agencyRoutes.plan:
res = returnResult(dummy.plan);
if (res) {
return res;
}
break;
case agencyRoutes.current:
res = returnResult(dummy.current);
if (res) {
return res;
}
if (parts[1] === agencyRoutes.sub.registered && recursive) {
return dummy.current.registered;
}
break;
case agencyRoutes.sync:
if (parts[1] === agencyRoutes.sub.beat && recursive) {
return dummy.sync.heartbeats;
}
if (parts[1] === agencyRoutes.sub.interval) {
res = {};
res[route] = dummy.sync.interval;
return res;
}
break;
default:
fail("Requested route: GET " + route);
}
fail("Requested route: GET " + route);
},
list: function(route, recursive, flat) {
'use strict';
var parts = route.split("/");
var returnResult = function(route) {
if (parts[1] === agencyRoutes.sub.databases) {
return route.databases;
}
if (parts[1] === agencyRoutes.sub.colls) {
return _.map(route.databases, function(d) {
return route + "/" + d;
});
}
if (parts[1] === agencyRoutes.sub.coords) {
return _.keys(route.coordinators);
}
};
if (!flat) {
fail("List is not requested flat");
}
var res;
switch (parts[0]) {
case agencyRoutes.target:
res = returnResult(dummy.target);
if (res) {
return res;
}
break;
case agencyRoutes.plan:
res = returnResult(dummy.plan);
if (res) {
return res;
}
break;
case agencyRoutes.current:
res = returnResult(dummy.current);
if (res) {
return res;
}
break;
default:
fail("Requested route: LIST " + route);
}
}
};
Communication._createAgency = function() {
'use strict';
return agencyMock;
};
function runTargetTests(test) {
'use strict';
function DBServersSuite() {
var targetServers;
return {
setUp: function() {
setup();
targetServers = comm.target.DBServers();
},
tearDown: teardown,
testGetServerList: function() {
var expected = {
pavel: {
role: "primary",
secondary: "sandro"
},
paul: {
role: "primary",
secondary: "sally"
},
patricia: {
role: "primary",
secondary: "sandra"
},
sandro: {
role: "secondary"
},
sally: {
role: "secondary"
},
sandra: {
role: "secondary"
}
};
var res = targetServers.getList();
assertEqual(res, expected);
},
testAddNewPrimaryServer: function() {
var name = "pancho";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, "none");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(targetServers.addPrimary(name), "Failed to insert a new primary");
assertTrue(wasCalled, "Agency has not been informed to insert primary.");
var newList = targetServers.getList();
assertNotUndefined(newList[name]);
assertEqual(newList[name].role, "primary");
assertUndefined(newList[name].secondary);
},
testAddNewSecondaryServer: function() {
var name = "pancho";
var secName = "samuel";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, "none");
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(targetServers.addPrimary(name), "Failed to insert a new primary");
assertTrue(wasCalled, "Agency has not been informed to insert primary.");
wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, secName);
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(targetServers.addSecondary(secName, name), "Failed to insert a new secondary");
assertTrue(wasCalled, "Agency has not been informed to insert secondary.");
var newList = targetServers.getList();
assertNotUndefined(newList[name]);
assertEqual(newList[name].role, "primary");
assertEqual(newList[name].secondary, secName);
assertNotUndefined(newList[secName]);
assertEqual(newList[secName].role, "secondary");
},
testAddNewServerPair: function() {
var name = "pancho";
var secName = "samuel";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, secName);
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(targetServers.addPair(name, secName), "Failed to insert a new primary/secondary pair");
assertTrue(wasCalled, "Agency has not been informed to insert the new pair.");
var newList = targetServers.getList();
assertNotUndefined(newList[name]);
assertEqual(newList[name].role, "primary");
assertEqual(newList[name].secondary, secName);
assertNotUndefined(newList[secName]);
assertEqual(newList[secName].role, "secondary");
},
testRemovePrimaryServer: function() {
var name = "pavel";
var secondaryName = "sandro";
var setWasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, secondaryName].join("/"));
assertEqual(value, "none");
assertFalse(setWasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
setWasCalled = true;
return true;
};
var delWasCalled = false;
agencyMock.remove = function(route) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertFalse(delWasCalled, "Delete has been called multiple times");
delete dummy.target.servers[route];
delWasCalled = true;
return true;
};
assertTrue(targetServers.removeServer(name), "Failed to remove a primary server");
assertTrue(setWasCalled, "Agency has not been informed to replace the primary with the secondary.");
assertTrue(delWasCalled, "Agency has not been informed to remove the primary/secondary pair.");
var newList = targetServers.getList();
assertUndefined(newList[name]);
assertNotUndefined(newList[secondaryName]);
assertEqual(newList[secondaryName].role, "primary");
assertUndefined(newList[secondaryName].secondary);
},
testRemoveSecondaryServer: function() {
var name = "sandro";
var pName = "pavel";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, pName].join("/"));
assertEqual(value, "none");
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(targetServers.removeServer(name), "Failed to remove a secondary server.");
assertTrue(wasCalled, "Agency has not been informed to update the primary server.");
var newList = targetServers.getList();
assertUndefined(newList[name]);
assertNotUndefined(newList[pName]);
assertEqual(newList[pName].role, "primary");
assertUndefined(newList[pName].secondary);
}
};
}
function CoordinatorSuite() {
var targetCoordinators;
return {
setUp: function() {
setup();
targetCoordinators = comm.target.Coordinators();
},
tearDown: teardown,
testGetCoordinatorList: function() {
var list = {
"carlos": {"role": "primary"},
"charly": {"role": "primary"},
"cindy": {"role": "primary"}
};
assertEqual(targetCoordinators.getList(), list);
},
testAddCoordinator: function() {
var name = "carol";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.coords, name].join("/"));
assertEqual(value, "none");
dummy.target.coordinators[route] = value;
wasCalled = true;
return true;
};
assertTrue(targetCoordinators.add(name), "Failed to insert a new coordinator.");
assertTrue(wasCalled, "Agency has not been informed to insert coordinator.");
var list = {
"carlos": {"role": "primary"},
"charly": {"role": "primary"},
"cindy": {"role": "primary"}
};
list[name] = {"role": "primary"};
assertEqual(targetCoordinators.getList(), list);
},
testRemoveCoordinator: function() {
var name = "cindy";
var delWasCalled = false;
agencyMock.remove = function(route) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.coords, name].join("/"));
assertFalse(delWasCalled, "Delete has been called multiple times");
delete dummy.target.coordinators[route];
delWasCalled = true;
return true;
};
assertTrue(targetCoordinators.remove(name), "Failed to remove a coordinator.");
assertTrue(delWasCalled, "Agency has not been informed to remove a coordinator.");
var list = {
"carlos": {"role": "primary"},
"charly": {"role": "primary"},
};
assertEqual(targetCoordinators.getList(), list);
}
};
}
function DataSuite() {
var dbs;
return {
setUp: function() {
setup();
dbs = comm.target.Databases();
},
tearDown: teardown,
testGetDatabaseList: function() {
var list = [
"_system",
"a_db",
"b_db",
"z_db"
].sort();
assertEqual(dbs.getList(), list);
},
testGetCollectionListForDatabase: function() {
var syslist = [
"_graphs",
"v",
"e"
].sort();
var alist = [
"s",
"a",
"d"
].sort();
assertEqual(dbs.select("_system").getCollections(), syslist);
assertEqual(dbs.select("a_db").getCollections(), alist);
},
testSelectNotExistingDatabase: function() {
assertFalse(dbs.select("foxx"));
},
testGetCollectionMetaInfo: function() {
var sysdb = dbs.select("_system");
assertEqual(sysdb.collection("v").info(), dummy.target.vInfo);
},
testGetResponsibilitiesForCollection: function() {
var colV = dbs.select("_system").collection("v");
var expected = {
v1: "pavel",
v2: "paul",
v3: "patricia",
v4: "pavel",
v5: "patricia",
v6: "pavel"
};
assertEqual(colV.getShards(), expected);
},
testGetShardsForServer: function() {
var colV = dbs.select("_system").collection("v");
assertEqual(colV.getShardsForServer("pavel"), ["v1", "v4", "v6"].sort());
assertEqual(colV.getShardsForServer("paul"), ["v2"].sort());
assertEqual(colV.getShardsForServer("patricia"), ["v3", "v5"].sort());
},
testGetServerForShard: function() {
var colV = dbs.select("_system").collection("v");
assertEqual(colV.getServerForShard("v1"), "pavel");
assertEqual(colV.getServerForShard("v2"), "paul");
},
testMoveResponsibility: function() {
var colV = dbs.select("_system").collection("v");
var source = "pavel";
var target = "paul";
var shard = "v1";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.colls, "_system", "87123"].join("/"));
dummy.target.vInfo = value;
wasCalled = true;
return true;
};
assertEqual(colV.getServerForShard(shard), source);
assertTrue(colV.moveShard(shard, target), "Failed to move shard responsibility.");
assertTrue(wasCalled, "Agency has not been informed to move shard..");
assertEqual(colV.getServerForShard(shard), target);
}
};
}
test.run(DBServersSuite);
test.run(CoordinatorSuite);
test.run(DataSuite);
}
function runPlanTests(test) {
'use strict';
function DBServersSuite() {
var servers;
return {
setUp: function() {
setup();
servers = comm.plan.DBServers();
},
tearDown: teardown,
testGetServerList: function() {
var expected = {
pavel: {
role: "primary",
secondary: "sandro"
},
paul: {
role: "primary",
secondary: "sally"
},
patricia: {
role: "primary",
secondary: "sandra"
},
sandro: {
role: "secondary"
},
sally: {
role: "secondary"
},
sandra: {
role: "secondary"
}
};
var res = servers.getList();
assertEqual(res, expected);
}
};
}
function CoordinatorSuite() {
var coordinators;
return {
setUp: function() {
setup();
coordinators = comm.plan.Coordinators();
},
tearDown: teardown,
testGetCoordinatorList: function() {
var list = {
"carlos": {"role": "primary"},
"charly": {"role": "primary"},
"cindy": {"role": "primary"}
};
assertEqual(coordinators.getList(), list);
}
};
}
function DataSuite() {
var dbs;
return {
setUp: function() {
setup();
dbs = comm.plan.Databases();
},
tearDown: teardown,
testGetDatabaseList: function() {
var list = [
"_system",
"a_db",
"b_db",
"z_db"
].sort();
assertEqual(dbs.getList(), list);
},
testGetCollectionListForDatabase: function() {
var syslist = [
"_graphs",
"v",
"e"
].sort();
var alist = [
"s",
"a",
"d"
].sort();
assertEqual(dbs.select("_system").getCollections(), syslist);
assertEqual(dbs.select("a_db").getCollections(), alist);
},
testSelectNotExistingDatabase: function() {
assertFalse(dbs.select("foxx"));
},
testGetCollectionMetaInfo: function() {
var sysdb = dbs.select("_system");
assertEqual(sysdb.collection("v").info(), dummy.target.vInfo);
},
testGetResponsibilitiesForCollection: function() {
var colV = dbs.select("_system").collection("v");
var expected = {
v1: "pavel",
v2: "paul",
v3: "patricia",
v4: "pavel",
v5: "patricia",
v6: "pavel"
};
assertEqual(colV.getShards(), expected);
},
testGetShardsForServer: function() {
var colV = dbs.select("_system").collection("v");
assertEqual(colV.getShardsForServer("pavel"), ["v1", "v4", "v6"].sort());
assertEqual(colV.getShardsForServer("paul"), ["v2"].sort());
assertEqual(colV.getShardsForServer("patricia"), ["v3", "v5"].sort());
},
testGetServerForShard: function() {
var colV = dbs.select("_system").collection("v");
assertEqual(colV.getServerForShard("v1"), "pavel");
assertEqual(colV.getServerForShard("v2"), "paul");
}
};
}
test.run(DBServersSuite);
test.run(CoordinatorSuite);
test.run(DataSuite);
}
function runCurrentTests(test) {
'use strict';
function DBServersSuite() {
var targetServers;
return {
setUp: function() {
setup();
targetServers = comm.current.DBServers();
},
tearDown: teardown,
testGetServerList: function() {
var expected = {
pavel: {
role: "primary",
secondary: "sandro",
address: "192.168.0.1:8529",
protocol: "http"
},
paul: {
role: "primary",
secondary: "sally",
address: "192.168.0.2:8529",
protocol: "http"
},
patricia: {
role: "primary",
secondary: "sandra",
address: "192.168.0.3:8529",
protocol: "http"
},
sandro: {
role: "secondary",
address: "192.168.0.4:8529",
protocol: "http"
},
sally: {
role: "secondary",
address: "192.168.0.5:8529",
protocol: "http"
},
sandra: {
role: "secondary",
address: "192.168.0.6:8529",
protocol: "http"
}
};
var res = targetServers.getList();
assertEqual(res, expected);
}
};
}
function CoordinatorSuite() {
return {
setUp: setup,
tearDown: teardown,
testGetServerList: function() {
var expected = {
"carlos": {
"address": "192.168.1.1:8529",
"protocol": "http"
},
"charly": {
"address": "192.168.1.2:8529",
"protocol": "http"
},
"cindy": {
"address": "192.168.1.3:8529",
"protocol": "http"
}
};
var res = comm.current.Coordinators().getList();
assertEqual(res, expected);
}
};
}
function DataSuite() {
var dbs;
return {
setUp: function() {
setup();
dbs = comm.current.Databases();
},
tearDown: teardown,
testGetDatabaseList: function() {
var list = [
"_system",
"a_db",
"b_db",
"z_db"
].sort();
assertEqual(dbs.getList(), list);
},
testGetCollectionListForDatabase: function() {
var syslist = [
"_graphs",
"v",
"e"
].sort();
var alist = [
"s",
"a",
"d"
].sort();
assertEqual(dbs.select("_system").getCollections(), syslist);
assertEqual(dbs.select("a_db").getCollections(), alist);
},
testSelectNotExistingDatabase: function() {
assertFalse(dbs.select("foxx"));
},
testGetCollectionMetaInfo: function() {
var sysdb = dbs.select("_system");
assertEqual(sysdb.collection("v").info(), dummy.target.vInfo);
},
testGetResponsibilitiesForCollection: function() {
var colV = dbs.select("_system").collection("v");
var expected = {
v1: "pavel",
v2: "paul",
v3: "patricia",
v4: "pavel",
v5: "patricia",
v6: "pavel"
};
assertEqual(colV.getShards(), expected);
},
testGetShardsForServer: function() {
var colV = dbs.select("_system").collection("v");
assertEqual(colV.getShardsForServer("pavel"), ["v1", "v4", "v6"].sort());
assertEqual(colV.getShardsForServer("paul"), ["v2"].sort());
assertEqual(colV.getShardsForServer("patricia"), ["v3", "v5"].sort());
},
testGetServerForShard: function() {
var colV = dbs.select("_system").collection("v");
assertEqual(colV.getServerForShard("v1"), "pavel");
assertEqual(colV.getServerForShard("v2"), "paul");
}
};
}
test.run(DBServersSuite);
test.run(CoordinatorSuite);
test.run(DataSuite);
}
function runSyncTests(test) {
'use strict';
function HeartbeatSuite() {
var beats;
return {
setUp: function() {
setup();
beats = comm.sync.Heartbeats();
},
tearDown: teardown,
testGetHeartbeats: function() {
assertEqual(beats.list(), dummy.sync.heartbeats);
},
testGetInactiveServers: function() {
assertEqual(beats.getInactive(), []);
},
testGetServingServers: function() {
assertEqual(beats.getServing(), ["pavel", "paul", "patricia"].sort());
},
testGetInSyncPairs: function() {
assertEqual(beats.getInSync(), [
"pavel", "sandro",
"paul", "sally"
].sort());
},
testGetOutOfSyncPairs: function() {
assertEqual(beats.getOutSync(), ["patricia", "sandra"].sort());
},
testGetNoBeatIfAllWork: function() {
assertEqual(beats.noBeat(), []);
},
testGetNoBeatIfOneFails: function() {
// Rewrite Beat
var now = new Date(),
old = new Date(now - 5 * 60 * 1000),
route = [
agencyRoutes.registered,
agencyRoutes.sub.beat,
"pavel"
].join("/");
dummy.sync.heartbeats[route].time = old.toISOString();
assertEqual(beats.noBeat(), ["pavel"]);
}
};
}
function ProblemsSuite() {
// TODO Not yet fully defined
return {
setUp: setup,
tearDown: teardown
};
}
test.run(HeartbeatSuite);
test.run(ProblemsSuite);
}
function runHighLevelTests(test) {
'use strict';
function ConfigureSuite() {
var targetServers;
var targetCoordinators;
return {
setUp: function() {
setup();
targetServers = comm.target.DBServers();
targetCoordinators = comm.target.Coordinators();
},
tearDown: teardown,
testAddNewPrimaryServer: function() {
var name = "pancho";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, "none");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(comm.addPrimary(name), "Failed to insert a new primary");
assertTrue(wasCalled, "Agency has not been informed to insert primary.");
var newList = targetServers.getList();
assertNotUndefined(newList[name]);
assertEqual(newList[name].role, "primary");
assertUndefined(newList[name].secondary);
},
testAddNewSecondaryServer: function() {
var name = "pancho";
var secName = "samuel";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, "none");
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(comm.addPrimary(name), "Failed to insert a new primary");
assertTrue(wasCalled, "Agency has not been informed to insert primary.");
wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, secName);
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(comm.addSecondary(secName, name), "Failed to insert a new secondary");
assertTrue(wasCalled, "Agency has not been informed to insert secondary.");
var newList = targetServers.getList();
assertNotUndefined(newList[name]);
assertEqual(newList[name].role, "primary");
assertEqual(newList[name].secondary, secName);
assertNotUndefined(newList[secName]);
assertEqual(newList[secName].role, "secondary");
},
testAddNewServerPair: function() {
var name = "pancho";
var secName = "samuel";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertEqual(value, secName);
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(comm.addPair(name, secName), "Failed to insert a new primary/secondary pair");
assertTrue(wasCalled, "Agency has not been informed to insert the new pair.");
var newList = targetServers.getList();
assertNotUndefined(newList[name]);
assertEqual(newList[name].role, "primary");
assertEqual(newList[name].secondary, secName);
assertNotUndefined(newList[secName]);
assertEqual(newList[secName].role, "secondary");
},
testRemovePrimaryServer: function() {
var name = "pavel";
var secondaryName = "sandro";
var setWasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, secondaryName].join("/"));
assertEqual(value, "none");
assertFalse(setWasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
setWasCalled = true;
return true;
};
var delWasCalled = false;
agencyMock.remove = function(route) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, name].join("/"));
assertFalse(delWasCalled, "Delete has been called multiple times");
delete dummy.target.servers[route];
delWasCalled = true;
return true;
};
assertTrue(comm.removeServer(name), "Failed to remove a primary server");
assertTrue(setWasCalled, "Agency has not been informed to replace the primary with the secondary.");
assertTrue(delWasCalled, "Agency has not been informed to remove the primary/secondary pair.");
var newList = targetServers.getList();
assertUndefined(newList[name]);
assertNotUndefined(newList[secondaryName]);
assertEqual(newList[secondaryName].role, "primary");
assertUndefined(newList[secondaryName].secondary);
},
testRemoveSecondaryServer: function() {
var name = "sandro";
var pName = "pavel";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.servers, pName].join("/"));
assertEqual(value, "none");
assertFalse(wasCalled, "Set has been called multiple times");
dummy.target.servers[route] = value;
wasCalled = true;
return true;
};
assertTrue(comm.removeServer(name), "Failed to remove a secondary server.");
assertTrue(wasCalled, "Agency has not been informed to update the primary server.");
var newList = targetServers.getList();
assertUndefined(newList[name]);
assertNotUndefined(newList[pName]);
assertEqual(newList[pName].role, "primary");
assertUndefined(newList[pName].secondary);
},
testAddCoordinator: function() {
var name = "carol";
var wasCalled = false;
agencyMock.set = function(route, value) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.coords, name].join("/"));
assertEqual(value, "none");
dummy.target.coordinators[route] = value;
wasCalled = true;
return true;
};
assertTrue(comm.addCoordinator(name), "Failed to insert a new coordinator.");
assertTrue(wasCalled, "Agency has not been informed to insert coordinator.");
var list = {
"carlos": {"role": "primary"},
"charly": {"role": "primary"},
"cindy": {"role": "primary"}
};
list[name] = {"role": "primary"};
assertEqual(targetCoordinators.getList(), list);
},
testRemoveCoordinator: function() {
var name = "cindy";
var delWasCalled = false;
agencyMock.remove = function(route) {
assertEqual(route, [agencyRoutes.target, agencyRoutes.sub.coords, name].join("/"));
assertFalse(delWasCalled, "Delete has been called multiple times");
delete dummy.target.coordinators[route];
delWasCalled = true;
return true;
};
assertTrue(comm.removeServer(name), "Failed to remove a coordinator.");
assertTrue(delWasCalled, "Agency has not been informed to remove a coordinator.");
var list = {
"carlos": {"role": "primary"},
"charly": {"role": "primary"},
};
assertEqual(targetCoordinators.getList(), list);
}
};
}
function DifferenceSuite() {
var planMissingDB = [{
name: "pavel",
role: "primary",
address: ips.pavel.endpoint.split("://")[1],
protocol: "http"
}, {
name: "sandra",
role: "secondary",
address: ips.sandra.endpoint.split("://")[1],
protocol: "http"
}];
var planMissingCoords = [{
name: "carlos",
role: "primary",
address: ips.carlos.endpoint.split("://")[1],
protocol: "http"
}];
var currentMissingDB = [{
name: "patricia",
role: "primary",
address: ips.patricia.endpoint.split("://")[1],
protocol: "http"
}];
var currentMissingCoords = [{
name: "charly",
role: "primary",
address: ips.charly.endpoint.split("://")[1],
protocol: "http"
}];
var modified = "sandro";
var modplan = "none";
var lonelyPrimary = "patricia";
return {
setUp: function() {
_.each(planMissingDB, function(obj) {
var d = obj.name;
delete dummy.plan.servers[[agencyRoutes.plan, agencyRoutes.sub.servers, d].join("/")];
delete dummy.current.servers[[agencyRoutes.current, agencyRoutes.sub.servers, d].join("/")];
});
dummy.plan.servers[[agencyRoutes.plan, agencyRoutes.sub.servers, lonelyPrimary].join("/")] = "none";
dummy.current.servers[[agencyRoutes.current, agencyRoutes.sub.servers, lonelyPrimary].join("/")] = "none";
_.each(planMissingCoords, function(obj) {
var d = obj.name;
delete dummy.plan.coordinators[[agencyRoutes.plan, agencyRoutes.sub.coords, d].join("/")];
delete dummy.current.coordinators[[agencyRoutes.current, agencyRoutes.sub.coords, d].join("/")];
});
_.each(currentMissingDB, function(obj) {
var d = obj.name;
delete dummy.current.servers[[agencyRoutes.current, agencyRoutes.sub.servers, d].join("/")];
});
_.each(currentMissingCoords, function(obj) {
var d = obj.name;
delete dummy.current.coordinators[[agencyRoutes.current, agencyRoutes.sub.coords, d].join("/")];
});
dummy.plan.servers[[agencyRoutes.plan, agencyRoutes.sub.servers, modified].join("/")] = modplan;
dummy.current.servers[[agencyRoutes.current, agencyRoutes.sub.servers, modified].join("/")] = modplan;
comm = new Communication.Communication();
},
tearDown: teardown,
testDifferencePlanDBServers: function() {
var diff = comm.diff.plan.DBServers();
assertEqual(diff.missing, planMissingDB);
assertEqual(diff.difference[modified], {
target: {role: "secondary"},
plan: {role: "primary"}
});
assertEqual(diff.difference[lonelyPrimary], {
target: {
role: "primary",
secondary: "sandra"
},
plan: {role: "primary"}
});
},
testDifferencePlanCoordinators: function() {
var diff = comm.diff.plan.Coordinators();
assertEqual(diff.missing, planMissingCoords);
assertEqual(diff.difference, {});
},
testDifferenceCurrentDBServers: function() {
var diff = comm.diff.current.DBServers();
assertEqual(diff.missing, currentMissingDB);
},
testDifferenceCurrentCoordinators: function() {
var diff = comm.diff.current.Coordinators();
assertEqual(diff.missing, currentMissingCoords);
}
};
}
test.run(ConfigureSuite);
test.run(DifferenceSuite);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suites
////////////////////////////////////////////////////////////////////////////////
runTargetTests(jsunity);
runPlanTests(jsunity);
runCurrentTests(jsunity);
runSyncTests(jsunity);
runHighLevelTests(jsunity);
return jsunity.done();