1 /*
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 
17 #include <android/hardware/weaver/1.0/IWeaver.h>
18 #include <gtest/gtest.h>
19 #include <hidl/GtestPrinter.h>
20 #include <hidl/ServiceManagement.h>
21 
22 #include <limits>
23 
24 using ::android::hardware::weaver::V1_0::IWeaver;
25 using ::android::hardware::weaver::V1_0::WeaverConfig;
26 using ::android::hardware::weaver::V1_0::WeaverReadStatus;
27 using ::android::hardware::weaver::V1_0::WeaverReadResponse;
28 using ::android::hardware::weaver::V1_0::WeaverStatus;
29 using ::android::hardware::Return;
30 using ::android::sp;
31 
32 const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
33 const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
34 const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
35 const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
36 
37 struct WeaverHidlTest : public ::testing::TestWithParam<std::string> {
SetUpWeaverHidlTest38     virtual void SetUp() override {
39         weaver = IWeaver::getService(GetParam());
40         ASSERT_NE(weaver, nullptr);
41     }
42 
TearDownWeaverHidlTest43     virtual void TearDown() override {}
44 
45     sp<IWeaver> weaver;
46 };
47 
48 /*
49  * Checks config values are suitably large
50  */
TEST_P(WeaverHidlTest,GetConfig)51 TEST_P(WeaverHidlTest, GetConfig) {
52     WeaverStatus status;
53     WeaverConfig config;
54 
55     bool callbackCalled = false;
56     auto ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
57         callbackCalled = true;
58         status = s;
59         config = c;
60     });
61     ASSERT_TRUE(ret.isOk());
62     ASSERT_TRUE(callbackCalled);
63     ASSERT_EQ(status, WeaverStatus::OK);
64 
65     EXPECT_GE(config.slots, 16u);
66     EXPECT_GE(config.keySize, 16u);
67     EXPECT_GE(config.valueSize, 16u);
68 }
69 
70 /*
71  * Gets the config twice and checks they are the same
72  */
TEST_P(WeaverHidlTest,GettingConfigMultipleTimesGivesSameResult)73 TEST_P(WeaverHidlTest, GettingConfigMultipleTimesGivesSameResult) {
74     WeaverConfig config1;
75     WeaverConfig config2;
76 
77     WeaverStatus status;
78     bool callbackCalled = false;
79     auto ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
80         callbackCalled = true;
81         status = s;
82         config1 = c;
83     });
84     ASSERT_TRUE(ret.isOk());
85     ASSERT_TRUE(callbackCalled);
86     ASSERT_EQ(status, WeaverStatus::OK);
87 
88     callbackCalled = false;
89     ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
90         callbackCalled = true;
91         status = s;
92         config2 = c;
93     });
94     ASSERT_TRUE(ret.isOk());
95     ASSERT_TRUE(callbackCalled);
96     ASSERT_EQ(status, WeaverStatus::OK);
97 
98     EXPECT_EQ(config1, config2);
99 }
100 
101 /*
102  * Gets the number of slots from the config and writes a key and value to the last one
103  */
TEST_P(WeaverHidlTest,WriteToLastSlot)104 TEST_P(WeaverHidlTest, WriteToLastSlot) {
105     WeaverStatus status;
106     WeaverConfig config;
107     const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
108         status = s;
109         config = c;
110     });
111     ASSERT_TRUE(configRet.isOk());
112     ASSERT_EQ(status, WeaverStatus::OK);
113 
114     const uint32_t lastSlot = config.slots - 1;
115     const auto writeRet = weaver->write(lastSlot, KEY, VALUE);
116     ASSERT_TRUE(writeRet.isOk());
117     ASSERT_EQ(writeRet, WeaverStatus::OK);
118 }
119 
120 /*
121  * Writes a key and value to a slot
122  * Reads the slot with the same key and receives the value that was previously written
123  */
TEST_P(WeaverHidlTest,WriteFollowedByReadGivesTheSameValue)124 TEST_P(WeaverHidlTest, WriteFollowedByReadGivesTheSameValue) {
125     constexpr uint32_t slotId = 0;
126     const auto ret = weaver->write(slotId, KEY, VALUE);
127     ASSERT_TRUE(ret.isOk());
128     ASSERT_EQ(ret, WeaverStatus::OK);
129 
130     bool callbackCalled = false;
131     WeaverReadStatus status;
132     std::vector<uint8_t> readValue;
133     uint32_t timeout;
134     const auto readRet = weaver->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
135         callbackCalled = true;
136         status = s;
137         readValue = r.value;
138         timeout = r.timeout;
139     });
140     ASSERT_TRUE(readRet.isOk());
141     ASSERT_TRUE(callbackCalled);
142     ASSERT_EQ(status, WeaverReadStatus::OK);
143     EXPECT_EQ(readValue, VALUE);
144     EXPECT_EQ(timeout, 0u);
145 }
146 
147 /*
148  * Writes a key and value to a slot
149  * Overwrites the slot with a new key and value
150  * Reads the slot with the new key and receives the new value
151  */
TEST_P(WeaverHidlTest,OverwritingSlotUpdatesTheValue)152 TEST_P(WeaverHidlTest, OverwritingSlotUpdatesTheValue) {
153     constexpr uint32_t slotId = 0;
154     const auto initialWriteRet = weaver->write(slotId, WRONG_KEY, VALUE);
155     ASSERT_TRUE(initialWriteRet.isOk());
156     ASSERT_EQ(initialWriteRet, WeaverStatus::OK);
157 
158     const auto overwriteRet = weaver->write(slotId, KEY, OTHER_VALUE);
159     ASSERT_TRUE(overwriteRet.isOk());
160     ASSERT_EQ(overwriteRet, WeaverStatus::OK);
161 
162     bool callbackCalled = false;
163     WeaverReadStatus status;
164     std::vector<uint8_t> readValue;
165     uint32_t timeout;
166     const auto readRet = weaver->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
167         callbackCalled = true;
168         status = s;
169         readValue = r.value;
170         timeout = r.timeout;
171     });
172     ASSERT_TRUE(readRet.isOk());
173     ASSERT_TRUE(callbackCalled);
174     ASSERT_EQ(status, WeaverReadStatus::OK);
175     EXPECT_EQ(readValue, OTHER_VALUE);
176     EXPECT_EQ(timeout, 0u);
177 }
178 
179 /*
180  * Writes a key and value to a slot
181  * Reads the slot with a different key so does not receive the value
182  */
TEST_P(WeaverHidlTest,WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue)183 TEST_P(WeaverHidlTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
184     constexpr uint32_t slotId = 0;
185     const auto ret = weaver->write(slotId, KEY, VALUE);
186     ASSERT_TRUE(ret.isOk());
187     ASSERT_EQ(ret, WeaverStatus::OK);
188 
189     bool callbackCalled = false;
190     WeaverReadStatus status;
191     std::vector<uint8_t> readValue;
192     const auto readRet =
193         weaver->read(slotId, WRONG_KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
194             callbackCalled = true;
195             status = s;
196             readValue = r.value;
197         });
198     ASSERT_TRUE(callbackCalled);
199     ASSERT_TRUE(readRet.isOk());
200     ASSERT_EQ(status, WeaverReadStatus::INCORRECT_KEY);
201     EXPECT_TRUE(readValue.empty());
202 }
203 
204 /*
205  * Writing to an invalid slot fails
206  */
TEST_P(WeaverHidlTest,WritingToInvalidSlotFails)207 TEST_P(WeaverHidlTest, WritingToInvalidSlotFails) {
208     WeaverStatus status;
209     WeaverConfig config;
210     const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
211         status = s;
212         config = c;
213     });
214     ASSERT_TRUE(configRet.isOk());
215     ASSERT_EQ(status, WeaverStatus::OK);
216 
217     if (config.slots == std::numeric_limits<uint32_t>::max()) {
218         // If there are no invalid slots then pass
219         return;
220     }
221 
222     const auto writeRet = weaver->write(config.slots, KEY, VALUE);
223     ASSERT_TRUE(writeRet.isOk());
224     ASSERT_EQ(writeRet, WeaverStatus::FAILED);
225 }
226 
227 /*
228  * Reading from an invalid slot fails rather than incorrect key
229  */
TEST_P(WeaverHidlTest,ReadingFromInvalidSlotFails)230 TEST_P(WeaverHidlTest, ReadingFromInvalidSlotFails) {
231     WeaverStatus status;
232     WeaverConfig config;
233     const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
234         status = s;
235         config = c;
236     });
237     ASSERT_TRUE(configRet.isOk());
238     ASSERT_EQ(status, WeaverStatus::OK);
239 
240     if (config.slots == std::numeric_limits<uint32_t>::max()) {
241         // If there are no invalid slots then pass
242         return;
243     }
244 
245     bool callbackCalled = false;
246     WeaverReadStatus readStatus;
247     std::vector<uint8_t> readValue;
248     uint32_t timeout;
249     const auto readRet =
250         weaver->read(config.slots, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
251             callbackCalled = true;
252             readStatus = s;
253             readValue = r.value;
254             timeout = r.timeout;
255         });
256     ASSERT_TRUE(callbackCalled);
257     ASSERT_TRUE(readRet.isOk());
258     ASSERT_EQ(readStatus, WeaverReadStatus::FAILED);
259     EXPECT_TRUE(readValue.empty());
260     EXPECT_EQ(timeout, 0u);
261 }
262 
263 /*
264  * Writing a key that is too large fails
265  */
TEST_P(WeaverHidlTest,WriteWithTooLargeKeyFails)266 TEST_P(WeaverHidlTest, WriteWithTooLargeKeyFails) {
267     WeaverStatus status;
268     WeaverConfig config;
269     const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
270         status = s;
271         config = c;
272     });
273     ASSERT_TRUE(configRet.isOk());
274     ASSERT_EQ(status, WeaverStatus::OK);
275 
276     std::vector<uint8_t> bigKey(config.keySize + 1);
277 
278     constexpr uint32_t slotId = 0;
279     const auto writeRet = weaver->write(slotId, bigKey, VALUE);
280     ASSERT_TRUE(writeRet.isOk());
281     ASSERT_EQ(writeRet, WeaverStatus::FAILED);
282 }
283 
284 /*
285  * Writing a value that is too large fails
286  */
TEST_P(WeaverHidlTest,WriteWithTooLargeValueFails)287 TEST_P(WeaverHidlTest, WriteWithTooLargeValueFails) {
288     WeaverStatus status;
289     WeaverConfig config;
290     const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
291         status = s;
292         config = c;
293     });
294     ASSERT_TRUE(configRet.isOk());
295     ASSERT_EQ(status, WeaverStatus::OK);
296 
297     std::vector<uint8_t> bigValue(config.valueSize + 1);
298 
299     constexpr uint32_t slotId = 0;
300     const auto writeRet = weaver->write(slotId, KEY, bigValue);
301     ASSERT_TRUE(writeRet.isOk());
302     ASSERT_EQ(writeRet, WeaverStatus::FAILED);
303 }
304 
305 /*
306  * Reading with a key that is loo large fails
307  */
TEST_P(WeaverHidlTest,ReadWithTooLargeKeyFails)308 TEST_P(WeaverHidlTest, ReadWithTooLargeKeyFails) {
309     WeaverStatus status;
310     WeaverConfig config;
311     const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
312         status = s;
313         config = c;
314     });
315     ASSERT_TRUE(configRet.isOk());
316     ASSERT_EQ(status, WeaverStatus::OK);
317 
318     std::vector<uint8_t> bigKey(config.keySize + 1);
319 
320     constexpr uint32_t slotId = 0;
321     bool callbackCalled = false;
322     WeaverReadStatus readStatus;
323     std::vector<uint8_t> readValue;
324     uint32_t timeout;
325     const auto readRet =
326         weaver->read(slotId, bigKey, [&](WeaverReadStatus s, WeaverReadResponse r) {
327             callbackCalled = true;
328             readStatus = s;
329             readValue = r.value;
330             timeout = r.timeout;
331         });
332     ASSERT_TRUE(callbackCalled);
333     ASSERT_TRUE(readRet.isOk());
334     ASSERT_EQ(readStatus, WeaverReadStatus::FAILED);
335     EXPECT_TRUE(readValue.empty());
336     EXPECT_EQ(timeout, 0u);
337 }
338 
339 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverHidlTest);
340 INSTANTIATE_TEST_SUITE_P(
341         PerInstance, WeaverHidlTest,
342         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IWeaver::descriptor)),
343         android::hardware::PrintInstanceNameToString);
344