blob: a985536e2a18d12b48b880a104d5dadee330f8b9 [file] [log] [blame]
Harald Weltef30e22b2019-11-14 08:36:19 +01001module CCID_Tests {
2
3import from General_Types all;
4import from Osmocom_Types all;
5import from Misc_Helpers all;
6
7import from USB_PortType all;
8
9import from CCID_Types all;
10import from CCID_Templates all;
11import from CCID_Emulation all;
12
13/* global test component; manages CCID device */
14type component Test_CT {
15 var CCID_Emulation_CT vc_CCID;
16 port USB_PT USB;
17 var Slot_CT vc_SLOT[NR_SLOTS];
18};
19
20/* per-slot test component; manages one slot */
21type component Slot_CT {
22 var uint8_t g_slot_nr;
23 port CCID_SLOT_PT CCID;
24 timer g_Tguard := 10.0;
25};
26
27private const integer NR_SLOTS := 4;
28
29/***********************************************************************
30 * helper infrastructure
31 ***********************************************************************/
32
33type function void_fn() runs on Slot_CT;
34
35/* altstep running on the per-slot test component */
36private altstep as_Tguard() runs on Slot_CT {
37 [] g_Tguard.timeout {
38 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
39 }
40}
41
42/* first function inside Slot_CT; wait for CCID_EVENT_UP + call testcase-specific function */
43private function f_handler_init(void_fn fn, integer slot_nr) runs on Slot_CT {
44 g_slot_nr := slot_nr;
45 CCID.receive(CCID_Emulation_Event:{up_down:=CCID_EVENT_UP});
46 g_Tguard.start;
47 activate(as_Tguard());
48
49 fn.apply();
50}
51
52/* start a single slot handler */
53private function f_start_handler(void_fn fn, integer slot_nr) runs on Test_CT
54{
55 var Slot_CT vc;
56
57 vc_SLOT[slot_nr] := Slot_CT.create("Slot" & int2str(slot_nr));
58 connect(vc_SLOT[slot_nr]:CCID, vc_CCID:SLOT[slot_nr]);
59 vc_SLOT[slot_nr].start(f_handler_init(fn, slot_nr));
60}
61
62private function f_wait_handlers_complete() runs on Test_CT {
63 var integer i;
64
65 for (i := 0; i < NR_SLOTS; i := i+1) {
66 if (vc_SLOT[i] != null) {
67 vc_SLOT[i].done;
68 }
69 }
70 setverdict(pass);
71}
72
73private function f_start_and_wait() runs on Test_CT {
74 /* start CCID_Emulation last, it will trigger all the per-slot components */
75 vc_CCID.start(CCID_Emulation.main());
76 f_wait_handlers_complete();
77}
78
79private function f_init() runs on Test_CT {
80 var integer i;
81 vc_CCID := CCID_Emulation_CT.create("CCID");
82 map(vc_CCID:USB, system:USB);
83 for (i := 0; i < NR_SLOTS; i := i+1) {
84 vc_SLOT[i] := null;
85 }
86}
87
88private function f_power_on(CCID_PowerSelect psel := CCID_PWRSEL_AUTO) runs on Slot_CT {
89 CCID.send(ts_CCID_IccPowerOn(g_slot_nr, psel));
90 CCID.receive(tr_CCID_DataBlock(g_slot_nr));
91}
92
93private function f_xceive(octetstring tx, template octetstring rx) runs on Slot_CT return octetstring {
94 var CCID_PDU pdu;
95
96 CCID.send(ts_CCID_XfrBlock(g_slot_nr, tx, 0));
97 alt {
98 [] CCID.receive(tr_CCID_DataBlock(g_slot_nr, ?, rx)) -> value pdu {
99 return pdu.u.DataBlock.abData;
100 }
101 [] CCID.receive(tr_CCID_DataBlock(g_slot_nr, ?, ?)) -> value pdu {
102 setverdict(fail, "Received unexpected DataBlock ", pdu);
103 self.stop;
104 }
105 [] CCID.receive(CCID_PDU:?) -> value pdu {
106 setverdict(fail, "Received unexpected CCID ", pdu);
107 self.stop;
108 }
109 }
110 return ''O;
111}
112
113
114/***********************************************************************
115 * actual test cases
116 ***********************************************************************/
117
118
119/* request 100 times the slot status */
120private function f_TC_getstatus() runs on Slot_CT
121{
122 var integer i;
123 for (i := 0; i < 100; i := i+1) {
124 CCID.send(ts_CCID_GetSlotStatus(g_slot_nr));
125 /* it would be fun to simply send more requests here, but the CCID
126 * spec doesn't permit more than one unresponded command [per slot] */
127 alt {
128 [] CCID.receive(tr_CCID_SlotStatus(g_slot_nr));
129 [] CCID.receive {
130 setverdict(fail, "Unexpected data from device");
131 }
132 }
133 }
134 setverdict(pass);
135}
136testcase TC_get_status() runs on Test_CT
137{
138 var integer i;
139
140 f_init();
141
142 for (i := 0; i < NR_SLOTS; i := i+1) {
143 f_start_handler(refers(f_TC_getstatus), i);
144 }
145
146 f_start_and_wait();
147}
148
149
150private function f_TC_power_on() runs on Slot_CT
151{
152 f_power_on();
153}
154testcase TC_power_on() runs on Test_CT
155{
156 var integer i;
157
158 f_init();
159
160 for (i := 0; i < NR_SLOTS; i := i+1) {
161 f_start_handler(refers(f_TC_power_on), i);
162 }
163
164 f_start_and_wait();
165}
166
167private function f_TC_select_mf() runs on Slot_CT
168{
169 var integer i;
170 f_power_on();
171 for (i := 0; i < 10000; i := i+1) {
172 f_xceive('00a40004023f00'O, ?);
173 }
174}
175testcase TC_select_mf() runs on Test_CT
176{
177 var integer i;
178
179 f_init();
180
181 for (i := 0; i < NR_SLOTS; i := i+1) {
182 f_start_handler(refers(f_TC_select_mf), i);
183 }
184
185 f_start_and_wait();
186}
187
188
189
190control {
191 execute( TC_get_status() );
192 execute( TC_power_on() );
193 execute( TC_select_mf() );
194}
195
196
197
198
199}