1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker *
4*84e33947SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker *
8*84e33947SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker *
10*84e33947SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker */
16*84e33947SAndroid Build Coastguard Worker
17*84e33947SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*84e33947SAndroid Build Coastguard Worker
19*84e33947SAndroid Build Coastguard Worker #include <stddef.h>
20*84e33947SAndroid Build Coastguard Worker #include <stdint.h>
21*84e33947SAndroid Build Coastguard Worker #include <thread>
22*84e33947SAndroid Build Coastguard Worker
23*84e33947SAndroid Build Coastguard Worker #include "app_test_base.h"
24*84e33947SAndroid Build Coastguard Worker #include "chpp/app.h"
25*84e33947SAndroid Build Coastguard Worker #include "chpp/clients/discovery.h"
26*84e33947SAndroid Build Coastguard Worker #include "chpp/clients/loopback.h"
27*84e33947SAndroid Build Coastguard Worker #include "chpp/clients/timesync.h"
28*84e33947SAndroid Build Coastguard Worker #include "chpp/log.h"
29*84e33947SAndroid Build Coastguard Worker #include "chpp/platform/platform_link.h"
30*84e33947SAndroid Build Coastguard Worker #include "chpp/transport.h"
31*84e33947SAndroid Build Coastguard Worker
32*84e33947SAndroid Build Coastguard Worker /*
33*84e33947SAndroid Build Coastguard Worker * Test suite for the CHPP Loopback client/service
34*84e33947SAndroid Build Coastguard Worker */
35*84e33947SAndroid Build Coastguard Worker namespace chpp {
36*84e33947SAndroid Build Coastguard Worker namespace {
37*84e33947SAndroid Build Coastguard Worker
38*84e33947SAndroid Build Coastguard Worker class ChppAppTest : public AppTestBase {};
39*84e33947SAndroid Build Coastguard Worker
TEST_F(ChppAppTest,SimpleStartStop)40*84e33947SAndroid Build Coastguard Worker TEST_F(ChppAppTest, SimpleStartStop) {
41*84e33947SAndroid Build Coastguard Worker // Simple test to make sure start/stop work threads work without crashing
42*84e33947SAndroid Build Coastguard Worker ASSERT_TRUE(mClientLinkContext.linkEstablished);
43*84e33947SAndroid Build Coastguard Worker ASSERT_TRUE(mServiceLinkContext.linkEstablished);
44*84e33947SAndroid Build Coastguard Worker }
45*84e33947SAndroid Build Coastguard Worker
TEST_F(ChppAppTest,TransportLayerLoopback)46*84e33947SAndroid Build Coastguard Worker TEST_F(ChppAppTest, TransportLayerLoopback) {
47*84e33947SAndroid Build Coastguard Worker // This tests the more limited transport-layer-looopback. In contrast,
48*84e33947SAndroid Build Coastguard Worker // the regular application-layer loopback test provides a more thorough test
49*84e33947SAndroid Build Coastguard Worker // and test results.
50*84e33947SAndroid Build Coastguard Worker constexpr size_t kTestLen =
51*84e33947SAndroid Build Coastguard Worker CHPP_LINUX_LINK_TX_MTU_BYTES - CHPP_TRANSPORT_ENCODING_OVERHEAD_BYTES;
52*84e33947SAndroid Build Coastguard Worker uint8_t buf[kTestLen];
53*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < kTestLen; i++) {
54*84e33947SAndroid Build Coastguard Worker buf[i] = (uint8_t)(i + 100);
55*84e33947SAndroid Build Coastguard Worker }
56*84e33947SAndroid Build Coastguard Worker
57*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(2000));
58*84e33947SAndroid Build Coastguard Worker CHPP_LOGI("Starting transport-layer loopback test (max buffer = %zu)...",
59*84e33947SAndroid Build Coastguard Worker kTestLen);
60*84e33947SAndroid Build Coastguard Worker
61*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(CHPP_APP_ERROR_NONE,
62*84e33947SAndroid Build Coastguard Worker chppRunTransportLoopback(mClientAppContext.transportContext, buf,
63*84e33947SAndroid Build Coastguard Worker kTestLen));
64*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(300));
65*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(CHPP_APP_ERROR_NONE,
66*84e33947SAndroid Build Coastguard Worker mClientAppContext.transportContext->loopbackResult);
67*84e33947SAndroid Build Coastguard Worker
68*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(
69*84e33947SAndroid Build Coastguard Worker CHPP_APP_ERROR_NONE,
70*84e33947SAndroid Build Coastguard Worker chppRunTransportLoopback(mClientAppContext.transportContext, buf, 100));
71*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(300));
72*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(CHPP_APP_ERROR_NONE,
73*84e33947SAndroid Build Coastguard Worker mClientAppContext.transportContext->loopbackResult);
74*84e33947SAndroid Build Coastguard Worker
75*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(
76*84e33947SAndroid Build Coastguard Worker CHPP_APP_ERROR_NONE,
77*84e33947SAndroid Build Coastguard Worker chppRunTransportLoopback(mClientAppContext.transportContext, buf, 1));
78*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(300));
79*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(CHPP_APP_ERROR_NONE,
80*84e33947SAndroid Build Coastguard Worker mClientAppContext.transportContext->loopbackResult);
81*84e33947SAndroid Build Coastguard Worker
82*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(
83*84e33947SAndroid Build Coastguard Worker CHPP_APP_ERROR_INVALID_LENGTH,
84*84e33947SAndroid Build Coastguard Worker chppRunTransportLoopback(mClientAppContext.transportContext, buf, 0));
85*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(300));
86*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(CHPP_APP_ERROR_INVALID_LENGTH,
87*84e33947SAndroid Build Coastguard Worker mClientAppContext.transportContext->loopbackResult);
88*84e33947SAndroid Build Coastguard Worker }
89*84e33947SAndroid Build Coastguard Worker
TEST_F(ChppAppTest,SimpleLoopback)90*84e33947SAndroid Build Coastguard Worker TEST_F(ChppAppTest, SimpleLoopback) {
91*84e33947SAndroid Build Coastguard Worker constexpr size_t kTestLen = CHPP_LINUX_LINK_TX_MTU_BYTES -
92*84e33947SAndroid Build Coastguard Worker CHPP_TRANSPORT_ENCODING_OVERHEAD_BYTES -
93*84e33947SAndroid Build Coastguard Worker CHPP_LOOPBACK_HEADER_LEN;
94*84e33947SAndroid Build Coastguard Worker uint8_t buf[kTestLen];
95*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < kTestLen; i++) {
96*84e33947SAndroid Build Coastguard Worker buf[i] = (uint8_t)(i + 100);
97*84e33947SAndroid Build Coastguard Worker }
98*84e33947SAndroid Build Coastguard Worker
99*84e33947SAndroid Build Coastguard Worker CHPP_LOGI(
100*84e33947SAndroid Build Coastguard Worker "Starting loopback test without fragmentation (max buffer = %zu)...",
101*84e33947SAndroid Build Coastguard Worker kTestLen);
102*84e33947SAndroid Build Coastguard Worker
103*84e33947SAndroid Build Coastguard Worker struct ChppLoopbackTestResult result =
104*84e33947SAndroid Build Coastguard Worker chppRunLoopbackTest(&mClientAppContext, buf, kTestLen);
105*84e33947SAndroid Build Coastguard Worker
106*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE);
107*84e33947SAndroid Build Coastguard Worker
108*84e33947SAndroid Build Coastguard Worker result = chppRunLoopbackTest(&mClientAppContext, buf, 10);
109*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE);
110*84e33947SAndroid Build Coastguard Worker
111*84e33947SAndroid Build Coastguard Worker result = chppRunLoopbackTest(&mClientAppContext, buf, 1);
112*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE);
113*84e33947SAndroid Build Coastguard Worker
114*84e33947SAndroid Build Coastguard Worker result = chppRunLoopbackTest(&mClientAppContext, buf, 0);
115*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_INVALID_LENGTH);
116*84e33947SAndroid Build Coastguard Worker }
117*84e33947SAndroid Build Coastguard Worker
TEST_F(ChppAppTest,FragmentedLoopback)118*84e33947SAndroid Build Coastguard Worker TEST_F(ChppAppTest, FragmentedLoopback) {
119*84e33947SAndroid Build Coastguard Worker constexpr size_t kTestLen = UINT16_MAX;
120*84e33947SAndroid Build Coastguard Worker uint8_t buf[kTestLen];
121*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < kTestLen; i++) {
122*84e33947SAndroid Build Coastguard Worker // Arbitrary data. A modulus of 251, a prime number, reduces the chance of
123*84e33947SAndroid Build Coastguard Worker // alignment with the MTU.
124*84e33947SAndroid Build Coastguard Worker buf[i] = (uint8_t)((i % 251) + 64);
125*84e33947SAndroid Build Coastguard Worker }
126*84e33947SAndroid Build Coastguard Worker
127*84e33947SAndroid Build Coastguard Worker CHPP_LOGI("Starting loopback test with fragmentation (max buffer = %zu)...",
128*84e33947SAndroid Build Coastguard Worker kTestLen);
129*84e33947SAndroid Build Coastguard Worker
130*84e33947SAndroid Build Coastguard Worker struct ChppLoopbackTestResult result =
131*84e33947SAndroid Build Coastguard Worker chppRunLoopbackTest(&mClientAppContext, buf, kTestLen);
132*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE);
133*84e33947SAndroid Build Coastguard Worker
134*84e33947SAndroid Build Coastguard Worker result = chppRunLoopbackTest(&mClientAppContext, buf, 50000);
135*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE);
136*84e33947SAndroid Build Coastguard Worker
137*84e33947SAndroid Build Coastguard Worker result = chppRunLoopbackTest(
138*84e33947SAndroid Build Coastguard Worker &mClientAppContext, buf,
139*84e33947SAndroid Build Coastguard Worker chppTransportTxMtuSize(mClientAppContext.transportContext) -
140*84e33947SAndroid Build Coastguard Worker CHPP_LOOPBACK_HEADER_LEN + 1);
141*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(result.error, CHPP_APP_ERROR_NONE);
142*84e33947SAndroid Build Coastguard Worker }
143*84e33947SAndroid Build Coastguard Worker
TEST_F(ChppAppTest,Timesync)144*84e33947SAndroid Build Coastguard Worker TEST_F(ChppAppTest, Timesync) {
145*84e33947SAndroid Build Coastguard Worker // Upper bound for the RTT (response received - request sent).
146*84e33947SAndroid Build Coastguard Worker constexpr uint64_t kMaxRttNs = 20 * CHPP_NSEC_PER_MSEC;
147*84e33947SAndroid Build Coastguard Worker // The offset is defined as (Time when the service sent the response) - (Time
148*84e33947SAndroid Build Coastguard Worker // when the client got the response).
149*84e33947SAndroid Build Coastguard Worker // We use half the RTT as the upper bound.
150*84e33947SAndroid Build Coastguard Worker constexpr int64_t kMaxOffsetNs = kMaxRttNs / 2;
151*84e33947SAndroid Build Coastguard Worker
152*84e33947SAndroid Build Coastguard Worker CHPP_LOGI("Starting timesync test...");
153*84e33947SAndroid Build Coastguard Worker
154*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(100));
155*84e33947SAndroid Build Coastguard Worker EXPECT_TRUE(chppTimesyncMeasureOffset(&mClientAppContext));
156*84e33947SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::milliseconds(100));
157*84e33947SAndroid Build Coastguard Worker
158*84e33947SAndroid Build Coastguard Worker EXPECT_EQ(chppTimesyncGetResult(&mClientAppContext)->error,
159*84e33947SAndroid Build Coastguard Worker CHPP_APP_ERROR_NONE);
160*84e33947SAndroid Build Coastguard Worker
161*84e33947SAndroid Build Coastguard Worker EXPECT_LT(chppTimesyncGetResult(&mClientAppContext)->rttNs, kMaxRttNs);
162*84e33947SAndroid Build Coastguard Worker EXPECT_NE(chppTimesyncGetResult(&mClientAppContext)->rttNs, 0);
163*84e33947SAndroid Build Coastguard Worker
164*84e33947SAndroid Build Coastguard Worker EXPECT_LT(chppTimesyncGetResult(&mClientAppContext)->offsetNs, kMaxOffsetNs);
165*84e33947SAndroid Build Coastguard Worker EXPECT_GT(chppTimesyncGetResult(&mClientAppContext)->offsetNs, -kMaxOffsetNs);
166*84e33947SAndroid Build Coastguard Worker EXPECT_NE(chppTimesyncGetResult(&mClientAppContext)->offsetNs, 0);
167*84e33947SAndroid Build Coastguard Worker }
168*84e33947SAndroid Build Coastguard Worker
TEST_F(ChppAppTest,DiscoveryMatched)169*84e33947SAndroid Build Coastguard Worker TEST_F(ChppAppTest, DiscoveryMatched) {
170*84e33947SAndroid Build Coastguard Worker constexpr uint64_t kTimeoutMs = 5000;
171*84e33947SAndroid Build Coastguard Worker EXPECT_TRUE(chppWaitForDiscoveryComplete(&mClientAppContext, kTimeoutMs));
172*84e33947SAndroid Build Coastguard Worker EXPECT_TRUE(chppAreAllClientsMatched(&mClientAppContext));
173*84e33947SAndroid Build Coastguard Worker }
174*84e33947SAndroid Build Coastguard Worker
175*84e33947SAndroid Build Coastguard Worker } // namespace
176*84e33947SAndroid Build Coastguard Worker } // namespace chpp
177