-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfp_frame_command_test.cc
168 lines (141 loc) · 5.74 KB
/
fp_frame_command_test.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <vector>
#include <base/test/task_environment.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "biod/fp_frame_command.h"
namespace biod {
namespace {
using ::testing::Return;
constexpr int kValidMaxReadSize = 128;
constexpr int kValidFrameSize = 4096;
constexpr int kValidIndex = 0;
TEST(FpFrameCommand, FpFrameCommand) {
auto cmd =
FpFrameCommand::Create(kValidIndex, kValidFrameSize, kValidMaxReadSize);
EXPECT_TRUE(cmd);
EXPECT_EQ(cmd->Version(), 0);
EXPECT_EQ(cmd->Command(), EC_CMD_FP_FRAME);
}
TEST(FpFrameCommand, InvalidReadSize) {
constexpr int kInvalidMaxReadSize = kMaxPacketSize + 1;
EXPECT_FALSE(FpFrameCommand::Create(kValidIndex, kValidFrameSize,
kInvalidMaxReadSize));
}
TEST(FpFrameCommand, InvalidReadSizeZero) {
constexpr int kInvalidMaxReadSize = 0;
EXPECT_FALSE(FpFrameCommand::Create(kValidIndex, kValidFrameSize,
kInvalidMaxReadSize));
}
TEST(FpFrameCommand, MaxReadSizeEqualsMaxPacketSize) {
constexpr int kValidReadSize = kMaxPacketSize;
EXPECT_TRUE(
FpFrameCommand::Create(kValidIndex, kValidFrameSize, kValidReadSize));
}
TEST(FpFrameCommand, ZeroFrameSize) {
constexpr int kInvalidFrameSize = 0;
EXPECT_FALSE(FpFrameCommand::Create(kValidIndex, kInvalidFrameSize,
kValidMaxReadSize));
}
// Mock the underlying EcCommand to test
class FpFrameCommandTest : public testing::Test {
public:
class MockFpFrameCommand : public FpFrameCommand {
public:
MockFpFrameCommand(int index, uint32_t frame_size, ssize_t max_read_size)
: FpFrameCommand(index, frame_size, max_read_size) {
// Unless overridden, return packets full of zeroes.
static FpFramePacket packet = {0};
ON_CALL(*this, Resp).WillByDefault(Return(&packet));
}
MOCK_METHOD(bool, EcCommandRun, (int fd), (override));
MOCK_METHOD(FpFramePacket*, Resp, (), (override));
MOCK_METHOD(uint32_t, Result, (), (const, override));
};
protected:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
};
TEST_F(FpFrameCommandTest, Success) {
FpFramePacket packet = {1, 2, 3, 4, 5};
EXPECT_EQ(packet.size(), 544);
// Ec command payload is empty until EcCommandRun is called.
FpFramePacket payload = {0};
constexpr int kMaxReadSize = 536; // SPI max packet size is 544. Subtract
// the sizeof(struct ec_host_response)
// to get 536.
static_assert(kMaxReadSize <= packet.size(),
"Read size must be less than or equal to packet size");
// Create a frame that has two full packets worth of data and one partial
// packet.
constexpr int kFrameSize = kMaxReadSize + kMaxReadSize + 10;
auto mock_fp_frame_command =
FpFrameCommand::Create<MockFpFrameCommand>(0, kFrameSize, kMaxReadSize);
EXPECT_CALL(*mock_fp_frame_command, Resp).WillRepeatedly(Return(&payload));
EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
.WillRepeatedly(
// Command is run, so start returning actual packet.
[&payload, &packet](int fd) {
payload = packet;
return true;
});
EXPECT_TRUE(mock_fp_frame_command->Run(-1));
const auto& frame = mock_fp_frame_command->frame();
// First chunk
std::vector<uint8_t> packet_vec(packet.begin(),
packet.begin() + kMaxReadSize);
auto frame_begin = frame->begin();
auto frame_end = frame->begin() + packet_vec.size();
std::vector<uint8_t> frame_chunk_1(frame_begin, frame_end);
EXPECT_EQ(packet_vec, frame_chunk_1);
// Second chunk
frame_begin += packet_vec.size();
frame_end += packet_vec.size();
std::vector<uint8_t> frame_chunk_2(frame_begin, frame_end);
EXPECT_EQ(packet_vec, frame_chunk_2);
// Last chunk (short)
frame_begin += packet_vec.size();
frame_end += 10;
packet_vec.resize(10);
std::vector<uint8_t> frame_chunk_3(frame_begin, frame_end);
EXPECT_EQ(packet_vec, frame_chunk_3);
}
TEST_F(FpFrameCommandTest, RetriesWhenBusy) {
auto mock_fp_frame_command =
FpFrameCommand::Create<MockFpFrameCommand>(0, 4096, 128);
EXPECT_TRUE(mock_fp_frame_command);
EXPECT_CALL(*mock_fp_frame_command, Result).WillOnce(Return(EC_RES_BUSY));
EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
EXPECT_TRUE(mock_fp_frame_command->Run(-1));
}
TEST_F(FpFrameCommandTest, FailsIfBusyAfterFirstRequest) {
auto mock_fp_frame_command =
FpFrameCommand::Create<MockFpFrameCommand>(0, 4096, 128);
EXPECT_TRUE(mock_fp_frame_command);
EXPECT_CALL(*mock_fp_frame_command, Result).WillOnce(Return(EC_RES_BUSY));
EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
.WillOnce(Return(false)) // Failure on first request; triggers retry.
.WillOnce(Return(true)) // Retry succeeds.
.WillOnce(Return(false)); // Next request fails. Since it wasn't first
// request, no more retries.
EXPECT_FALSE(mock_fp_frame_command->Run(-1));
}
TEST_F(FpFrameCommandTest, StopsBusyRetriesAfterMaxAttempts) {
auto mock_fp_frame_command =
FpFrameCommand::Create<MockFpFrameCommand>(0, 4096, 128);
EXPECT_TRUE(mock_fp_frame_command);
EXPECT_CALL(*mock_fp_frame_command, EcCommandRun)
.Times(51)
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_fp_frame_command, Result)
.Times(51)
.WillRepeatedly(Return(EC_RES_BUSY));
EXPECT_FALSE(mock_fp_frame_command->Run(-1));
}
} // namespace
} // namespace biod