• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "rpc_test.h"
18 
19 #include <cstdint>
20 
21 #include "chre/core/event_loop.h"
22 #include "chre/core/event_loop_manager.h"
23 #include "chre/core/settings.h"
24 #include "chre/util/nanoapp/log.h"
25 #include "chre/util/time.h"
26 #include "chre_api/chre/event.h"
27 #include "chre_api/chre/re.h"
28 
29 #include "gtest/gtest.h"
30 #include "inc/test_util.h"
31 #include "test_base.h"
32 #include "test_event.h"
33 #include "test_event_queue.h"
34 #include "test_util.h"
35 
36 namespace chre {
37 
Increment(const chre_rpc_NumberMessage & request,chre_rpc_NumberMessage & response)38 pw::Status RpcTestService::Increment(const chre_rpc_NumberMessage &request,
39                                      chre_rpc_NumberMessage &response) {
40   EnvSingleton::get()->mServer.setPermissionForNextMessage(
41       CHRE_MESSAGE_PERMISSION_NONE);
42   response.number = request.number + 1;
43   return pw::OkStatus();
44 }
45 
46 namespace {
47 
48 class RpcTest : public TestBase {};
49 
TEST_F(RpcTest,PwRpcCanPublishServicesInNanoappStart)50 TEST_F(RpcTest, PwRpcCanPublishServicesInNanoappStart) {
51   class App : public TestNanoapp {
52    public:
53     bool start() override {
54       struct chreNanoappRpcService servicesA[] = {
55           {.id = 1, .version = 0},
56           {.id = 2, .version = 0},
57       };
58 
59       struct chreNanoappRpcService servicesB[] = {
60           {.id = 3, .version = 0},
61           {.id = 4, .version = 0},
62       };
63 
64       return chrePublishRpcServices(servicesA, 2 /* numServices */) &&
65              chrePublishRpcServices(servicesB, 2 /* numServices */);
66     }
67   };
68 
69   uint64_t appId = loadNanoapp(MakeUnique<App>());
70   Nanoapp *napp = getNanoappByAppId(appId);
71   ASSERT_NE(napp, nullptr);
72 
73   EXPECT_EQ(napp->getRpcServices().size(), 4);
74   EXPECT_EQ(napp->getRpcServices()[0].id, 1);
75   EXPECT_EQ(napp->getRpcServices()[1].id, 2);
76   EXPECT_EQ(napp->getRpcServices()[2].id, 3);
77   EXPECT_EQ(napp->getRpcServices()[3].id, 4);
78 }
79 
TEST_F(RpcTest,PwRpcCanNotPublishDuplicateServices)80 TEST_F(RpcTest, PwRpcCanNotPublishDuplicateServices) {
81   class App : public TestNanoapp {
82     bool start() override {
83       struct chreNanoappRpcService servicesA[] = {
84           {.id = 1, .version = 0},
85           {.id = 2, .version = 0},
86       };
87 
88       bool success = chrePublishRpcServices(servicesA, 2 /* numServices */);
89 
90       EXPECT_FALSE(chrePublishRpcServices(servicesA, 2 /* numServices */));
91 
92       struct chreNanoappRpcService servicesB[] = {
93           {.id = 5, .version = 0},
94           {.id = 5, .version = 0},
95       };
96 
97       EXPECT_FALSE(chrePublishRpcServices(servicesB, 2 /* numServices */));
98 
99       return success;
100     }
101   };
102 
103   uint64_t appId = loadNanoapp(MakeUnique<App>());
104   Nanoapp *napp = getNanoappByAppId(appId);
105   ASSERT_NE(napp, nullptr);
106 
107   EXPECT_EQ(napp->getRpcServices().size(), 2);
108   EXPECT_EQ(napp->getRpcServices()[0].id, 1);
109   EXPECT_EQ(napp->getRpcServices()[1].id, 2);
110 }
111 
TEST_F(RpcTest,PwRpcDifferentAppCanPublishSameServices)112 TEST_F(RpcTest, PwRpcDifferentAppCanPublishSameServices) {
113   class App : public TestNanoapp {
114    public:
115     explicit App(uint64_t id) : TestNanoapp(TestNanoappInfo{.id = id}) {}
116 
117     bool start() override {
118       struct chreNanoappRpcService services[] = {
119           {.id = 1, .version = 0},
120           {.id = 2, .version = 0},
121       };
122 
123       return chrePublishRpcServices(services, 2 /* numServices */);
124     }
125   };
126 
127   uint64_t app1Id = loadNanoapp(MakeUnique<App>(0x01));
128   uint64_t app2Id = loadNanoapp(MakeUnique<App>(0x02));
129   Nanoapp *napp1 = getNanoappByAppId(app1Id);
130   ASSERT_NE(napp1, nullptr);
131 
132   EXPECT_EQ(napp1->getRpcServices().size(), 2);
133   EXPECT_EQ(napp1->getRpcServices()[0].id, 1);
134   EXPECT_EQ(napp1->getRpcServices()[1].id, 2);
135 
136   Nanoapp *napp2 = getNanoappByAppId(app2Id);
137   ASSERT_NE(napp2, nullptr);
138 
139   EXPECT_EQ(napp2->getRpcServices().size(), 2);
140   EXPECT_EQ(napp2->getRpcServices()[0].id, 1);
141   EXPECT_EQ(napp2->getRpcServices()[1].id, 2);
142 }
143 
TEST_F(RpcTest,PwRpcCanNotPublishServicesOutsideOfNanoappStart)144 TEST_F(RpcTest, PwRpcCanNotPublishServicesOutsideOfNanoappStart) {
145   CREATE_CHRE_TEST_EVENT(PUBLISH_SERVICES, 0);
146 
147   class App : public TestNanoapp {
148    public:
149     void handleEvent(uint32_t, uint16_t eventType,
150                      const void *eventData) override {
151       switch (eventType) {
152         case CHRE_EVENT_TEST_EVENT: {
153           auto event = static_cast<const TestEvent *>(eventData);
154           switch (event->type) {
155             case PUBLISH_SERVICES: {
156               struct chreNanoappRpcService services[] = {
157                   {.id = 1, .version = 0},
158                   {.id = 2, .version = 0},
159               };
160 
161               bool success =
162                   chrePublishRpcServices(services, 2 /* numServices */);
163               TestEventQueueSingleton::get()->pushEvent(PUBLISH_SERVICES,
164                                                         success);
165               break;
166             }
167           }
168         }
169       }
170     }
171   };
172 
173   uint64_t appId = loadNanoapp(MakeUnique<App>());
174 
175   bool success = true;
176   sendEventToNanoapp(appId, PUBLISH_SERVICES);
177   waitForEvent(PUBLISH_SERVICES, &success);
178   EXPECT_FALSE(success);
179 
180   Nanoapp *napp = getNanoappByAppId(appId);
181   ASSERT_NE(napp, nullptr);
182 
183   EXPECT_EQ(napp->getRpcServices().size(), 0);
184 }
185 
TEST_F(RpcTest,PwRpcRegisterServicesShouldGracefullyFailOnDuplicatedService)186 TEST_F(RpcTest, PwRpcRegisterServicesShouldGracefullyFailOnDuplicatedService) {
187   class App : public TestNanoapp {
188    public:
189     bool start() override {
190       static RpcTestService testService;
191 
192       chre::RpcServer::Service service = {.service = testService,
193                                           .id = 0xca8f7150a3f05847,
194                                           .version = 0x01020034};
195 
196       chre::RpcServer &server = EnvSingleton::get()->mServer;
197 
198       bool status = server.registerServices(1, &service);
199 
200       EXPECT_TRUE(status);
201 
202       EXPECT_FALSE(server.registerServices(1, &service));
203 
204       return status;
205     }
206 
207     void end() override {
208       EnvSingleton::get()->closeServer();
209     }
210   };
211 
212   EnvSingleton::init();
213   uint64_t appId = loadNanoapp(MakeUnique<App>());
214   unloadNanoapp(appId);
215   EnvSingleton::deinit();
216 }
217 
TEST_F(RpcTest,PwRpcGetNanoappInfoByAppIdReturnsServices)218 TEST_F(RpcTest, PwRpcGetNanoappInfoByAppIdReturnsServices) {
219   CREATE_CHRE_TEST_EVENT(QUERY_INFO, 0);
220 
221   class App : public TestNanoapp {
222    public:
223     bool start() override {
224       struct chreNanoappRpcService services[] = {
225           {.id = 1, .version = 2},
226           {.id = 2, .version = 3},
227       };
228 
229       return chrePublishRpcServices(services, 2 /* numServices */);
230     }
231 
232     void handleEvent(uint32_t, uint16_t eventType,
233                      const void *eventData) override {
234       switch (eventType) {
235         case CHRE_EVENT_TEST_EVENT: {
236           auto event = static_cast<const TestEvent *>(eventData);
237           switch (event->type) {
238             case QUERY_INFO: {
239               auto id = static_cast<uint64_t *>(event->data);
240               bool success = chreGetNanoappInfoByAppId(*id, &mInfo);
241               const struct chreNanoappInfo *pInfo = success ? &mInfo : nullptr;
242               TestEventQueueSingleton::get()->pushEvent(QUERY_INFO, pInfo);
243               break;
244             }
245           }
246         }
247       }
248     }
249 
250    protected:
251     struct chreNanoappInfo mInfo;
252   };
253 
254   uint64_t appId = loadNanoapp(MakeUnique<App>());
255 
256   struct chreNanoappInfo *pInfo = nullptr;
257   sendEventToNanoapp(appId, QUERY_INFO, appId);
258   waitForEvent(QUERY_INFO, &pInfo);
259   EXPECT_TRUE(pInfo != nullptr);
260   EXPECT_EQ(pInfo->rpcServiceCount, 2);
261   EXPECT_EQ(pInfo->rpcServices[0].id, 1);
262   EXPECT_EQ(pInfo->rpcServices[0].version, 2);
263   EXPECT_EQ(pInfo->rpcServices[1].id, 2);
264   EXPECT_EQ(pInfo->rpcServices[1].version, 3);
265   EXPECT_EQ(pInfo->reserved[0], 0);
266   EXPECT_EQ(pInfo->reserved[1], 0);
267   EXPECT_EQ(pInfo->reserved[2], 0);
268 }
269 
TEST_F(RpcTest,PwRpcClientNanoappCanRequestServerNanoapp)270 TEST_F(RpcTest, PwRpcClientNanoappCanRequestServerNanoapp) {
271   CREATE_CHRE_TEST_EVENT(INCREMENT_REQUEST, 0);
272 
273   class ClientApp : public TestNanoapp {
274    public:
275     ClientApp() : TestNanoapp(TestNanoappInfo{.id = kPwRcpClientAppId}) {}
276 
277     void handleEvent(uint32_t senderInstanceId, uint16_t eventType,
278                      const void *eventData) override {
279       Env *env = EnvSingleton::get();
280 
281       env->mClient.handleEvent(senderInstanceId, eventType, eventData);
282       switch (eventType) {
283         case CHRE_EVENT_TEST_EVENT: {
284           auto event = static_cast<const TestEvent *>(eventData);
285           switch (event->type) {
286             case INCREMENT_REQUEST: {
287               auto client =
288                   env->mClient
289                       .get<rpc::pw_rpc::nanopb::RpcTestService::Client>();
290               if (client.has_value()) {
291                 chre_rpc_NumberMessage incrementRequest;
292                 incrementRequest.number = *static_cast<uint32_t *>(event->data);
293                 env->mIncrementCall = client->Increment(
294                     incrementRequest, [](const chre_rpc_NumberMessage &response,
295                                          pw::Status status) {
296                       if (status.ok()) {
297                         EnvSingleton::get()->mNumber = response.number;
298                         TestEventQueueSingleton::get()->pushEvent(
299                             INCREMENT_REQUEST, true);
300                       } else {
301                         TestEventQueueSingleton::get()->pushEvent(
302                             INCREMENT_REQUEST, false);
303                       }
304                     });
305               } else {
306                 TestEventQueueSingleton::get()->pushEvent(INCREMENT_REQUEST,
307                                                           false);
308               }
309             }
310           }
311         }
312       }
313     }
314 
315     void end() {
316       EnvSingleton::get()->closeClient();
317     }
318   };
319 
320   class ServerApp : public TestNanoapp {
321    public:
322     ServerApp() : TestNanoapp(TestNanoappInfo{.id = kPwRcpServerAppId}) {}
323 
324     bool start() override {
325       chre::RpcServer::Service service = {
326           .service = EnvSingleton::get()->mRpcTestService,
327           .id = 0xca8f7150a3f05847,
328           .version = 0x01020034};
329       return EnvSingleton::get()->mServer.registerServices(1, &service);
330     }
331 
332     void handleEvent(uint32_t senderInstanceId, uint16_t eventType,
333                      const void *eventData) override {
334       EnvSingleton::get()->mServer.handleEvent(senderInstanceId, eventType,
335                                                eventData);
336     }
337 
338     void end() {
339       EnvSingleton::get()->closeServer();
340     }
341   };
342 
343   EnvSingleton::init();
344   uint64_t serverId = loadNanoapp(MakeUnique<ServerApp>());
345   uint64_t clientId = loadNanoapp(MakeUnique<ClientApp>());
346   bool status;
347   constexpr uint32_t kNumber = 101;
348 
349   sendEventToNanoapp(clientId, INCREMENT_REQUEST, kNumber);
350   waitForEvent(INCREMENT_REQUEST, &status);
351   EXPECT_TRUE(status);
352   EXPECT_EQ(EnvSingleton::get()->mNumber, kNumber + 1);
353   unloadNanoapp(serverId);
354   unloadNanoapp(clientId);
355   EnvSingleton::deinit();
356 }
357 
TEST_F(RpcTest,PwRpcRpcClientHasServiceCheckForAMatchingService)358 TEST_F(RpcTest, PwRpcRpcClientHasServiceCheckForAMatchingService) {
359   CREATE_CHRE_TEST_EVENT(QUERY_HAS_SERVICE, 0);
360 
361   struct ServiceInfo {
362     uint64_t id;
363     uint32_t version;
364     uint64_t appId;
365   };
366 
367   class App : public TestNanoapp {
368    public:
369     bool start() override {
370       struct chreNanoappRpcService services[] = {{.id = 1, .version = 2}};
371 
372       return chrePublishRpcServices(services, 1 /* numServices */);
373     }
374 
375     void handleEvent(uint32_t, uint16_t eventType, const void *eventData) {
376       switch (eventType) {
377         case CHRE_EVENT_TEST_EVENT: {
378           auto event = static_cast<const TestEvent *>(eventData);
379           switch (event->type) {
380             case QUERY_HAS_SERVICE: {
381               auto service =
382                   static_cast<const struct ServiceInfo *>(event->data);
383               RpcClient client{service->appId};
384               bool hasService =
385                   client.hasService(service->id, service->version);
386               TestEventQueueSingleton::get()->pushEvent(QUERY_HAS_SERVICE,
387                                                         hasService);
388               break;
389             }
390           }
391           break;
392         }
393       }
394     }
395   };
396 
397   uint64_t appId = loadNanoapp(MakeUnique<App>());
398 
399   ServiceInfo service;
400   bool hasService = false;
401 
402   service = {.id = 1, .version = 2, .appId = appId};
403   sendEventToNanoapp(appId, QUERY_HAS_SERVICE, service);
404   waitForEvent(QUERY_HAS_SERVICE, &hasService);
405   EXPECT_TRUE(hasService);
406   service = {.id = 10, .version = 2, .appId = appId};
407   sendEventToNanoapp(appId, QUERY_HAS_SERVICE, service);
408   waitForEvent(QUERY_HAS_SERVICE, &hasService);
409   EXPECT_FALSE(hasService);
410 }
411 
412 }  // namespace
413 
414 }  // namespace chre
415