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