Adds a CHPP loopback test
Bug: 165268537
Test: chre_chpp_linux_tests
Change-Id: I89a97ab1802ef55c5e5a283e18adee405a9addfc
diff --git a/chpp/Android.bp b/chpp/Android.bp
index d1cafc6..3727757 100644
--- a/chpp/Android.bp
+++ b/chpp/Android.bp
@@ -28,6 +28,8 @@
"-DCHPP_SERVICE_ENABLED_WWAN",
// clock_gettime() requires _POSIX_C_SOURCE >= 199309L
"-D_POSIX_C_SOURCE=199309L",
+ // Required for pthread_setname_np()
+ "-D_GNU_SOURCE"
],
conlyflags: ["-std=c11"],
srcs: [
@@ -74,7 +76,10 @@
cc_test_host {
name: "chre_chpp_linux_tests",
- srcs: ["test/transport_test.cpp"],
+ srcs: [
+ "test/loopback_test.cpp",
+ "test/transport_test.cpp",
+ ],
static_libs: ["chre_chpp_linux"],
}
diff --git a/chpp/platform/linux/include/chpp/platform/log.h b/chpp/platform/linux/include/chpp/platform/log.h
index 4913975..fbb7101 100644
--- a/chpp/platform/linux/include/chpp/platform/log.h
+++ b/chpp/platform/linux/include/chpp/platform/log.h
@@ -17,6 +17,7 @@
#ifndef CHPP_LOG_H_
#define CHPP_LOG_H_
+#include <pthread.h>
#include <stdio.h>
#ifdef __cplusplus
@@ -29,9 +30,13 @@
// TODO: Should use PRIu8 etc. from inttypes.h instead of %d, etc. (add -Wall
// and -Werror to cflags to catch these)
-#define CHPP_LINUX_LOG(level, color, fmt, ...) \
- printf("\e[" color "m%s %s:%d\t" fmt "\e[0m\n", level, __FILENAME__, \
- __LINE__, ##__VA_ARGS__)
+#define CHPP_LINUX_LOG(level, color, fmt, ...) \
+ { \
+ char name[16]; \
+ pthread_getname_np(pthread_self(), name, 16); \
+ printf("\e[" color "m%s %s:%d\t (%s) " fmt "\e[0m\n", level, __FILENAME__, \
+ __LINE__, name, ##__VA_ARGS__); \
+ }
#define CHPP_LOGE(fmt, ...) CHPP_LINUX_LOG("E", "91", fmt, ##__VA_ARGS__)
#define CHPP_LOGW(fmt, ...) CHPP_LINUX_LOG("W", "93", fmt, ##__VA_ARGS__)
diff --git a/chpp/platform/linux/include/chpp/platform/platform_link.h b/chpp/platform/linux/include/chpp/platform/platform_link.h
index f3343ff..2259008 100644
--- a/chpp/platform/linux/include/chpp/platform/platform_link.h
+++ b/chpp/platform/linux/include/chpp/platform/platform_link.h
@@ -57,6 +57,12 @@
//! The temporary buffer to use to send data to the remote endpoint.
uint8_t buf[CHPP_PLATFORM_LINK_TX_MTU_BYTES];
size_t bufLen;
+
+ //! The string name of the linkSendThread.
+ const char *linkThreadName;
+
+ //! The string name of the CHPP work thread.
+ const char *workThreadName;
};
#ifdef __cplusplus
diff --git a/chpp/platform/linux/link.c b/chpp/platform/linux/link.c
index b101d61..03766b8 100644
--- a/chpp/platform/linux/link.c
+++ b/chpp/platform/linux/link.c
@@ -65,6 +65,9 @@
chppNotifierInit(¶ms->notifier);
pthread_create(¶ms->linkSendThread, NULL /* attr */, linkSendThread,
params);
+ if (params->linkThreadName != NULL) {
+ pthread_setname_np(params->linkSendThread, params->linkThreadName);
+ }
}
void chppPlatformLinkDeinit(struct ChppPlatformLinkParameters *params) {
diff --git a/chpp/test/loopback_test.cpp b/chpp/test/loopback_test.cpp
new file mode 100644
index 0000000..ff1d3d7
--- /dev/null
+++ b/chpp/test/loopback_test.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <thread>
+
+#include "chpp/app.h"
+#include "chpp/clients/loopback.h"
+#include "chpp/macros.h"
+#include "chpp/platform/log.h"
+#include "chpp/transport.h"
+
+namespace {
+
+void *workThread(void *arg) {
+ ChppTransportState *context = static_cast<ChppTransportState *>(arg);
+ pthread_setname_np(pthread_self(), context->linkParams.workThreadName);
+
+ chppWorkThreadStart(context);
+
+ return nullptr;
+}
+
+/*
+ * Test suite for the CHPP Loopback client/service
+ */
+class LoopbackTests : public testing::Test {
+ protected:
+ void SetUp() override {
+ memset(&mClientTransportContext.linkParams, 0,
+ sizeof(mClientTransportContext.linkParams));
+ memset(&mServiceTransportContext.linkParams, 0,
+ sizeof(mServiceTransportContext.linkParams));
+ // The linkSendThread in the link layer is a link "to" the remote end.
+ mServiceTransportContext.linkParams.linkThreadName = "Link to client";
+ mServiceTransportContext.linkParams.workThreadName = "Service work";
+ mClientTransportContext.linkParams.linkThreadName = "Link to service";
+ mClientTransportContext.linkParams.workThreadName = "Client work";
+
+ chppTransportInit(&mClientTransportContext, &mClientAppContext);
+ chppAppInit(&mClientAppContext, &mClientTransportContext);
+
+ chppTransportInit(&mServiceTransportContext, &mServiceAppContext);
+ chppAppInit(&mServiceAppContext, &mServiceTransportContext);
+
+ mClientTransportContext.linkParams.remoteTransportContext =
+ &mServiceTransportContext;
+ mServiceTransportContext.linkParams.remoteTransportContext =
+ &mClientTransportContext;
+
+ pthread_create(&mClientWorkThread, NULL, workThread,
+ &mClientTransportContext);
+
+ // Wait a bit to emulate the scenario where the remote is not yet up
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ pthread_create(&mServiceWorkThread, NULL, workThread,
+ &mServiceTransportContext);
+ mClientTransportContext.linkParams.linkEstablished = true;
+ mServiceTransportContext.linkParams.linkEstablished = true;
+ }
+
+ void TearDown() override {
+ chppWorkThreadStop(&mClientTransportContext);
+ pthread_join(mClientWorkThread, NULL);
+
+ chppAppDeinit(&mClientAppContext);
+ chppTransportDeinit(&mClientTransportContext);
+
+ chppWorkThreadStop(&mServiceTransportContext);
+ pthread_join(mServiceWorkThread, NULL);
+
+ chppAppDeinit(&mServiceAppContext);
+ chppTransportDeinit(&mServiceTransportContext);
+ }
+
+ ChppTransportState mClientTransportContext = {};
+ ChppAppState mClientAppContext = {};
+
+ ChppTransportState mServiceTransportContext = {};
+ ChppAppState mServiceAppContext = {};
+
+ pthread_t mClientWorkThread;
+ pthread_t mServiceWorkThread;
+};
+
+TEST_F(LoopbackTests, SimpleStartStop) {
+ // Simple test to make sure start/stop work threads work,
+ // without crashes.
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+}
+
+TEST_F(LoopbackTests, SimpleLoopback) {
+ // Wait for the reset to finish.
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+
+ chppLoopbackClientInit(&mClientAppContext);
+
+ CHPP_LOGI("Starting loopback test ...");
+ uint8_t buf[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ struct ChppLoopbackTestResult result =
+ chppRunLoopbackTest(&mClientAppContext, buf, 10);
+ ASSERT_EQ(result.error, CHPP_APP_ERROR_NONE);
+
+ chppLoopbackClientDeinit();
+}
+
+} // namespace