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 17 #include <gtest/gtest.h> 18 19 #include <stddef.h> 20 #include <stdint.h> 21 #include <string.h> 22 #include <thread> 23 24 #include "app_test_base.h" 25 #include "chpp/app.h" 26 #include "chpp/clients/discovery.h" 27 #include "chpp/clients/loopback.h" 28 #include "chpp/clients/timesync.h" 29 #include "chpp/log.h" 30 #include "chpp/transport.h" 31 32 /* 33 * Test suite for the CHPP Loopback client/service 34 */ 35 namespace chpp { 36 namespace { 37 38 TEST_F(AppTestBase, SimpleStartStop) { 39 // Simple test to make sure start/stop work threads work without crashing 40 ASSERT_TRUE(mClientTransportContext.linkParams.linkEstablished); 41 ASSERT_TRUE(mServiceTransportContext.linkParams.linkEstablished); 42 } 43 44 TEST_F(AppTestBase, TransportLayerLoopback) { 45 // This tests the more limited transport-layer-looopback. In contrast, 46 // the regular application-layer loopback test provides a more thorough test 47 // and test results. 48 constexpr size_t kTestLen = CHPP_TRANSPORT_TX_MTU_BYTES; 49 uint8_t buf[kTestLen]; 50 for (size_t i = 0; i < kTestLen; i++) { 51 buf[i] = (uint8_t)(i + 100); 52 } 53 54 std::this_thread::sleep_for(std::chrono::milliseconds(2000)); 55 CHPP_LOGI("Starting transport-layer loopback test (max buffer = %zu)...", 56 kTestLen); 57 58 EXPECT_EQ(CHPP_APP_ERROR_NONE, 59 chppRunTransportLoopback(mClientAppContext.transportContext, buf, 60 kTestLen)); 61 std::this_thread::sleep_for(std::chrono::milliseconds(300)); 62 EXPECT_EQ(CHPP_APP_ERROR_NONE, 63 mClientAppContext.transportContext->loopbackResult); 64 65 EXPECT_EQ( 66 CHPP_APP_ERROR_NONE, 67 chppRunTransportLoopback(mClientAppContext.transportContext, buf, 100)); 68 std::this_thread::sleep_for(std::chrono::milliseconds(300)); 69 EXPECT_EQ(CHPP_APP_ERROR_NONE, 70 mClientAppContext.transportContext->loopbackResult); 71 72 EXPECT_EQ( 73 CHPP_APP_ERROR_NONE, 74 chppRunTransportLoopback(mClientAppContext.transportContext, buf, 1)); 75 std::this_thread::sleep_for(std::chrono::milliseconds(300)); 76 EXPECT_EQ(CHPP_APP_ERROR_NONE, 77 mClientAppContext.transportContext->loopbackResult); 78 79 EXPECT_EQ( 80 CHPP_APP_ERROR_INVALID_LENGTH, 81 chppRunTransportLoopback(mClientAppContext.transportContext, buf, 0)); 82 std::this_thread::sleep_for(std::chrono::milliseconds(300)); 83 EXPECT_EQ(CHPP_APP_ERROR_INVALID_LENGTH, 84 mClientAppContext.transportContext->loopbackResult); 85 } 86 87 TEST_F(AppTestBase, SimpleLoopback) { 88 constexpr size_t kTestLen = 89 CHPP_TRANSPORT_TX_MTU_BYTES - CHPP_LOOPBACK_HEADER_LEN; 90 uint8_t buf[kTestLen]; 91 for (size_t i = 0; i < kTestLen; i++) { 92 buf[i] = (uint8_t)(i + 100); 93 } 94 95 CHPP_LOGI( 96 "Starting loopback test without fragmentation (max buffer = %zu)...", 97 kTestLen); 98 99 struct ChppLoopbackTestResult result; 100 101 result = chppRunLoopbackTest(&mClientAppContext, buf, kTestLen); 102 EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE); 103 104 result = chppRunLoopbackTest(&mClientAppContext, buf, 10); 105 EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE); 106 107 result = chppRunLoopbackTest(&mClientAppContext, buf, 1); 108 EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE); 109 110 result = chppRunLoopbackTest(&mClientAppContext, buf, 0); 111 EXPECT_EQ(result.error, CHPP_APP_ERROR_INVALID_LENGTH); 112 } 113 114 TEST_F(AppTestBase, FragmentedLoopback) { 115 constexpr size_t kTestLen = UINT16_MAX; 116 uint8_t buf[kTestLen]; 117 for (size_t i = 0; i < kTestLen; i++) { 118 buf[i] = (uint8_t)( 119 (i % 251) + 64); // Arbitrary data. A modulus of 251, a prime number, 120 // reduces the chance of alignment with the MTU. 121 } 122 123 CHPP_LOGI("Starting loopback test with fragmentation (max buffer = %zu)...", 124 kTestLen); 125 126 struct ChppLoopbackTestResult result; 127 128 result = chppRunLoopbackTest(&mClientAppContext, buf, kTestLen); 129 EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE); 130 131 result = chppRunLoopbackTest(&mClientAppContext, buf, 50000); 132 EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE); 133 134 result = chppRunLoopbackTest( 135 &mClientAppContext, buf, 136 CHPP_TRANSPORT_TX_MTU_BYTES - CHPP_LOOPBACK_HEADER_LEN + 1); 137 EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE); 138 } 139 140 TEST_F(AppTestBase, Timesync) { 141 constexpr uint64_t kMaxRtt = 2 * CHPP_NSEC_PER_MSEC; // in ms 142 constexpr int64_t kMaxOffset = 1 * CHPP_NSEC_PER_MSEC; // in ms 143 144 CHPP_LOGI("Starting timesync test..."); 145 146 std::this_thread::sleep_for(std::chrono::milliseconds(100)); 147 EXPECT_TRUE(chppTimesyncMeasureOffset(&mClientAppContext)); 148 std::this_thread::sleep_for(std::chrono::milliseconds(100)); 149 150 EXPECT_EQ(chppTimesyncGetResult(&mClientAppContext)->error, 151 CHPP_APP_ERROR_NONE); 152 153 EXPECT_LT(chppTimesyncGetResult(&mClientAppContext)->rttNs, kMaxRtt); 154 EXPECT_NE(chppTimesyncGetResult(&mClientAppContext)->rttNs, 0); 155 156 EXPECT_LT(chppTimesyncGetResult(&mClientAppContext)->offsetNs, kMaxOffset); 157 EXPECT_GT(chppTimesyncGetResult(&mClientAppContext)->offsetNs, -kMaxOffset); 158 EXPECT_NE(chppTimesyncGetResult(&mClientAppContext)->offsetNs, 0); 159 } 160 161 TEST_F(AppTestBase, DiscoveryMatched) { 162 constexpr uint64_t kTimeoutMs = 5000; 163 EXPECT_TRUE(chppWaitForDiscoveryComplete(&mClientAppContext, kTimeoutMs)); 164 EXPECT_TRUE(chppAreAllClientsMatched(&mClientAppContext)); 165 } 166 167 } // namespace 168 } // namespace chpp 169