1 /* 2 * Copyright (C) 2021 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 "clients_test.h" 18 19 #include <gtest/gtest.h> 20 21 #include <string.h> 22 #include <thread> 23 24 #include "chpp/app.h" 25 #include "chpp/clients.h" 26 #include "chpp/macros.h" 27 #include "chpp/memory.h" 28 #include "chpp/platform/utils.h" 29 #include "chpp/services.h" 30 #include "chpp/time.h" 31 #include "chpp/transport.h" 32 #include "chre/pal/wwan.h" 33 34 class ClientsTest : public testing::Test { 35 protected: 36 void SetUp() override { 37 chppClearTotalAllocBytes(); 38 memset(&mTransportContext.linkParams, 0, 39 sizeof(mTransportContext.linkParams)); 40 mTransportContext.linkParams.linkEstablished = true; 41 chppTransportInit(&mTransportContext, &mAppContext); 42 chppAppInit(&mAppContext, &mTransportContext); 43 mClientState = 44 (struct ChppClientState *)mAppContext.registeredClientContexts[0]; 45 chppClientInit(mClientState, CHPP_HANDLE_NEGOTIATED_RANGE_START); 46 47 mTransportContext.resetState = CHPP_RESET_STATE_NONE; 48 } 49 50 void TearDown() override { 51 chppAppDeinit(&mAppContext); 52 chppTransportDeinit(&mTransportContext); 53 54 EXPECT_EQ(chppGetTotalAllocBytes(), 0); 55 } 56 57 struct ChppTransportState mTransportContext; 58 struct ChppAppState mAppContext; 59 struct ChppClient mClient; 60 struct ChppClientState *mClientState; 61 struct ChppRequestResponseState mRRState; 62 }; 63 64 void getClientRRStateInputCheck(struct ChppClientState *clientState, 65 struct ChppAppHeader *header) { 66 ASSERT_TRUE(clientState != NULL); 67 uint8_t clientIdx = clientState->index; 68 69 ASSERT_TRUE(clientState->appContext != NULL); 70 ASSERT_TRUE(clientState->appContext->registeredClients != NULL); 71 ASSERT_TRUE(clientState->appContext->registeredClients[clientIdx] != NULL); 72 ASSERT_TRUE( 73 clientState->appContext->registeredClientStates[clientIdx]->rRStates != 74 NULL); 75 ASSERT_LT( 76 header->command, 77 clientState->appContext->registeredClients[clientIdx]->rRStateCount); 78 } 79 80 struct ChppRequestResponseState *getClientRRState( 81 struct ChppClientState *clientState, struct ChppAppHeader *header) { 82 getClientRRStateInputCheck(clientState, header); 83 84 uint8_t clientIdx = clientState->index; 85 return &(clientState->appContext->registeredClientStates[clientIdx] 86 ->rRStates[header->command]); 87 } 88 89 void isTimeoutAsExpected(uint64_t timeoutTimeNs, uint64_t expectedTimeNs) { 90 uint64_t kJitterNs = 10 * CHPP_NSEC_PER_MSEC; 91 92 if (expectedTimeNs == CHPP_TIME_MAX) { 93 EXPECT_EQ(timeoutTimeNs, expectedTimeNs); 94 } else { 95 EXPECT_GE(timeoutTimeNs, expectedTimeNs); 96 EXPECT_LE(timeoutTimeNs, expectedTimeNs + kJitterNs); 97 } 98 } 99 100 void registerAndValidateRequestForTimeout(struct ChppClientState *clientState, 101 struct ChppAppHeader *header, 102 uint64_t timeoutNs, 103 uint64_t expectedTimeNs) { 104 struct ChppRequestResponseState *rRState = 105 getClientRRState(clientState, header); 106 chppClientTimestampRequest(clientState, rRState, header, timeoutNs); 107 108 isTimeoutAsExpected(clientState->appContext->nextRequestTimeoutNs, 109 expectedTimeNs); 110 } 111 112 void registerAndValidateResponseForTimeout(struct ChppClientState *clientState, 113 const struct ChppAppHeader *header, 114 uint64_t expectedTimeNs) { 115 ASSERT_FALSE(clientState == NULL); 116 uint8_t clientIdx = clientState->index; 117 118 ASSERT_FALSE(clientState->appContext == NULL); 119 ASSERT_FALSE(clientState->appContext->registeredClients == NULL); 120 ASSERT_FALSE(clientState->appContext->registeredClients[clientIdx] == NULL); 121 ASSERT_FALSE( 122 clientState->appContext->registeredClientStates[clientIdx]->rRStates == 123 NULL); 124 ASSERT_LT( 125 header->command, 126 clientState->appContext->registeredClients[clientIdx]->rRStateCount); 127 128 struct ChppRequestResponseState *rRState = 129 &(clientState->appContext->registeredClientStates[clientIdx] 130 ->rRStates[header->command]); 131 chppClientTimestampResponse(clientState, rRState, header); 132 133 isTimeoutAsExpected(clientState->appContext->nextRequestTimeoutNs, 134 expectedTimeNs); 135 } 136 137 void validateTimeoutResponse(const struct ChppAppHeader *request, 138 const struct ChppAppHeader *response) { 139 ASSERT_TRUE(request != NULL); 140 ASSERT_TRUE(response != NULL); 141 142 EXPECT_EQ(response->handle, request->handle); 143 EXPECT_EQ(response->type, CHPP_MESSAGE_TYPE_SERVICE_RESPONSE); 144 EXPECT_EQ(response->transaction, request->transaction); 145 EXPECT_EQ(response->error, CHPP_APP_ERROR_TIMEOUT); 146 EXPECT_EQ(response->command, request->command); 147 } 148 149 TEST_F(ClientsTest, RequestResponseTimestampValid) { 150 struct ChppAppHeader *reqHeader = 151 chppAllocClientRequestCommand(mClientState, 0 /* command */); 152 chppClientTimestampRequest(mClientState, &mRRState, reqHeader, 153 CHPP_CLIENT_REQUEST_TIMEOUT_INFINITE); 154 155 struct ChppAppHeader *respHeader = 156 chppAllocServiceResponse(reqHeader, sizeof(*reqHeader)); 157 ASSERT_TRUE(chppClientTimestampResponse(mClientState, &mRRState, respHeader)); 158 159 chppFree(reqHeader); 160 chppFree(respHeader); 161 } 162 163 TEST_F(ClientsTest, RequestResponseTimestampDuplicate) { 164 struct ChppAppHeader *reqHeader = 165 chppAllocClientRequestCommand(mClientState, 0 /* command */); 166 chppClientTimestampRequest(mClientState, &mRRState, reqHeader, 167 CHPP_CLIENT_REQUEST_TIMEOUT_INFINITE); 168 169 struct ChppAppHeader *respHeader = 170 chppAllocServiceResponse(reqHeader, sizeof(*reqHeader)); 171 ASSERT_TRUE(chppClientTimestampResponse(mClientState, &mRRState, respHeader)); 172 ASSERT_FALSE( 173 chppClientTimestampResponse(mClientState, &mRRState, respHeader)); 174 175 chppFree(reqHeader); 176 chppFree(respHeader); 177 } 178 179 TEST_F(ClientsTest, RequestResponseTimestampInvalidId) { 180 struct ChppAppHeader *reqHeader = 181 chppAllocClientRequestCommand(mClientState, 0 /* command */); 182 chppClientTimestampRequest(mClientState, &mRRState, reqHeader, 183 CHPP_CLIENT_REQUEST_TIMEOUT_INFINITE); 184 185 struct ChppAppHeader *newReqHeader = 186 chppAllocClientRequestCommand(mClientState, 0 /* command */); 187 struct ChppAppHeader *respHeader = 188 chppAllocServiceResponse(newReqHeader, sizeof(*reqHeader)); 189 ASSERT_FALSE( 190 chppClientTimestampResponse(mClientState, &mRRState, respHeader)); 191 192 chppFree(reqHeader); 193 chppFree(newReqHeader); 194 chppFree(respHeader); 195 } 196 197 TEST_F(ClientsTest, RequestTimeoutAddRemoveSingle) { 198 EXPECT_EQ(mAppContext.nextRequestTimeoutNs, CHPP_TIME_MAX); 199 200 struct ChppAppHeader *reqHeader = 201 chppAllocClientRequestCommand(mClientState, 1 /* command */); 202 203 uint64_t time = chppGetCurrentTimeNs(); 204 uint64_t timeout = 1000 * CHPP_NSEC_PER_MSEC; 205 registerAndValidateRequestForTimeout(mClientState, reqHeader, timeout, 206 time + timeout); 207 208 EXPECT_TRUE( 209 chppTransportGetClientRequestTimeoutResponse(&mTransportContext) == NULL); 210 211 registerAndValidateResponseForTimeout(mClientState, reqHeader, CHPP_TIME_MAX); 212 213 chppFree(reqHeader); 214 } 215 216 TEST_F(ClientsTest, RequestTimeoutAddRemoveMultiple) { 217 struct ChppAppHeader *reqHeader1 = 218 chppAllocClientRequestCommand(mClientState, 0 /* command */); 219 struct ChppAppHeader *reqHeader2 = 220 chppAllocClientRequestCommand(mClientState, 1 /* command */); 221 struct ChppAppHeader *reqHeader3 = 222 chppAllocClientRequestCommand(mClientState, 2 /* command */); 223 224 EXPECT_EQ(mAppContext.nextRequestTimeoutNs, CHPP_TIME_MAX); 225 226 uint64_t time1 = chppGetCurrentTimeNs(); 227 uint64_t timeout1 = 2000 * CHPP_NSEC_PER_MSEC; 228 registerAndValidateRequestForTimeout(mClientState, reqHeader1, timeout1, 229 time1 + timeout1); 230 231 uint64_t time2 = chppGetCurrentTimeNs(); 232 uint64_t timeout2 = 4000 * CHPP_NSEC_PER_MSEC; 233 registerAndValidateRequestForTimeout(mClientState, reqHeader2, timeout2, 234 time1 + timeout1); 235 236 uint64_t time3 = chppGetCurrentTimeNs(); 237 uint64_t timeout3 = 3000 * CHPP_NSEC_PER_MSEC; 238 registerAndValidateRequestForTimeout(mClientState, reqHeader3, timeout3, 239 time1 + timeout1); 240 241 registerAndValidateResponseForTimeout(mClientState, reqHeader1, 242 time3 + timeout3); 243 244 EXPECT_TRUE( 245 chppTransportGetClientRequestTimeoutResponse(&mTransportContext) == NULL); 246 247 uint64_t time4 = chppGetCurrentTimeNs(); 248 uint64_t timeout4 = 1000 * CHPP_NSEC_PER_MSEC; 249 registerAndValidateRequestForTimeout(mClientState, reqHeader1, timeout4, 250 time4 + timeout4); 251 252 registerAndValidateResponseForTimeout(mClientState, reqHeader1, 253 time3 + timeout3); 254 255 registerAndValidateResponseForTimeout(mClientState, reqHeader3, 256 time2 + timeout2); 257 258 registerAndValidateResponseForTimeout(mClientState, reqHeader2, 259 CHPP_TIME_MAX); 260 261 EXPECT_TRUE( 262 chppTransportGetClientRequestTimeoutResponse(&mTransportContext) == NULL); 263 264 chppFree(reqHeader1); 265 chppFree(reqHeader2); 266 chppFree(reqHeader3); 267 } 268 269 TEST_F(ClientsTest, DuplicateRequestTimeoutResponse) { 270 EXPECT_EQ(mAppContext.nextRequestTimeoutNs, CHPP_TIME_MAX); 271 272 struct ChppAppHeader *reqHeader = 273 chppAllocClientRequestCommand(mClientState, 1 /* command */); 274 275 uint64_t time1 = chppGetCurrentTimeNs(); 276 uint64_t timeout1 = 200 * CHPP_NSEC_PER_MSEC; 277 registerAndValidateRequestForTimeout(mClientState, reqHeader, timeout1, 278 time1 + timeout1); 279 280 std::this_thread::sleep_for(std::chrono::nanoseconds(timeout1 / 2)); 281 282 uint64_t time2 = chppGetCurrentTimeNs(); 283 uint64_t timeout2 = 200 * CHPP_NSEC_PER_MSEC; 284 registerAndValidateRequestForTimeout(mClientState, reqHeader, timeout2, 285 time2 + timeout2); 286 287 std::this_thread::sleep_for( 288 std::chrono::nanoseconds(timeout1 + time1 - chppGetCurrentTimeNs())); 289 // First request would have timed out but superseded by second request 290 ASSERT_GT(mAppContext.nextRequestTimeoutNs, chppGetCurrentTimeNs()); 291 292 std::this_thread::sleep_for( 293 std::chrono::nanoseconds(timeout2 + time2 - chppGetCurrentTimeNs())); 294 // Second request should have timed out 295 ASSERT_LT(mAppContext.nextRequestTimeoutNs, chppGetCurrentTimeNs()); 296 297 struct ChppAppHeader *response = 298 chppTransportGetClientRequestTimeoutResponse(&mTransportContext); 299 validateTimeoutResponse(reqHeader, response); 300 if (response != NULL) { 301 chppFree(response); 302 } 303 304 registerAndValidateResponseForTimeout(mClientState, reqHeader, CHPP_TIME_MAX); 305 EXPECT_TRUE( 306 chppTransportGetClientRequestTimeoutResponse(&mTransportContext) == NULL); 307 308 chppFree(reqHeader); 309 } 310 311 TEST_F(ClientsTest, RequestTimeoutResponse) { 312 EXPECT_EQ(mAppContext.nextRequestTimeoutNs, CHPP_TIME_MAX); 313 314 struct ChppAppHeader *reqHeader1 = 315 chppAllocClientRequestCommand(mClientState, 1 /* command */); 316 struct ChppAppHeader *reqHeader2 = 317 chppAllocClientRequestCommand(mClientState, 2 /* command */); 318 319 uint64_t time1 = chppGetCurrentTimeNs(); 320 uint64_t timeout1 = 200 * CHPP_NSEC_PER_MSEC; 321 registerAndValidateRequestForTimeout(mClientState, reqHeader1, timeout1, 322 time1 + timeout1); 323 324 std::this_thread::sleep_for(std::chrono::nanoseconds(timeout1)); 325 ASSERT_LT(mAppContext.nextRequestTimeoutNs, chppGetCurrentTimeNs()); 326 327 struct ChppAppHeader *response = 328 chppTransportGetClientRequestTimeoutResponse(&mTransportContext); 329 validateTimeoutResponse(reqHeader1, response); 330 if (response != NULL) { 331 chppFree(response); 332 } 333 334 registerAndValidateResponseForTimeout(mClientState, reqHeader1, 335 CHPP_TIME_MAX); 336 EXPECT_TRUE( 337 chppTransportGetClientRequestTimeoutResponse(&mTransportContext) == NULL); 338 339 uint64_t time2 = chppGetCurrentTimeNs(); 340 uint64_t timeout2 = 200 * CHPP_NSEC_PER_MSEC; 341 registerAndValidateRequestForTimeout(mClientState, reqHeader2, timeout2, 342 time2 + timeout2); 343 344 std::this_thread::sleep_for(std::chrono::nanoseconds(timeout2)); 345 ASSERT_LT(mAppContext.nextRequestTimeoutNs, chppGetCurrentTimeNs()); 346 347 response = chppTransportGetClientRequestTimeoutResponse(&mTransportContext); 348 validateTimeoutResponse(reqHeader2, response); 349 if (response != NULL) { 350 chppFree(response); 351 } 352 353 chppFree(reqHeader1); 354 chppFree(reqHeader2); 355 } 356