module L1CTL_Test {
	import from GSM_Types all;
	import from Osmocom_Types all;
	import from LAPDm_RAW_PT all;
	import from LAPDm_Types all;

	type component dummy_CT {
		port LAPDm_PT LAPDM;
		var lapdm_CT lapdm_component;
	};

	function f_init() runs on dummy_CT {
		/* create the LAPDm component */
		lapdm_component := lapdm_CT.create;
		/* connect our own LAPDM port to the LAPDM Service Provider of the LAPDm component */
		connect(self:LAPDM, lapdm_component:LAPDM_SP);
		/* connect the LAPDm compoent's lower-side port to the system L1CTL port (which is internally
		 * connected to the Unix Domain Socket test port */
		map(lapdm_component:L1CTL, system:L1CTL);

		/* start the LAPDm parallel component calling it's local function LAPDmStart */
		lapdm_component.start(LAPDmStart());
	}

	/* master function establishing a dedicated radio channel (takes care of RACH/IMM.ASS handling) */
	function f_establish_dcch() runs on dummy_CT {
		var BCCH_tune_req tune_req := { arfcn := { false, 871 }, combined_ccch := true };
		var DCCH_establish_req est_req := { ra := 23 };

		LAPDM.send(tune_req);
		LAPDM.send(est_req);
		LAPDM.receive(DCCH_establish_res:?);
	}

	/* helper function releasing dedicated radio channel physically (no Um signaling!) */
	function f_release_dcch() runs on dummy_CT {
		var DCCH_release_req rel_req := {};
		LAPDM.send(rel_req);
	}

	template LAPDm_ph_data t_PH_DATA(template GsmSapi sapi, template boolean sacch, template LapdmFrame frame) := {
		sacch := sacch,
		sapi := sapi,
		lapdm := frame
	}
	/* template for a valid SABM frame */
	template LapdmFrame LAPDm_B_SABM(template GsmSapi sapi, octetstring payload)  := {
		b := {
			addr := tr_LapdmAddr(sapi, false),
			ctrl := t_LapdmCtrlSABM(true),
			len := lengthof(payload),
			m := false,
			el := 1,
			payload := payload
		}
	}

	/* template for a valid UA frame */
	template LapdmFrame tr_LAPDm_B_UA(template GsmSapi sapi, template octetstring payload)  := {
		b := {
			addr := tr_LapdmAddr(sapi, false),
			ctrl := t_LapdmCtrlUA(true),
			len := ?,
			m := false,
			el := 1,
			payload := payload
		}
	}

	/* template for a valid UA frame */
	template LapdmFrame LAPDm_B_UA(template GsmSapi sapi, octetstring payload)  := {
		b := {
			addr := tr_LapdmAddr(sapi, false),
			ctrl := t_LapdmCtrlUA(true),
			len := lengthof(payload),
			m := false,
			el := 1,
			payload := payload
		}
	}

	/* template for a valid UI frame */
	template LapdmFrame LAPDm_B_UI(template GsmSapi sapi, octetstring payload)  := {
		b := {
			addr := tr_LapdmAddr(sapi, true),
			ctrl := t_LapdmCtrlUI(false),
			len := lengthof(payload),
			m := false,
			el := 1,
			payload := payload
		}
	}

	function f_test_sabm_results_in_ua(uint8_t sapi, boolean use_sacch, octetstring payload) runs on dummy_CT return boolean {
		var LAPDm_ph_data phd;
		var boolean result := false;
		timer T := 5.0;

		f_establish_dcch();
		LAPDM.send(t_PH_DATA(sapi, use_sacch, LAPDm_B_SABM(sapi, payload)));
		log("====> expecting ", t_PH_DATA(sapi, use_sacch, LAPDm_B_UA(sapi, payload)));
		T.start
		alt {
			[] LAPDM.receive(t_PH_DATA(?, use_sacch, LAPDm_B_UA(sapi, payload))) { result := true; }
			[] LAPDM.receive(t_PH_DATA(?, use_sacch, ?)) -> value phd { log("Other msg on DCH: ", phd); repeat; }
			[] LAPDM.receive(t_PH_DATA(?, ?, ?)) -> value phd { log("Other PH-DATA: ", phd); repeat; }
			[] T.timeout { }
		}
		f_release_dcch();
		return result;
	}

	testcase TC_sabm_ua_dcch_sapi0() runs on dummy_CT {
		f_init();
		if (not f_test_sabm_results_in_ua(0, false, 'FEFE'O)) {
			setverdict(fail);
		}
		setverdict(pass);
	}

	testcase TC_sabm_ua_dcch_sapi0_nopayload() runs on dummy_CT {
		f_init();
		if (f_test_sabm_results_in_ua(0, false, ''O)) {
			setverdict(fail, "Initial SABM/UA must contain L3 payload but BTS accepts without");
		}
		setverdict(pass);
	}

	testcase TC_sabm_ua_dcch_sapi3() runs on dummy_CT {
		f_init();
		if (f_test_sabm_results_in_ua(3, false, 'FEFE'O)) {
			setverdict(fail, "Initial SABM/UA must be on SAPI0, but BTS accepts SAPI=3");
		}
		setverdict(pass);
	}

	testcase TC_sabm_ua_dcch_sapi4() runs on dummy_CT {
		f_init();
		if (f_test_sabm_results_in_ua(4, false, 'FEFE'O)) {
			setverdict(fail, "Initial SABM/UA must be on SAPI0, but BTS accepts SAPI=4");
		}
		setverdict(pass);
	}

	testcase TC_sabm_contention() runs on dummy_CT {
		var LAPDm_ph_data phd;
		const octetstring payload := '0102030405'O;
		const GsmSapi sapi := 0;
		const boolean use_sacch := false;
		timer T := 5.0;

		f_init();

		f_establish_dcch();
		/* first frame is our real SABM */
		LAPDM.send(t_PH_DATA(sapi, use_sacch, LAPDm_B_SABM(sapi, payload)));
		/* second frame is a SABM with different payload, which BTS has to ignore according to 8.4.1.4 */
		LAPDM.send(t_PH_DATA(sapi, use_sacch, LAPDm_B_SABM(sapi, 'ABCDEF'O)));
		log("====> expecting ", t_PH_DATA(sapi, use_sacch, LAPDm_B_UA(sapi, payload)));
		T.start
		alt {
			[] LAPDM.receive(t_PH_DATA(?, use_sacch, LAPDm_B_UA(sapi, payload))) { setverdict(pass); repeat; }
			[] LAPDM.receive(t_PH_DATA(?, use_sacch, tr_LAPDm_B_UA(sapi, ?))) {
				setverdict(fail, "Second SABM was responded to during contention resolution");
			}
			[] LAPDM.receive { repeat };
			[] T.timeout { }
		}
		f_release_dcch();
	}


	testcase TC_foo() runs on dummy_CT {
/*
		var LapdmFrame lf := valueof(LAPDm_B_UA(0, ''O));
		log("ENC UA: ", enc_LapdmFrame(lf));
		lf := valueof(LAPDm_B_UI(0, ''O));
		log("ENC UI B: ", enc_LapdmFrame(lf));
		log("ENC UI B: ", enc_LapdmFrameB(lf.b));

		log("DEC UI AF: ", dec_LapdmAddressField('03'O));
*/
		log("DEC UI CU: ", dec_LapdmCtrlU('03'O));
		log("DEC UI CT: ", dec_LapdmCtrl('03'O));

		log("DEC UA: ", dec_LapdmFrameB('017301'O));
		log("DEC UI: ", dec_LapdmFrameA('030301'O));
		log("DEC I: ", dec_LapdmFrameA('030001'O));
		log("DEC S: ", dec_LapdmFrameA('030101'O));
		log("DEC: ", dec_LapdmFrameB('030301'O));
		log("DEC: ", dec_LapdmFrameB('0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O));
	}

	control {
		execute(TC_foo());
		execute(TC_sabm_ua_dcch_sapi0());
		execute(TC_sabm_ua_dcch_sapi0_nopayload());
		execute(TC_sabm_ua_dcch_sapi3());
		execute(TC_sabm_ua_dcch_sapi4());
		execute(TC_sabm_contention());
	}
}
