1 /*
2  * Copyright (C) 2020 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 #include <aidl/Gtest.h>
17 #include <aidl/Vintf.h>
18 
19 #include <aidl/android/hardware/weaver/IWeaver.h>
20 #include <android/binder_manager.h>
21 #include <android/binder_process.h>
22 
23 #include <limits>
24 
25 using ::aidl::android::hardware::weaver::IWeaver;
26 using ::aidl::android::hardware::weaver::WeaverConfig;
27 using ::aidl::android::hardware::weaver::WeaverReadResponse;
28 
29 using ::ndk::SpAIBinder;
30 
31 const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
32 const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
33 const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
34 const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
35 
36 struct WeaverAidlTest : public ::testing::TestWithParam<std::string> {
SetUpWeaverAidlTest37     virtual void SetUp() override {
38         weaver = IWeaver::fromBinder(
39             SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
40         ASSERT_NE(weaver, nullptr);
41     }
42 
TearDownWeaverAidlTest43     virtual void TearDown() override {}
44 
45     std::shared_ptr<IWeaver> weaver;
46 };
47 
48 /*
49  * Checks config values are suitably large
50  */
TEST_P(WeaverAidlTest,GetConfig)51 TEST_P(WeaverAidlTest, GetConfig) {
52     WeaverConfig config;
53 
54     auto ret = weaver->getConfig(&config);
55 
56     ASSERT_TRUE(ret.isOk());
57 
58     EXPECT_GE(config.slots, 16u);
59     EXPECT_GE(config.keySize, 16u);
60     EXPECT_GE(config.valueSize, 16u);
61 }
62 
63 /*
64  * Gets the config twice and checks they are the same
65  */
TEST_P(WeaverAidlTest,GettingConfigMultipleTimesGivesSameResult)66 TEST_P(WeaverAidlTest, GettingConfigMultipleTimesGivesSameResult) {
67     WeaverConfig config1;
68     WeaverConfig config2;
69 
70     auto ret = weaver->getConfig(&config1);
71     ASSERT_TRUE(ret.isOk());
72 
73     ret = weaver->getConfig(&config2);
74     ASSERT_TRUE(ret.isOk());
75 
76     EXPECT_EQ(config1, config2);
77 }
78 
79 /*
80  * Gets the number of slots from the config and writes a key and value to the last one
81  */
TEST_P(WeaverAidlTest,WriteToLastSlot)82 TEST_P(WeaverAidlTest, WriteToLastSlot) {
83     WeaverConfig config;
84     const auto configRet = weaver->getConfig(&config);
85 
86     ASSERT_TRUE(configRet.isOk());
87 
88     const uint32_t lastSlot = config.slots - 1;
89     const auto writeRet = weaver->write(lastSlot, KEY, VALUE);
90     ASSERT_TRUE(writeRet.isOk());
91 }
92 
93 /*
94  * Writes a key and value to a slot
95  * Reads the slot with the same key and receives the value that was previously written
96  */
TEST_P(WeaverAidlTest,WriteFollowedByReadGivesTheSameValue)97 TEST_P(WeaverAidlTest, WriteFollowedByReadGivesTheSameValue) {
98     constexpr uint32_t slotId = 0;
99     const auto ret = weaver->write(slotId, KEY, VALUE);
100     ASSERT_TRUE(ret.isOk());
101 
102     WeaverReadResponse response;
103     std::vector<uint8_t> readValue;
104     uint32_t timeout;
105     const auto readRet = weaver->read(slotId, KEY, &response);
106 
107     readValue = response.value;
108     timeout = response.timeout;
109 
110     ASSERT_TRUE(readRet.isOk());
111     EXPECT_EQ(readValue, VALUE);
112     EXPECT_EQ(timeout, 0u);
113 }
114 
115 /*
116  * Writes a key and value to a slot
117  * Overwrites the slot with a new key and value
118  * Reads the slot with the new key and receives the new value
119  */
TEST_P(WeaverAidlTest,OverwritingSlotUpdatesTheValue)120 TEST_P(WeaverAidlTest, OverwritingSlotUpdatesTheValue) {
121     constexpr uint32_t slotId = 0;
122     const auto initialWriteRet = weaver->write(slotId, WRONG_KEY, VALUE);
123     ASSERT_TRUE(initialWriteRet.isOk());
124 
125     const auto overwriteRet = weaver->write(slotId, KEY, OTHER_VALUE);
126     ASSERT_TRUE(overwriteRet.isOk());
127 
128     WeaverReadResponse response;
129     std::vector<uint8_t> readValue;
130     uint32_t timeout;
131     const auto readRet = weaver->read(slotId, KEY, &response);
132 
133     readValue = response.value;
134     timeout = response.timeout;
135 
136     ASSERT_TRUE(readRet.isOk());
137     EXPECT_EQ(readValue, OTHER_VALUE);
138     EXPECT_EQ(timeout, 0u);
139 }
140 
141 /*
142  * Writes a key and value to a slot
143  * Reads the slot with a different key so does not receive the value
144  */
TEST_P(WeaverAidlTest,WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue)145 TEST_P(WeaverAidlTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
146     constexpr uint32_t slotId = 0;
147     const auto ret = weaver->write(slotId, KEY, VALUE);
148     ASSERT_TRUE(ret.isOk());
149 
150     WeaverReadResponse response;
151     std::vector<uint8_t> readValue;
152     const auto readRet =
153         weaver->read(slotId, WRONG_KEY, &response);
154 
155     readValue = response.value;
156 
157     ASSERT_FALSE(readRet.isOk());
158     ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
159     ASSERT_EQ(IWeaver::STATUS_INCORRECT_KEY, readRet.getServiceSpecificError());
160     EXPECT_TRUE(readValue.empty());
161 }
162 
163 /*
164  * Writing to an invalid slot fails
165  */
TEST_P(WeaverAidlTest,WritingToInvalidSlotFails)166 TEST_P(WeaverAidlTest, WritingToInvalidSlotFails) {
167     WeaverConfig config;
168     const auto configRet = weaver->getConfig(&config);
169     ASSERT_TRUE(configRet.isOk());
170 
171     if (config.slots == std::numeric_limits<uint32_t>::max()) {
172         // If there are no invalid slots then pass
173         return;
174     }
175 
176     const auto writeRet = weaver->write(config.slots, KEY, VALUE);
177     ASSERT_FALSE(writeRet.isOk());
178 }
179 
180 /*
181  * Reading from an invalid slot fails rather than incorrect key
182  */
TEST_P(WeaverAidlTest,ReadingFromInvalidSlotFails)183 TEST_P(WeaverAidlTest, ReadingFromInvalidSlotFails) {
184     WeaverConfig config;
185     const auto configRet = weaver->getConfig(&config);
186     ASSERT_TRUE(configRet.isOk());
187 
188     if (config.slots == std::numeric_limits<uint32_t>::max()) {
189         // If there are no invalid slots then pass
190         return;
191     }
192 
193     WeaverReadResponse response;
194     std::vector<uint8_t> readValue;
195     uint32_t timeout;
196     const auto readRet =
197         weaver->read(config.slots, KEY, &response);
198 
199     readValue = response.value;
200     timeout = response.timeout;
201 
202     ASSERT_FALSE(readRet.isOk());
203     ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
204     ASSERT_EQ(IWeaver::STATUS_FAILED, readRet.getServiceSpecificError());
205     EXPECT_TRUE(readValue.empty());
206     EXPECT_EQ(timeout, 0u);
207 }
208 
209 /*
210  * Writing a key that is too large fails
211  */
TEST_P(WeaverAidlTest,WriteWithTooLargeKeyFails)212 TEST_P(WeaverAidlTest, WriteWithTooLargeKeyFails) {
213     WeaverConfig config;
214     const auto configRet = weaver->getConfig(&config);
215     ASSERT_TRUE(configRet.isOk());
216 
217     std::vector<uint8_t> bigKey(config.keySize + 1);
218 
219     constexpr uint32_t slotId = 0;
220     const auto writeRet = weaver->write(slotId, bigKey, VALUE);
221     ASSERT_FALSE(writeRet.isOk());
222 }
223 
224 /*
225  * Writing a value that is too large fails
226  */
TEST_P(WeaverAidlTest,WriteWithTooLargeValueFails)227 TEST_P(WeaverAidlTest, WriteWithTooLargeValueFails) {
228     WeaverConfig config;
229     const auto configRet = weaver->getConfig(&config);
230     ASSERT_TRUE(configRet.isOk());
231 
232     std::vector<uint8_t> bigValue(config.valueSize + 1);
233 
234     constexpr uint32_t slotId = 0;
235     const auto writeRet = weaver->write(slotId, KEY, bigValue);
236     ASSERT_FALSE(writeRet.isOk());
237 }
238 
239 /*
240  * Reading with a key that is loo large fails
241  */
TEST_P(WeaverAidlTest,ReadWithTooLargeKeyFails)242 TEST_P(WeaverAidlTest, ReadWithTooLargeKeyFails) {
243     WeaverConfig config;
244     const auto configRet = weaver->getConfig(&config);
245     ASSERT_TRUE(configRet.isOk());
246 
247     std::vector<uint8_t> bigKey(config.keySize + 1);
248 
249     constexpr uint32_t slotId = 0;
250     WeaverReadResponse response;
251     std::vector<uint8_t> readValue;
252     uint32_t timeout;
253     const auto readRet =
254         weaver->read(slotId, bigKey, &response);
255 
256     readValue = response.value;
257     timeout = response.timeout;
258 
259     ASSERT_FALSE(readRet.isOk());
260     ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
261     ASSERT_EQ(IWeaver::STATUS_FAILED, readRet.getServiceSpecificError());
262     EXPECT_TRUE(readValue.empty());
263     EXPECT_EQ(timeout, 0u);
264 }
265 
266 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverAidlTest);
267 INSTANTIATE_TEST_SUITE_P(
268         PerInstance, WeaverAidlTest,
269         testing::ValuesIn(android::getAidlHalInstanceNames(IWeaver::descriptor)),
270         android::PrintInstanceNameToString);
271 
main(int argc,char ** argv)272 int main(int argc, char** argv) {
273     ::testing::InitGoogleTest(&argc, argv);
274     ABinderProcess_setThreadPoolMaxThreadCount(1);
275     ABinderProcess_startThreadPool();
276     return RUN_ALL_TESTS();
277 }
278