remsim: server: TC_connect_{client,bankd}_duplicate

Add two new tests for the remsim-server, which simulate what happens
if a client or bankd with identical ID connects twice.  We expect
the second connection to get rejected at RSPRO level, and to be closed.

Change-Id: I29023f6b5ba430338c77bf01508c81bd6d8c99fa
Ralated: OS#5527
diff --git a/remsim/RSPRO.asn b/remsim/RSPRO.asn
index faf9cec..5e2c05b 100644
--- a/remsim/RSPRO.asn
+++ b/remsim/RSPRO.asn
@@ -87,6 +87,7 @@
 	illegalSlotId			(3),
 	unsupportedProtocolVersion	(4),
 	unknownSlotmap			(5),
+	identityInUse			(6),
 
 	-- no card is present in given slot
 	cardNotPresent			(100),
diff --git a/remsim/RemsimServer_Tests.ttcn b/remsim/RemsimServer_Tests.ttcn
index 135ce15..6d2b27d 100644
--- a/remsim/RemsimServer_Tests.ttcn
+++ b/remsim/RemsimServer_Tests.ttcn
@@ -133,6 +133,44 @@
 	setverdict(pass);
 }
 
+/* duplicate connection from Same Client/Slot ID */
+testcase TC_connect_client_duplicate() runs on test_CT {
+	var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
+	var JsRoot js;
+
+	f_init();
+	f_rsres_init();
+	f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
+	rspro[0].rspro_client_slot := valueof(ts_ClientSlot(13,1));
+
+	js := f_rsres_get("/api/backend/v1/clients");
+	if (not match(js.clients, JsClients:{})) {
+		setverdict(fail, "Initial state not empty");
+		mtc.stop;
+	}
+	f_rspro_connect_client(0);
+	js := f_rsres_get("/api/backend/v1/clients");
+	if (not match(js.clients[0], tr_JsClient(CONNECTED_CLIENT, rspro[0].rspro_id))) {
+		setverdict(fail, "Non-matching JSON response");
+		mtc.stop;
+	}
+
+	/* connect a second time for same Client ID */
+	f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_id, 1);
+	rspro[1].rspro_client_slot := valueof(ts_ClientSlot(13,1));
+	f_rspro_connect_client(1, identityInUse);
+	f_rspro_exp_disconnect(1);
+
+	/* expect the first connection still to be active */
+	js := f_rsres_get("/api/backend/v1/clients");
+	if (not match(js.clients[0], tr_JsClient(CONNECTED_CLIENT, rspro[0].rspro_id))) {
+		setverdict(fail, "Non-matching JSON response");
+		mtc.stop;
+	}
+
+	setverdict(pass);
+}
+
 testcase TC_connect_bank() runs on test_CT {
 	var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, "foobar"));
 	var JsRoot js;
@@ -158,6 +196,50 @@
 	setverdict(pass);
 }
 
+testcase TC_connect_bank_duplicate() runs on test_CT {
+	var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, "foobar"));
+	var JsRoot js;
+
+	f_init();
+	f_rsres_init();
+	f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
+	rspro[0].rspro_bank_id := 1;
+	rspro[0].rspro_bank_nslots := 8;
+
+	js := f_rsres_get("/api/backend/v1/banks");
+	if (not match(js.banks, JsBanks:{})) {
+		setverdict(fail, "Initial state not empty");
+		mtc.stop;
+	}
+	f_rspro_connect_client(0);
+	js := f_rsres_get("/api/backend/v1/banks");
+	if (not match(js.banks[0], tr_JsBank(CONNECTED_BANKD, rspro[0].rspro_id, rspro[0].rspro_bank_id,
+					     rspro[0].rspro_bank_nslots))) {
+		setverdict(fail, "Non-matching JSON response");
+		mtc.stop;
+	}
+
+	/* connect a second time for same Bank ID */
+	f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_id, 1);
+	rspro[1].rspro_bank_id := 1;
+	rspro[1].rspro_bank_nslots := 23;
+	f_rspro_connect_client(1, identityInUse);
+
+	/* expect only the first bank to survive */
+	js := f_rsres_get("/api/backend/v1/banks");
+	if (not match(js.banks[0], tr_JsBank(CONNECTED_BANKD, rspro[0].rspro_id, rspro[0].rspro_bank_id,
+					     rspro[0].rspro_bank_nslots))) {
+		setverdict(fail, "Non-matching JSON response");
+		mtc.stop;
+	}
+
+	/* wait for T2/rejected timer to expire in server */
+	f_sleep(2.0);
+
+	setverdict(pass);
+}
+
+
 function f_ensure_slotmaps(template JsSlotmaps maps)
 runs on http_CT {
 	var JsRoot js;
@@ -508,7 +590,9 @@
 control {
 	execute( TC_connect_and_nothing() );
 	execute( TC_connect_client() );
+	execute( TC_connect_client_duplicate() );
 	execute( TC_connect_bank() );
+	execute( TC_connect_bank_duplicate() );
 	execute( TC_slotmap_add() );
 	execute( TC_slotmap_add_conn_cl_b() );
 	execute( TC_slotmap_add_out_of_range() );