xref: /aosp_15_r20/system/chre/chpp/test/app_discovery_test.cpp (revision 84e339476a462649f82315436d70fd732297a399)
1 /*
2  * Copyright (C) 2023 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 <gtest/gtest.h>
18 
19 #include <stdbool.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <cstring>
24 #include <thread>
25 
26 #include "chpp/app.h"
27 #include "chpp/clients.h"
28 #include "chpp/clients/discovery.h"
29 #include "chpp/macros.h"
30 #include "chpp/platform/platform_link.h"
31 #include "chpp/platform/utils.h"
32 #include "chpp/services.h"
33 #include "chpp/transport.h"
34 
35 namespace chre {
36 
37 namespace {
38 
39 constexpr uint64_t kResetWaitTimeMs = 5000;
40 constexpr uint64_t kDiscoveryWaitTimeMs = 5000;
41 
workThread(void * transportState)42 void *workThread(void *transportState) {
43   ChppTransportState *state = static_cast<ChppTransportState *>(transportState);
44 
45   auto linkContext =
46       static_cast<struct ChppLinuxLinkState *>(state->linkContext);
47 
48   pthread_setname_np(pthread_self(), linkContext->workThreadName);
49 
50   chppWorkThreadStart(state);
51 
52   return nullptr;
53 }
54 
55 #define TEST_UUID                                                           \
56   {                                                                         \
57     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
58         0x00, 0x00, 0x00, 0x12                                              \
59   }
60 
61 constexpr uint16_t kNumCommands = 1;
62 
63 struct ClientState {
64   struct ChppEndpointState chppClientState;
65   struct ChppOutgoingRequestState outReqStates[kNumCommands];
66   bool resetNotified;
67   bool matchNotified;
68 };
69 
70 void clientNotifyReset(void *clientState);
71 void clientNotifyMatch(void *clientState);
72 bool clientInit(void *clientState, uint8_t handle,
73                 struct ChppVersion serviceVersion);
74 void clientDeinit(void *clientState);
75 
76 constexpr struct ChppClient kClient = {
77     .descriptor.uuid = TEST_UUID,
78     .descriptor.version.major = 1,
79     .descriptor.version.minor = 0,
80     .descriptor.version.patch = 0,
81     .resetNotifierFunctionPtr = &clientNotifyReset,
82     .matchNotifierFunctionPtr = &clientNotifyMatch,
83     .responseDispatchFunctionPtr = nullptr,
84     .notificationDispatchFunctionPtr = nullptr,
85     .initFunctionPtr = &clientInit,
86     .deinitFunctionPtr = &clientDeinit,
87     .outReqCount = kNumCommands,
88     .minLength = sizeof(struct ChppAppHeader),
89 };
90 
clientNotifyReset(void * clientState)91 void clientNotifyReset(void *clientState) {
92   auto state = static_cast<struct ClientState *>(clientState);
93   state->resetNotified = true;
94 }
95 
clientNotifyMatch(void * clientState)96 void clientNotifyMatch(void *clientState) {
97   auto state = static_cast<struct ClientState *>(clientState);
98   state->matchNotified = true;
99 }
100 
clientInit(void * clientState,uint8_t handle,struct ChppVersion serviceVersion)101 bool clientInit(void *clientState, uint8_t handle,
102                 struct ChppVersion serviceVersion) {
103   UNUSED_VAR(serviceVersion);
104   auto state = static_cast<struct ClientState *>(clientState);
105   state->chppClientState.openState = CHPP_OPEN_STATE_OPENED;
106   chppClientInit(&state->chppClientState, handle);
107   return true;
108 }
109 
clientDeinit(void * clientState)110 void clientDeinit(void *clientState) {
111   auto state = static_cast<struct ClientState *>(clientState);
112   chppClientDeinit(&state->chppClientState);
113   state->chppClientState.openState = CHPP_OPEN_STATE_CLOSED;
114 }
115 
116 // Service
117 struct ServiceState {
118   struct ChppEndpointState chppServiceState;
119   struct ChppIncomingRequestState inReqStates[kNumCommands];
120   bool resetNotified;
121 };
122 
serviceNotifyReset(void * serviceState)123 void serviceNotifyReset(void *serviceState) {
124   auto state = static_cast<struct ServiceState *>(serviceState);
125   state->resetNotified = true;
126 }
127 
128 const struct ChppService kService = {
129     .descriptor.uuid = TEST_UUID,
130     .descriptor.name = "Test",
131     .descriptor.version.major = 1,
132     .descriptor.version.minor = 0,
133     .descriptor.version.patch = 0,
134     .resetNotifierFunctionPtr = &serviceNotifyReset,
135     .requestDispatchFunctionPtr = nullptr,
136     .notificationDispatchFunctionPtr = nullptr,
137     .minLength = sizeof(struct ChppAppHeader),
138 };
139 
140 // Test Clients/Services discovery and matching.
141 class AppDiscoveryTest : public testing::Test {
142  protected:
SetUp()143   void SetUp() {
144     chppClearTotalAllocBytes();
145     memset(&mClientLinkContext, 0, sizeof(mClientLinkContext));
146     memset(&mServiceLinkContext, 0, sizeof(mServiceLinkContext));
147 
148     mServiceLinkContext.linkThreadName = "Host Link";
149     mServiceLinkContext.workThreadName = "Host worker";
150     mServiceLinkContext.isLinkActive = true;
151     mServiceLinkContext.remoteLinkState = &mClientLinkContext;
152     mServiceLinkContext.rxInRemoteEndpointWorker = false;
153 
154     mClientLinkContext.linkThreadName = "CHRE Link";
155     mClientLinkContext.workThreadName = "CHRE worker";
156     mClientLinkContext.isLinkActive = true;
157     mClientLinkContext.remoteLinkState = &mServiceLinkContext;
158     mClientLinkContext.rxInRemoteEndpointWorker = false;
159 
160     // No default clients/services.
161     struct ChppClientServiceSet set;
162     memset(&set, 0, sizeof(set));
163 
164     const struct ChppLinkApi *linkApi = getLinuxLinkApi();
165 
166     // Init client side.
167     chppTransportInit(&mClientTransportContext, &mClientAppContext,
168                       &mClientLinkContext, linkApi);
169     chppAppInitWithClientServiceSet(&mClientAppContext,
170                                     &mClientTransportContext, set);
171 
172     // Init service side.
173     chppTransportInit(&mServiceTransportContext, &mServiceAppContext,
174                       &mServiceLinkContext, linkApi);
175     chppAppInitWithClientServiceSet(&mServiceAppContext,
176                                     &mServiceTransportContext, set);
177   }
178 
TearDown()179   void TearDown() {
180     chppWorkThreadStop(&mClientTransportContext);
181     chppWorkThreadStop(&mServiceTransportContext);
182     pthread_join(mClientWorkThread, NULL);
183     pthread_join(mServiceWorkThread, NULL);
184 
185     // Deinit client side.
186     chppAppDeinit(&mClientAppContext);
187     chppTransportDeinit(&mClientTransportContext);
188 
189     // Deinit service side.
190     chppAppDeinit(&mServiceAppContext);
191     chppTransportDeinit(&mServiceTransportContext);
192 
193     EXPECT_EQ(chppGetTotalAllocBytes(), 0);
194   }
195 
196   // Client side.
197   ChppLinuxLinkState mClientLinkContext = {};
198   ChppTransportState mClientTransportContext = {};
199   ChppAppState mClientAppContext = {};
200   pthread_t mClientWorkThread;
201   ClientState mClientState;
202 
203   // Service side
204   ChppLinuxLinkState mServiceLinkContext = {};
205   ChppTransportState mServiceTransportContext = {};
206   ChppAppState mServiceAppContext = {};
207   pthread_t mServiceWorkThread;
208   ServiceState mServiceState;
209 };
210 
TEST_F(AppDiscoveryTest,workWhenThereIsNoService)211 TEST_F(AppDiscoveryTest, workWhenThereIsNoService) {
212   // Register the client
213   memset(&mClientState, 0, sizeof(mClientState));
214   chppRegisterClient(&mClientAppContext, &mClientState,
215                      &mClientState.chppClientState,
216                      &mClientState.outReqStates[0], &kClient);
217 
218   pthread_create(&mClientWorkThread, NULL, workThread,
219                  &mClientTransportContext);
220 
221   std::this_thread::sleep_for(std::chrono::milliseconds(450));
222 
223   // Start the service thread (no service registered).
224   pthread_create(&mServiceWorkThread, NULL, workThread,
225                  &mServiceTransportContext);
226 
227   mClientLinkContext.linkEstablished = true;
228   mServiceLinkContext.linkEstablished = true;
229 
230   EXPECT_TRUE(chppTransportWaitForResetComplete(&mClientTransportContext,
231                                                 kResetWaitTimeMs));
232   EXPECT_TRUE(chppTransportWaitForResetComplete(&mServiceTransportContext,
233                                                 kResetWaitTimeMs));
234 
235   EXPECT_TRUE(
236       chppWaitForDiscoveryComplete(&mClientAppContext, kDiscoveryWaitTimeMs));
237   EXPECT_TRUE(
238       chppWaitForDiscoveryComplete(&mServiceAppContext, kDiscoveryWaitTimeMs));
239 
240   EXPECT_FALSE(mClientState.resetNotified);
241   EXPECT_FALSE(mClientState.matchNotified);
242   EXPECT_EQ(mClientAppContext.discoveredServiceCount, 0);
243   EXPECT_EQ(mClientAppContext.matchedClientCount, 0);
244   EXPECT_EQ(mServiceAppContext.discoveredServiceCount, 0);
245   EXPECT_EQ(mServiceAppContext.matchedClientCount, 0);
246 }
247 
TEST_F(AppDiscoveryTest,servicesShouldBeDiscovered)248 TEST_F(AppDiscoveryTest, servicesShouldBeDiscovered) {
249   // Start the client thread (no client registered).
250   pthread_create(&mClientWorkThread, NULL, workThread,
251                  &mClientTransportContext);
252 
253   std::this_thread::sleep_for(std::chrono::milliseconds(450));
254 
255   // Register the service
256   memset(&mServiceState, 0, sizeof(mServiceState));
257   chppRegisterService(&mServiceAppContext, &mServiceState,
258                       &mServiceState.chppServiceState, NULL /*outReqStates*/,
259                       &kService);
260 
261   pthread_create(&mServiceWorkThread, NULL, workThread,
262                  &mServiceTransportContext);
263 
264   mClientLinkContext.linkEstablished = true;
265   mServiceLinkContext.linkEstablished = true;
266 
267   EXPECT_TRUE(chppTransportWaitForResetComplete(&mClientTransportContext,
268                                                 kResetWaitTimeMs));
269   EXPECT_TRUE(chppTransportWaitForResetComplete(&mServiceTransportContext,
270                                                 kResetWaitTimeMs));
271 
272   EXPECT_TRUE(
273       chppWaitForDiscoveryComplete(&mClientAppContext, kDiscoveryWaitTimeMs));
274   EXPECT_TRUE(
275       chppWaitForDiscoveryComplete(&mServiceAppContext, kDiscoveryWaitTimeMs));
276 
277   EXPECT_FALSE(mClientState.resetNotified);
278   EXPECT_TRUE(mServiceState.resetNotified);
279   EXPECT_FALSE(mClientState.matchNotified);
280   EXPECT_EQ(mClientAppContext.discoveredServiceCount, 1);
281   EXPECT_EQ(mClientAppContext.matchedClientCount, 0);
282   EXPECT_EQ(mServiceAppContext.discoveredServiceCount, 0);
283   EXPECT_EQ(mServiceAppContext.matchedClientCount, 0);
284 }
285 
TEST_F(AppDiscoveryTest,discoveredServiceShouldBeMatchedWithClients)286 TEST_F(AppDiscoveryTest, discoveredServiceShouldBeMatchedWithClients) {
287   // Register the client
288   memset(&mClientState, 0, sizeof(mClientState));
289   chppRegisterClient(&mClientAppContext, &mClientState,
290                      &mClientState.chppClientState,
291                      &mClientState.outReqStates[0], &kClient);
292 
293   pthread_create(&mClientWorkThread, NULL, workThread,
294                  &mClientTransportContext);
295 
296   std::this_thread::sleep_for(std::chrono::milliseconds(450));
297 
298   // Register the service
299   memset(&mServiceState, 0, sizeof(mServiceState));
300   chppRegisterService(&mServiceAppContext, &mServiceState,
301                       &mServiceState.chppServiceState, NULL /*outReqStates*/,
302                       &kService);
303 
304   pthread_create(&mServiceWorkThread, NULL, workThread,
305                  &mServiceTransportContext);
306 
307   mClientLinkContext.linkEstablished = true;
308   mServiceLinkContext.linkEstablished = true;
309 
310   EXPECT_TRUE(chppTransportWaitForResetComplete(&mClientTransportContext,
311                                                 kResetWaitTimeMs));
312   EXPECT_TRUE(chppTransportWaitForResetComplete(&mServiceTransportContext,
313                                                 kResetWaitTimeMs));
314 
315   EXPECT_TRUE(
316       chppWaitForDiscoveryComplete(&mClientAppContext, kDiscoveryWaitTimeMs));
317   EXPECT_TRUE(
318       chppWaitForDiscoveryComplete(&mServiceAppContext, kDiscoveryWaitTimeMs));
319 
320   EXPECT_FALSE(mClientState.resetNotified);
321   EXPECT_TRUE(mServiceState.resetNotified);
322   EXPECT_TRUE(mClientState.matchNotified);
323   EXPECT_EQ(mClientAppContext.discoveredServiceCount, 1);
324   EXPECT_EQ(mClientAppContext.matchedClientCount, 1);
325   EXPECT_TRUE(mClientState.chppClientState.initialized);
326   EXPECT_EQ(mServiceAppContext.discoveredServiceCount, 0);
327   EXPECT_EQ(mServiceAppContext.matchedClientCount, 0);
328 }
329 
330 }  // namespace
331 
332 }  // namespace chre