blob: 48da12bdae265ae832a81233d56174d9d7b8b425 [file] [log] [blame]
Will Drewryd4ae5282017-01-03 22:06:26 -06001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Tests a very simple end to end T=1 using the echo backend.
17 */
18
19#include <string.h>
20
21#include <vector>
22#include <gtest/gtest.h>
23
24#include <ese/ese.h>
25#include <ese/teq1.h>
26#define LOG_TAG "TEQ1_UNITTESTS"
27#include <ese/log.h>
28
Will Drewryd660eb42017-07-25 13:33:55 -050029#include "ese_operations_interface.h"
30#include "ese_operations_wrapper.h"
31
Will Drewryd4ae5282017-01-03 22:06:26 -060032#include "teq1_private.h"
33
Will Drewryd660eb42017-07-25 13:33:55 -050034#define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
Will Drewryd4ae5282017-01-03 22:06:26 -060035
36using ::testing::Test;
37
38// TODO:
39// - Unittests of each function
40// - teq1_rules matches Annex A of ISO 7816-3
41
Will Drewryd4ae5282017-01-03 22:06:26 -060042// Tests teq1_frame_error_check to avoid testing every combo that
43// ends in 255 in the rule engine.
44class Teq1FrameErrorCheck : public virtual Test {
45 public:
46 Teq1FrameErrorCheck() { }
47 virtual ~Teq1FrameErrorCheck() { }
Will Drewry8f367fc2017-03-30 22:07:48 -050048
Will Drewryd4ae5282017-01-03 22:06:26 -060049 struct Teq1Frame tx_frame_, rx_frame_;
50 struct Teq1State state_;
51 struct Teq1CardState card_state_;
52};
53
54TEST_F(Teq1FrameErrorCheck, info_parity) {
55 static const uint8_t kRxPCBs[] = {
56 TEQ1_I(0, 0),
57 TEQ1_I(1, 0),
58 TEQ1_I(0, 1),
59 TEQ1_I(1, 1),
60 255,
61 };
62 const uint8_t *pcb = &kRxPCBs[0];
63 /* The PCBs above are all valid for a sent unchained I block with advancing
64 * sequence #s.
65 */
Will Drewryde2cad72017-03-10 15:53:34 -060066 tx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -060067 state_.card_state = &card_state_;
68 state_.card_state->seq.card = 1;
69 while (*pcb != 255) {
Will Drewryde2cad72017-03-10 15:53:34 -060070 rx_frame_.header.PCB = *pcb;
Will Drewryd4ae5282017-01-03 22:06:26 -060071 rx_frame_.header.LEN = 2;
72 rx_frame_.INF[0] = 'A';
73 rx_frame_.INF[1] = 'B';
74 rx_frame_.INF[2] = teq1_compute_LRC(&rx_frame_);
Will Drewryde2cad72017-03-10 15:53:34 -060075 EXPECT_EQ(0, teq1_frame_error_check(&state_, &tx_frame_, &rx_frame_)) << teq1_pcb_to_name(rx_frame_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -060076 rx_frame_.INF[2] = teq1_compute_LRC(&rx_frame_) - 1;
77 // Reset so we check the LRC error instead of a wrong seq.
78 state_.card_state->seq.card = !state_.card_state->seq.card;
79 EXPECT_EQ(TEQ1_R(0, 0, 1), teq1_frame_error_check(&state_, &tx_frame_, &rx_frame_));
80 state_.card_state->seq.card = !state_.card_state->seq.card;
81 pcb++;
82 }
83};
84
85TEST_F(Teq1FrameErrorCheck, length_mismatch) {
86};
87
88TEST_F(Teq1FrameErrorCheck, unchained_r_block) {
89};
90
91TEST_F(Teq1FrameErrorCheck, unexpected_seq) {
92};
93
94class Teq1RulesTest : public virtual Test {
95 public:
96 Teq1RulesTest() :
97 tx_data_(INF_LEN, 'A'),
98 rx_data_(INF_LEN, 'B'),
Will Drewry8f367fc2017-03-30 22:07:48 -050099 tx_sg_({ .base = tx_data_.data(), .len = INF_LEN }),
100 rx_sg_({ .base = rx_data_.data(), .len = INF_LEN }),
Will Drewryd4ae5282017-01-03 22:06:26 -0600101 card_state_({ .seq = { .card = 1, .interface = 1, }, }),
Will Drewry8f367fc2017-03-30 22:07:48 -0500102 state_(TEQ1_INIT_STATE(&tx_sg_, 1, INF_LEN,
103 &rx_sg_, 1, INF_LEN,
Will Drewryde2cad72017-03-10 15:53:34 -0600104 &card_state_)) {
Will Drewryd4ae5282017-01-03 22:06:26 -0600105 memset(&tx_frame_, 0, sizeof(struct Teq1Frame));
106 memset(&tx_next_, 0, sizeof(struct Teq1Frame));
107 memset(&rx_frame_, 0, sizeof(struct Teq1Frame));
108 }
109 virtual ~Teq1RulesTest() { }
110 virtual void SetUp() {}
111 virtual void TearDown() { }
112
113 struct Teq1Frame tx_frame_;
114 struct Teq1Frame tx_next_;
115 struct Teq1Frame rx_frame_;
116 std::vector<uint8_t> tx_data_;
117 std::vector<uint8_t> rx_data_;
Will Drewry8f367fc2017-03-30 22:07:48 -0500118 struct EseSgBuffer tx_sg_;
119 struct EseSgBuffer rx_sg_;
Will Drewryd4ae5282017-01-03 22:06:26 -0600120 struct Teq1CardState card_state_;
121 struct Teq1State state_;
122};
123
124class Teq1ErrorFreeTest : public Teq1RulesTest {
125};
126
127class Teq1ErrorHandlingTest : public Teq1RulesTest {
128};
129
130class Teq1CompleteTest : public Teq1ErrorFreeTest {
131 public:
132 virtual void SetUp() {
Will Drewryde2cad72017-03-10 15:53:34 -0600133 tx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600134 teq1_fill_info_block(&state_, &tx_frame_);
135 // Check that the tx_data was fully consumed.
Will Drewry8f367fc2017-03-30 22:07:48 -0500136 EXPECT_EQ(0UL, state_.app_data.tx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600137
Will Drewryde2cad72017-03-10 15:53:34 -0600138 rx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600139 rx_frame_.header.LEN = INF_LEN;
140 ASSERT_EQ(static_cast<unsigned long>(INF_LEN), tx_data_.size()); // Catch fixture changes.
141 // Supply TX data and make sure it overwrites RX data on consumption.
142 memcpy(rx_frame_.INF, tx_data_.data(), INF_LEN);
143 rx_frame_.INF[INF_LEN] = teq1_compute_LRC(&rx_frame_);
144 }
145
146 virtual void RunRules() {
147 teq1_trace_header();
Will Drewryde2cad72017-03-10 15:53:34 -0600148 teq1_trace_transmit(tx_frame_.header.PCB, tx_frame_.header.LEN);
149 teq1_trace_receive(rx_frame_.header.PCB, rx_frame_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600150
151 enum RuleResult result = teq1_rules(&state_, &tx_frame_, &rx_frame_, &tx_next_);
152 EXPECT_EQ(0, state_.errors);
153 EXPECT_EQ(NULL, state_.last_error_message)
154 << "Last error: " << state_.last_error_message;
Will Drewryde2cad72017-03-10 15:53:34 -0600155 EXPECT_EQ(0, tx_next_.header.PCB)
156 << "Actual next TX: " << teq1_pcb_to_name(tx_next_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -0600157 EXPECT_EQ(kRuleResultComplete, result)
158 << "Actual result name: " << teq1_rule_result_to_name(result);
159 }
160};
161
162TEST_F(Teq1CompleteTest, I00_I00_empty) {
163 // No data.
Will Drewry8f367fc2017-03-30 22:07:48 -0500164 state_.app_data.tx_total = 0;
165 state_.app_data.rx_total = 0;
Will Drewryd4ae5282017-01-03 22:06:26 -0600166 // Re-zero the prepared frames.
167 teq1_fill_info_block(&state_, &tx_frame_);
168 rx_frame_.header.LEN = 0;
169 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
170 RunRules();
171 EXPECT_EQ(0U, rx_frame_.header.LEN);
172};
173
174TEST_F(Teq1CompleteTest, I00_I00_data) {
175 RunRules();
176 // Ensure that the rx_frame data was copied out to rx_data.
Will Drewry8f367fc2017-03-30 22:07:48 -0500177 EXPECT_EQ(0UL, state_.app_data.rx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600178 EXPECT_EQ(tx_data_, rx_data_);
179};
180
181TEST_F(Teq1CompleteTest, I10_I10_data) {
Will Drewryde2cad72017-03-10 15:53:34 -0600182 tx_frame_.header.PCB = TEQ1_I(1, 0);
183 rx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600184 rx_frame_.INF[INF_LEN] = teq1_compute_LRC(&rx_frame_);
185 RunRules();
186 // Ensure that the rx_frame data was copied out to rx_data.
187 EXPECT_EQ(INF_LEN, rx_frame_.header.LEN);
Will Drewry8f367fc2017-03-30 22:07:48 -0500188 EXPECT_EQ(0UL, state_.app_data.rx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600189 EXPECT_EQ(tx_data_, rx_data_);
190};
191
192// Note, IFS is not tested as it is not supported on current hardware.
193
194TEST_F(Teq1ErrorFreeTest, I00_WTX0_WTX1_data) {
Will Drewryde2cad72017-03-10 15:53:34 -0600195 tx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600196 teq1_fill_info_block(&state_, &tx_frame_);
197 // Check that the tx_data was fully consumed.
Will Drewry8f367fc2017-03-30 22:07:48 -0500198 EXPECT_EQ(0UL, state_.app_data.tx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600199
Will Drewryde2cad72017-03-10 15:53:34 -0600200 rx_frame_.header.PCB = TEQ1_S_WTX(0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600201 rx_frame_.header.LEN = 1;
202 rx_frame_.INF[0] = 2; /* Wait x 2 */
203 rx_frame_.INF[1] = teq1_compute_LRC(&rx_frame_);
204
205 teq1_trace_header();
Will Drewryde2cad72017-03-10 15:53:34 -0600206 teq1_trace_transmit(tx_frame_.header.PCB, tx_frame_.header.LEN);
207 teq1_trace_receive(rx_frame_.header.PCB, rx_frame_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600208
209 enum RuleResult result = teq1_rules(&state_, &tx_frame_, &rx_frame_, &tx_next_);
Will Drewryde2cad72017-03-10 15:53:34 -0600210 teq1_trace_transmit(tx_next_.header.PCB, tx_next_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600211
212 EXPECT_EQ(0, state_.errors);
213 EXPECT_EQ(NULL, state_.last_error_message)
214 << "Last error: " << state_.last_error_message;
Will Drewryde2cad72017-03-10 15:53:34 -0600215 EXPECT_EQ(TEQ1_S_WTX(1), tx_next_.header.PCB)
216 << "Actual next TX: " << teq1_pcb_to_name(tx_next_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -0600217 EXPECT_EQ(state_.wait_mult, 2);
218 EXPECT_EQ(state_.wait_mult, rx_frame_.INF[0]);
219 // Ensure the next call will use the original TX frame.
220 EXPECT_EQ(kRuleResultSingleShot, result)
221 << "Actual result name: " << teq1_rule_result_to_name(result);
222};
223
224class Teq1ErrorFreeChainingTest : public Teq1ErrorFreeTest {
225 public:
226 virtual void RunRules() {
Will Drewryd4ae5282017-01-03 22:06:26 -0600227 tx_data_.resize(oversized_data_len_, 'C');
Will Drewry8f367fc2017-03-30 22:07:48 -0500228 const_cast<struct EseSgBuffer *>(state_.app_data.tx)->base = tx_data_.data();
229 const_cast<struct EseSgBuffer *>(state_.app_data.tx)->len = oversized_data_len_;
230 state_.app_data.tx_total = oversized_data_len_;
Will Drewryd4ae5282017-01-03 22:06:26 -0600231 teq1_fill_info_block(&state_, &tx_frame_);
232 // Ensure More bit was set.
Will Drewryde2cad72017-03-10 15:53:34 -0600233 EXPECT_EQ(1, bs_get(PCB.I.more_data, tx_frame_.header.PCB));
Will Drewryd4ae5282017-01-03 22:06:26 -0600234 // Check that the tx_data was fully consumed.
Will Drewryde2cad72017-03-10 15:53:34 -0600235 EXPECT_EQ(static_cast<uint32_t>(oversized_data_len_ - INF_LEN),
Will Drewry8f367fc2017-03-30 22:07:48 -0500236 state_.app_data.tx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600237 // No one is checking the TX LRC since there is no card present.
238
239 rx_frame_.header.LEN = 0;
240 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
241
242 teq1_trace_header();
Will Drewryde2cad72017-03-10 15:53:34 -0600243 teq1_trace_transmit(tx_frame_.header.PCB, tx_frame_.header.LEN);
244 teq1_trace_receive(rx_frame_.header.PCB, rx_frame_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600245
246 enum RuleResult result = teq1_rules(&state_, &tx_frame_, &rx_frame_, &tx_next_);
Will Drewryde2cad72017-03-10 15:53:34 -0600247 teq1_trace_transmit(tx_next_.header.PCB, tx_next_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600248 EXPECT_EQ(0, state_.errors);
249 EXPECT_EQ(NULL, state_.last_error_message)
250 << "Last error: " << state_.last_error_message;
251 EXPECT_EQ(kRuleResultContinue, result)
252 << "Actual result name: " << teq1_rule_result_to_name(result);
253 // Check that the tx_buf was drained already for the next frame.
254 // ...
Will Drewryde2cad72017-03-10 15:53:34 -0600255 EXPECT_EQ(static_cast<uint32_t>(oversized_data_len_ - (2 * INF_LEN)),
Will Drewry8f367fc2017-03-30 22:07:48 -0500256 state_.app_data.tx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600257 // Belt and suspenders: make sure no RX buf was used.
Will Drewry8f367fc2017-03-30 22:07:48 -0500258 EXPECT_EQ(rx_data_.size(), state_.app_data.rx_total);
Will Drewryd4ae5282017-01-03 22:06:26 -0600259 }
260 int oversized_data_len_;
261};
262
263TEST_F(Teq1ErrorFreeChainingTest, I01_R1_I11_chaining) {
264 oversized_data_len_ = INF_LEN * 3;
Will Drewryde2cad72017-03-10 15:53:34 -0600265 tx_frame_.header.PCB = TEQ1_I(0, 0);
266 rx_frame_.header.PCB = TEQ1_R(1, 0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600267 RunRules();
Will Drewryde2cad72017-03-10 15:53:34 -0600268 EXPECT_EQ(TEQ1_I(1, 1), tx_next_.header.PCB)
269 << "Actual next TX: " << teq1_pcb_to_name(tx_next_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -0600270};
271
272TEST_F(Teq1ErrorFreeChainingTest, I11_R0_I01_chaining) {
273 oversized_data_len_ = INF_LEN * 3;
Will Drewryde2cad72017-03-10 15:53:34 -0600274 tx_frame_.header.PCB = TEQ1_I(1, 0);
275 rx_frame_.header.PCB = TEQ1_R(0, 0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600276 RunRules();
Will Drewryde2cad72017-03-10 15:53:34 -0600277 EXPECT_EQ(TEQ1_I(0, 1), tx_next_.header.PCB)
278 << "Actual next TX: " << teq1_pcb_to_name(tx_next_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -0600279};
280
281TEST_F(Teq1ErrorFreeChainingTest, I11_R0_I00_chaining) {
282 oversized_data_len_ = INF_LEN * 2; // Exactly 2 frames worth.
Will Drewryde2cad72017-03-10 15:53:34 -0600283 tx_frame_.header.PCB = TEQ1_I(1, 0);
284 rx_frame_.header.PCB = TEQ1_R(0, 0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600285 RunRules();
Will Drewryde2cad72017-03-10 15:53:34 -0600286 EXPECT_EQ(TEQ1_I(0, 0), tx_next_.header.PCB)
287 << "Actual next TX: " << teq1_pcb_to_name(tx_next_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -0600288};
289
290//
291// Error handling tests
292//
293//
294
295class Teq1Retransmit : public Teq1ErrorHandlingTest {
296 public:
297 virtual void SetUp() {
298 // No data.
Will Drewry8f367fc2017-03-30 22:07:48 -0500299 state_.app_data.rx_total = 0;
300 state_.app_data.tx_total = 0;
Will Drewryd4ae5282017-01-03 22:06:26 -0600301
Will Drewryde2cad72017-03-10 15:53:34 -0600302 tx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600303 teq1_fill_info_block(&state_, &tx_frame_);
304 // No one is checking the TX LRC since there is no card present.
305
306 // Assume the card may not even set the error bit.
307 rx_frame_.header.LEN = 0;
Will Drewryde2cad72017-03-10 15:53:34 -0600308 rx_frame_.header.PCB = TEQ1_R(0, 0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600309 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
310 }
311 virtual void TearDown() {
312 teq1_trace_header();
Will Drewryde2cad72017-03-10 15:53:34 -0600313 teq1_trace_transmit(tx_frame_.header.PCB, tx_frame_.header.LEN);
314 teq1_trace_receive(rx_frame_.header.PCB, rx_frame_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600315
316 enum RuleResult result = teq1_rules(&state_, &tx_frame_, &rx_frame_, &tx_next_);
317 // Not counted as an error as it was on the card-side.
318 EXPECT_EQ(0, state_.errors);
319 const char *kNull = NULL;
320 EXPECT_EQ(kNull, state_.last_error_message) << state_.last_error_message;
321 EXPECT_EQ(kRuleResultRetransmit, result)
322 << "Actual result name: " << teq1_rule_result_to_name(result);
323 }
324};
325
326TEST_F(Teq1Retransmit, I00_R000_I00) {
Will Drewryde2cad72017-03-10 15:53:34 -0600327 rx_frame_.header.PCB = TEQ1_R(0, 0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600328 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
329};
330
331TEST_F(Teq1Retransmit, I00_R001_I00) {
Will Drewryde2cad72017-03-10 15:53:34 -0600332 rx_frame_.header.PCB = TEQ1_R(0, 0, 1);
Will Drewryd4ae5282017-01-03 22:06:26 -0600333 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
334};
335
336TEST_F(Teq1Retransmit, I00_R010_I00) {
Will Drewryde2cad72017-03-10 15:53:34 -0600337 rx_frame_.header.PCB = TEQ1_R(0, 1, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600338 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
339};
340
341TEST_F(Teq1Retransmit, I00_R011_I00) {
Will Drewryde2cad72017-03-10 15:53:34 -0600342 rx_frame_.header.PCB = TEQ1_R(0, 1, 1);
Will Drewryd4ae5282017-01-03 22:06:26 -0600343 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_);
344}
345
346TEST_F(Teq1ErrorHandlingTest, I00_I00_bad_lrc) {
347 // No data.
Will Drewry8f367fc2017-03-30 22:07:48 -0500348 state_.app_data.rx_total = 0;
349 state_.app_data.tx_total = 0;
Will Drewryd4ae5282017-01-03 22:06:26 -0600350
Will Drewryde2cad72017-03-10 15:53:34 -0600351 tx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600352 teq1_fill_info_block(&state_, &tx_frame_);
353 // No one is checking the TX LRC since there is no card present.
354
Will Drewryde2cad72017-03-10 15:53:34 -0600355 rx_frame_.header.PCB = TEQ1_I(0, 0);
Will Drewryd4ae5282017-01-03 22:06:26 -0600356 rx_frame_.header.LEN = 0;
357 rx_frame_.INF[0] = teq1_compute_LRC(&rx_frame_) - 1;
358
359 teq1_trace_header();
Will Drewryde2cad72017-03-10 15:53:34 -0600360 teq1_trace_transmit(tx_frame_.header.PCB, tx_frame_.header.LEN);
361 teq1_trace_receive(rx_frame_.header.PCB, rx_frame_.header.LEN);
Will Drewryd4ae5282017-01-03 22:06:26 -0600362
363 enum RuleResult result = teq1_rules(&state_, &tx_frame_, &rx_frame_, &tx_next_);
364 EXPECT_EQ(1, state_.errors);
365 const char *kNull = NULL;
366 EXPECT_NE(kNull, state_.last_error_message);
367 EXPECT_STREQ("Invalid frame received", state_.last_error_message);
Will Drewryde2cad72017-03-10 15:53:34 -0600368 EXPECT_EQ(TEQ1_R(0, 0, 1), tx_next_.header.PCB)
369 << "Actual next TX: " << teq1_pcb_to_name(tx_next_.header.PCB);
Will Drewryd4ae5282017-01-03 22:06:26 -0600370 EXPECT_EQ(kRuleResultSingleShot, result)
371 << "Actual result name: " << teq1_rule_result_to_name(result);
372};
373
Will Drewryd660eb42017-07-25 13:33:55 -0500374static const struct Teq1ProtocolOptions kTeq1Options = {
375 .host_address = 0xA5,
376 .node_address = 0x5A,
377 .bwt = 1.624f,
378 .etu = 0.00015f, /* elementary time unit, in seconds */
379 .preprocess = NULL,
380};
381
382std::string to_hex(const std::vector<uint8_t>& data) {
383 static constexpr char hex[] = "0123456789ABCDEF";
384 std::string out;
385 out.reserve(data.size() * 2);
386 for (uint8_t c : data) {
387 out.push_back(hex[c / 16]);
388 out.push_back(hex[c % 16]);
389 }
390 return out;
391}
392
393class EseWireFake : public EseOperationsInterface {
394 public:
395 EseWireFake() : tx_cursor_(0), rx_cursor_(0) { }
396 virtual ~EseWireFake() = default;
397
398 virtual int EseOpen(struct EseInterface *UNUSED(ese), void *UNUSED(data)) {
399 return 0;
400 }
401 virtual int EseReset(struct EseInterface *UNUSED(ese)) {
402 ALOGI("EseReset called!"); // Add to invocations
403 // Using the RX cursor, check for a reset expected.
404 // This is on RX because the s(resync) global counter is on session resets.
405 EXPECT_EQ(1, invocations.at(tx_cursor_).expect_reset);
406 return 0;
407 }
408 virtual int EsePoll(struct EseInterface *UNUSED(ese), uint8_t UNUSED(poll_for),
409 float UNUSED(timeout), int UNUSED(complete)) {
410 return 0;
411 }
412 virtual void EseClose(struct EseInterface *UNUSED(ese)) { };
413
414 virtual uint32_t EseTransceive(struct EseInterface *ese, const struct EseSgBuffer *tx_sg, uint32_t tx_nsg,
415 struct EseSgBuffer *rx_sg, uint32_t rx_nsg) {
416 rx_cursor_ = 0;
417 return teq1_transceive(ese, &kTeq1Options, tx_sg, tx_nsg, rx_sg, rx_nsg);
418 }
419
420 virtual uint32_t EseHwTransmit(struct EseInterface *UNUSED(ese), const uint8_t *data,
421 uint32_t len, int UNUSED(complete)) {
422 EXPECT_GT(invocations.size(), tx_cursor_);
423 if (invocations.size() <= tx_cursor_) {
424 return 0;
425 }
426 if (!len) {
427 return 0;
428 }
429 if (!invocations.size()) {
430 return 0;
431 }
432 // Just called once per teq1_transmit -- no partials.
433 const struct Invocation &invocation = invocations.at(tx_cursor_++);
434
435 EXPECT_EQ(invocation.expected_tx.size(), len);
436 int eq = memcmp(data, invocation.expected_tx.data(), len);
437 const std::vector<uint8_t> vec_data(data, data + len);
438 EXPECT_EQ(0, eq)
439 << "Got: '" << to_hex(vec_data) << "' "
440 << "Expected: '" << to_hex(invocation.expected_tx) << "'";
441
442 return len;
443 }
444
445 virtual uint32_t EseHwReceive(struct EseInterface *UNUSED(ese), uint8_t *data,
446 uint32_t len, int UNUSED(complete)) {
447 if (!len) {
448 return 0;
449 }
450 // Get this calls expected data.
451 EXPECT_GT(invocations.size(), rx_cursor_);
452 if (!invocations.size())
453 return 0;
454 struct Invocation &invocation = invocations.at(rx_cursor_);
455
456 // Supply the golden return data and pop off the invocation.
457 // Allows partial reads from the invocation stack.
458 uint32_t rx_total = 0;
459 if (len <= invocation.rx.size()) {
460 rx_total = len;
461 memcpy(data, invocation.rx.data(), invocation.rx.size());
462 }
463 uint32_t remaining = invocation.rx.size() - rx_total;
464 if (remaining && rx_total) {
465 invocation.rx.erase(invocation.rx.begin(),
466 invocation.rx.begin() + rx_total);
467 } else {
468 rx_cursor_++;
469 // RX shouldn't get ahead of TX.
470 EXPECT_GE(tx_cursor_, rx_cursor_);
471 // We could delete, but this make test bugs a little easier to see.
472 }
473 return rx_total;
474 }
475
476 struct Invocation {
477 std::vector<uint8_t> rx;
478 std::vector<uint8_t> expected_tx;
479 int expect_reset;
480 };
481
482 std::vector<Invocation> invocations;
483 private:
484 uint32_t tx_cursor_;
485 uint32_t rx_cursor_;
486};
487
488class Teq1TransceiveTest : public virtual Test {
489 public:
490 Teq1TransceiveTest() { }
491 virtual ~Teq1TransceiveTest() { }
492
493 void SetUp() {
494 // Configure ese with our internal ops.
495 EseOperationsWrapper::InitializeEse(&ese_, &wire_);
496 // Start with normal seq's.
497 TEQ1_INIT_CARD_STATE((struct Teq1CardState *)(&(ese_.pad[0])));
498 }
499
500 void TearDown() {
501 wire_.invocations.resize(0);
502 }
503
504 protected:
505 EseWireFake wire_;
506 EseInterface ese_;
507};
508
509
510TEST_F(Teq1TransceiveTest, NormalTransceiveUnchained) {
511 EXPECT_EQ(0, ese_open(&ese_, NULL));
512
513 // I(0,0) ->
514 // <- I(0, 0)
515 wire_.invocations.resize(1);
516 struct Teq1Frame frame;
517 size_t frame_size = 0;
518 frame.header.NAD = kTeq1Options.node_address;
519 frame.header.PCB = TEQ1_I(0, 0);
520 frame.header.LEN = 4;
521 frame.INF[0] = 'A';
522 frame.INF[1] = 'B';
523 frame.INF[2] = 'C';
524 frame.INF[3] = 'D';
525 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
526 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
527 wire_.invocations[0].expected_tx.resize(frame_size);
528 memcpy(wire_.invocations[0].expected_tx.data(), &frame.val[0], frame_size);
529 ALOGI("Planning to send:");
530 teq1_trace_transmit(frame.header.PCB, frame.header.LEN);
531
532 frame.header.LEN = 0;
533 frame.header.NAD = kTeq1Options.host_address;
534 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
535 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
536 wire_.invocations[0].rx.resize(frame_size);
537 memcpy(wire_.invocations[0].rx.data(), &frame, frame_size);
538 ALOGI("Expecting to receive:");
539 teq1_trace_receive(frame.header.PCB, frame.header.LEN);
540
541 const uint8_t payload[] = { 'A', 'B', 'C', 'D' };
542 uint8_t reply[5]; // Should stay empty.
543 EXPECT_EQ(0, ese_transceive(&ese_, payload, sizeof(payload), reply, sizeof(reply)));
544};
545
546
547TEST_F(Teq1TransceiveTest, NormalUnchainedRetransmitRecovery) {
548 EXPECT_EQ(0, ese_open(&ese_, NULL));
549
550 // I(0,0) [4] ->
551 // <- R(0, 1, 0)
552 // I(0,0) [4] ->
553 // <- I(0, 0)
554 wire_.invocations.resize(2);
555 struct Teq1Frame frame;
556 size_t frame_size = 0;
557 frame.header.NAD = kTeq1Options.node_address;
558 frame.header.PCB = TEQ1_I(0, 0);
559 frame.header.LEN = 4;
560 frame.INF[0] = 'A';
561 frame.INF[1] = 'B';
562 frame.INF[2] = 'C';
563 frame.INF[3] = 'D';
564 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
565 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
566 wire_.invocations[0].expected_tx.resize(frame_size);
567 memcpy(wire_.invocations[0].expected_tx.data(), &frame.val[0], frame_size);
568 wire_.invocations[1].expected_tx.resize(frame_size);
569 memcpy(wire_.invocations[1].expected_tx.data(), &frame.val[0], frame_size);
570
571 frame.header.LEN = 0;
572 frame.header.NAD = kTeq1Options.host_address;
573 frame.header.PCB = TEQ1_R(0, 1, 0);
574 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
575 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
576 wire_.invocations[0].rx.resize(frame_size);
577 memcpy(wire_.invocations[0].rx.data(), &frame, frame_size);
578
579 frame.header.LEN = 0;
580 frame.header.NAD = kTeq1Options.host_address;
581 frame.header.PCB = TEQ1_I(0, 0);
582 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
583 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
584 wire_.invocations[1].rx.resize(frame_size);
585 memcpy(wire_.invocations[1].rx.data(), &frame, frame_size);
586
587 const uint8_t payload[] = { 'A', 'B', 'C', 'D' };
588 uint8_t reply[5]; // Should stay empty.
589 EXPECT_EQ(0, ese_transceive(&ese_, payload, sizeof(payload), reply, sizeof(reply)));
590};
591
592TEST_F(Teq1TransceiveTest, RetransmitResyncRecovery) {
593 EXPECT_EQ(0, ese_open(&ese_, NULL));
594
595 // I(0,0) [4] ->
596 // <- R(0, 1, 0)
597 // I(0,0) [4] ->
598 // <- R(0, 1, 0)
599 // I(0,0) [4] ->
600 // <- R(0, 1, 0)
601 // I(0,0) [4] ->
602 // <- R(0, 1, 0)
603 // S(RESYNC, REQUEST) -> (retran this is another case)
604 // <- S(RESYNC, RESPONSE)
605 // I(0, 0) [4] ->
606 // <- I(0, 0) [0]
607 wire_.invocations.resize(6);
608 struct Teq1Frame frame;
609 size_t frame_size = 0;
610 frame.header.NAD = kTeq1Options.node_address;
611 frame.header.PCB = TEQ1_I(0, 0);
612 frame.header.LEN = 4;
613 frame.INF[0] = 'A';
614 frame.INF[1] = 'B';
615 frame.INF[2] = 'C';
616 frame.INF[3] = 'D';
617 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
618 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
619 wire_.invocations[0].expected_tx.resize(frame_size);
620 memcpy(wire_.invocations[0].expected_tx.data(), &frame.val[0], frame_size);
621 wire_.invocations[1].expected_tx.resize(frame_size);
622 memcpy(wire_.invocations[1].expected_tx.data(), &frame.val[0], frame_size);
623 wire_.invocations[2].expected_tx.resize(frame_size);
624 memcpy(wire_.invocations[2].expected_tx.data(), &frame.val[0], frame_size);
625 wire_.invocations[3].expected_tx.resize(frame_size);
626 memcpy(wire_.invocations[3].expected_tx.data(), &frame.val[0], frame_size);
627 wire_.invocations[5].expected_tx.resize(frame_size);
628 memcpy(wire_.invocations[5].expected_tx.data(), &frame.val[0], frame_size);
629
630 frame.header.LEN = 0;
631 frame.header.NAD = kTeq1Options.node_address;
632 frame.header.PCB = TEQ1_S_RESYNC(0);
633 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
634 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
635 wire_.invocations[4].expected_tx.resize(frame_size);
636 memcpy(wire_.invocations[4].expected_tx.data(), &frame, frame_size);
637
638 frame.header.LEN = 0;
639 frame.header.NAD = kTeq1Options.host_address;
640 frame.header.PCB = TEQ1_R(0, 1, 0);
641 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
642 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
643 wire_.invocations[0].rx.resize(frame_size);
644 memcpy(wire_.invocations[0].rx.data(), &frame, frame_size);
645 wire_.invocations[1].rx.resize(frame_size);
646 memcpy(wire_.invocations[1].rx.data(), &frame, frame_size);
647 wire_.invocations[2].rx.resize(frame_size);
648 memcpy(wire_.invocations[2].rx.data(), &frame, frame_size);
649 wire_.invocations[3].rx.resize(frame_size);
650 memcpy(wire_.invocations[3].rx.data(), &frame, frame_size);
651
652 frame.header.LEN = 0;
653 frame.header.NAD = kTeq1Options.host_address;
654 frame.header.PCB = TEQ1_S_RESYNC(1);
655 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
656 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
657 wire_.invocations[4].rx.resize(frame_size);
658 memcpy(wire_.invocations[4].rx.data(), &frame, frame_size);
659
660 frame.header.LEN = 0;
661 frame.header.NAD = kTeq1Options.host_address;
662 frame.header.PCB = TEQ1_I(0, 0);
663 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
664 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
665 wire_.invocations[5].rx.resize(frame_size);
666 memcpy(wire_.invocations[5].rx.data(), &frame, frame_size);
667
668 const uint8_t payload[] = { 'A', 'B', 'C', 'D' };
669 uint8_t reply[5]; // Should stay empty.
670 EXPECT_EQ(0, ese_transceive(&ese_, payload, sizeof(payload), reply, sizeof(reply)));
671};
672
673// Error case described in b/63546784
674TEST_F(Teq1TransceiveTest, RetransmitResyncLoop) {
675 EXPECT_EQ(0, ese_open(&ese_, NULL));
676
677 // I(0,0) [4] ->
678 // <- R(0, 1, 0)
679 // I(0,0) [4] ->
680 // <- R(0, 1, 0)
681 // I(0,0) [4] ->
682 // <- R(0, 1, 0)
683 // I(0,0) [4] ->
684 // <- R(0, 1, 0)
685 // S(RESYNC, REQUEST) ->
686 // <- S(RESYNC, RESPONSE)
687 // I(0,0) [4] ->
688 // <- R(0, 1, 0)
689 // I(0,0) [4] ->
690 // <- R(0, 1, 0)
691 // I(0,0) [4] ->
692 // <- R(0, 1, 0)
693 // I(0,0) [4] ->
694 // <- R(0, 1, 0)
695 // S(RESYNC, REQUEST) ->
696 // <- S(RESYNC, RESPONSE)
697 // ...
698 // 6 failure loops before a reset then 6 more before a hard failure.
699 wire_.invocations.resize(5 * 12);
700 struct Teq1Frame frame;
701 size_t frame_size = 0;
702
703 frame.header.NAD = kTeq1Options.node_address;
704 frame.header.PCB = TEQ1_I(0, 0);
705 frame.header.LEN = 4;
706 frame.INF[0] = 'A';
707 frame.INF[1] = 'B';
708 frame.INF[2] = 'C';
709 frame.INF[3] = 'D';
710 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
711 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
712 // Initialize all invocations to I/R then overwrite with resyncs.
713 for (auto &invocation : wire_.invocations) {
714 invocation.expected_tx.resize(frame_size);
715 memcpy(invocation.expected_tx.data(), &frame.val[0], frame_size);
716 }
717
718 frame.header.LEN = 0;
719 frame.header.NAD = kTeq1Options.host_address;
720 frame.header.PCB = TEQ1_R(0, 1, 0);
721 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
722 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
723 for (auto &invocation : wire_.invocations) {
724 invocation.rx.resize(frame_size);
725 memcpy(invocation.rx.data(), &frame.val[0], frame_size);
726 }
727
728 frame.header.LEN = 0;
729 frame.header.NAD = kTeq1Options.node_address;
730 frame.header.PCB = TEQ1_S_RESYNC(0);
731 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
732 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
733 int count = 0;
734 for (auto &invocation : wire_.invocations) {
735 if (++count % 5 == 0) {
736 invocation.expected_tx.resize(frame_size);
737 memcpy(invocation.expected_tx.data(), &frame, frame_size);
738 }
739 }
740
741 frame.header.LEN = 0;
742 frame.header.NAD = kTeq1Options.host_address;
743 frame.header.PCB = TEQ1_S_RESYNC(1);
744 frame.INF[frame.header.LEN] = teq1_compute_LRC(&frame);
745 frame_size = sizeof(frame.header) + frame.header.LEN + 1;
746 count = 0;
747 for (auto &invocation : wire_.invocations) {
748 if (++count % 5 == 0) {
749 invocation.rx.resize(frame_size);
750 memcpy(invocation.rx.data(), &frame, frame_size);
751 }
752 }
753
754 wire_.invocations[30].expect_reset = 1;
755
756 const uint8_t payload[] = { 'A', 'B', 'C', 'D' };
757 uint8_t reply[5]; // Should stay empty.
758 EXPECT_EQ(-1, ese_transceive(&ese_, payload, sizeof(payload), reply, sizeof(reply)));
759 EXPECT_NE(0, ese_error(&ese_));
760};
761
Will Drewryd4ae5282017-01-03 22:06:26 -0600762