Harald Welte | f30e22b | 2019-11-14 08:36:19 +0100 | [diff] [blame^] | 1 | module CCID_Tests { |
| 2 | |
| 3 | import from General_Types all; |
| 4 | import from Osmocom_Types all; |
| 5 | import from Misc_Helpers all; |
| 6 | |
| 7 | import from USB_PortType all; |
| 8 | |
| 9 | import from CCID_Types all; |
| 10 | import from CCID_Templates all; |
| 11 | import from CCID_Emulation all; |
| 12 | |
| 13 | /* global test component; manages CCID device */ |
| 14 | type 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 */ |
| 21 | type component Slot_CT { |
| 22 | var uint8_t g_slot_nr; |
| 23 | port CCID_SLOT_PT CCID; |
| 24 | timer g_Tguard := 10.0; |
| 25 | }; |
| 26 | |
| 27 | private const integer NR_SLOTS := 4; |
| 28 | |
| 29 | /*********************************************************************** |
| 30 | * helper infrastructure |
| 31 | ***********************************************************************/ |
| 32 | |
| 33 | type function void_fn() runs on Slot_CT; |
| 34 | |
| 35 | /* altstep running on the per-slot test component */ |
| 36 | private 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 */ |
| 43 | private 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 */ |
| 53 | private 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 | |
| 62 | private 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 | |
| 73 | private 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 | |
| 79 | private 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 | |
| 88 | private 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 | |
| 93 | private 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 */ |
| 120 | private 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 | } |
| 136 | testcase 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 | |
| 150 | private function f_TC_power_on() runs on Slot_CT |
| 151 | { |
| 152 | f_power_on(); |
| 153 | } |
| 154 | testcase 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 | |
| 167 | private 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 | } |
| 175 | testcase 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 | |
| 190 | control { |
| 191 | execute( TC_get_status() ); |
| 192 | execute( TC_power_on() ); |
| 193 | execute( TC_select_mf() ); |
| 194 | } |
| 195 | |
| 196 | |
| 197 | |
| 198 | |
| 199 | } |