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 "test_base.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include "chre/core/event_loop_manager.h"
22 #include "chre/core/init.h"
23 #include "chre/platform/linux/platform_log.h"
24 #include "chre/platform/linux/task_util/task_manager.h"
25 #include "chre/util/time.h"
26 #include "chre_api/chre/version.h"
27 #include "inc/test_util.h"
28 #include "test_util.h"
29 
30 namespace chre {
31 
32 /**
33  * This base class initializes and runs the event loop.
34  *
35  * This test framework makes use of the TestEventQueue as a primary method
36  * of a test execution barrier (see its documentation for details). To simplify
37  * the test execution flow, it is encouraged that any communication between
38  * threads (e.g. a nanoapp and the main test thread) through this
39  * TestEventQueue. In this way, we can design simulation tests in a way that
40  * validates an expected sequence of events in a well-defined manner.
41  *
42  * To avoid the test from potentially stalling, we also push a timeout event
43  * to the TestEventQueue once a fixed timeout has elapsed since the start of
44  * this test.
45  */
SetUp()46 void TestBase::SetUp() {
47   // TODO(b/346903946): remove these extra prints once init failure is resolved
48   printf("SetUp(): log\n");
49   chre::PlatformLogSingleton::init();
50   printf("SetUp(): TaskManager\n");
51   TaskManagerSingleton::init();
52   printf("SetUp(): TestEventQueue\n");
53   TestEventQueueSingleton::init();
54   printf("SetUp(): CHRE\n");
55   chre::init();
56   EventLoopManagerSingleton::get()->lateInit();
57 
58   mChreThread = std::thread(
59       []() { EventLoopManagerSingleton::get()->getEventLoop().run(); });
60 
61   auto callback = [](void *) {
62     LOGE("Test timed out ...");
63     TestEventQueueSingleton::get()->pushEvent(
64         CHRE_EVENT_SIMULATION_TEST_TIMEOUT);
65   };
66 
67   ASSERT_TRUE(mSystemTimer.init());
68   ASSERT_TRUE(mSystemTimer.set(callback, nullptr /*data*/,
69                                Nanoseconds(getTimeoutNs())));
70   printf("SetUp() complete\n");
71 }
72 
TearDown()73 void TestBase::TearDown() {
74   mSystemTimer.cancel();
75   // Free memory allocated for event on the test queue.
76   TestEventQueueSingleton::get()->flush();
77   EventLoopManagerSingleton::get()->getEventLoop().stop();
78   mChreThread.join();
79 
80   chre::deinit();
81   TestEventQueueSingleton::deinit();
82   TaskManagerSingleton::deinit();
83   deleteNanoappInfos();
84   unregisterAllTestNanoapps();
85   chre::PlatformLogSingleton::deinit();
86 }
87 
TEST_F(TestBase,CanLoadAndStartSingleNanoapp)88 TEST_F(TestBase, CanLoadAndStartSingleNanoapp) {
89   constexpr uint64_t kAppId = 0x0123456789abcdef;
90   constexpr uint32_t kAppVersion = 0;
91   constexpr uint32_t kAppPerms = 0;
92 
93   UniquePtr<Nanoapp> nanoapp = createStaticNanoapp(
94       "Test nanoapp", kAppId, kAppVersion, kAppPerms, defaultNanoappStart,
95       defaultNanoappHandleEvent, defaultNanoappEnd);
96 
97   EventLoopManagerSingleton::get()->deferCallback(
98       SystemCallbackType::FinishLoadingNanoapp, std::move(nanoapp),
99       testFinishLoadingNanoappCallback);
100   waitForEvent(CHRE_EVENT_SIMULATION_TEST_NANOAPP_LOADED);
101 }
102 
TEST_F(TestBase,CanLoadAndStartMultipleNanoapps)103 TEST_F(TestBase, CanLoadAndStartMultipleNanoapps) {
104   constexpr uint64_t kAppId1 = 0x123;
105   constexpr uint64_t kAppId2 = 0x456;
106   constexpr uint32_t kAppVersion = 0;
107   constexpr uint32_t kAppPerms = 0;
108   loadNanoapp("Test nanoapp", kAppId1, kAppVersion, kAppPerms,
109               defaultNanoappStart, defaultNanoappHandleEvent,
110               defaultNanoappEnd);
111 
112   loadNanoapp("Test nanoapp", kAppId2, kAppVersion, kAppPerms,
113               defaultNanoappStart, defaultNanoappHandleEvent,
114               defaultNanoappEnd);
115 
116   uint16_t id1;
117   EXPECT_TRUE(EventLoopManagerSingleton::get()
118                   ->getEventLoop()
119                   .findNanoappInstanceIdByAppId(kAppId1, &id1));
120   uint16_t id2;
121   EXPECT_TRUE(EventLoopManagerSingleton::get()
122                   ->getEventLoop()
123                   .findNanoappInstanceIdByAppId(kAppId2, &id2));
124 
125   EXPECT_NE(id1, id2);
126 }
127 
TEST_F(TestBase,methods)128 TEST_F(TestBase, methods) {
129   CREATE_CHRE_TEST_EVENT(SOME_EVENT, 0);
130 
131   class App : public TestNanoapp {
132    public:
133     explicit App(TestNanoappInfo info) : TestNanoapp(info) {}
134     bool start() override {
135       LOGE("start");
136       mTest = 0xc0ffee;
137       return true;
138     }
139 
140     void handleEvent(uint32_t /*senderInstanceId*/, uint16_t /*eventType*/,
141                      const void * /**eventData*/) override {
142       LOGE("handleEvent %" PRIx16, mTest);
143     }
144 
145     void end() override {
146       LOGE("end");
147     }
148 
149    protected:
150     uint32_t mTest = 0;
151   };
152 
153   uint64_t appId = loadNanoapp(MakeUnique<App>(TestNanoappInfo{.id = 0x456}));
154 
155   sendEventToNanoapp(appId, SOME_EVENT);
156 }
157 
158 // Explicitly instantiate the TestEventQueueSingleton to reduce codesize.
159 template class Singleton<TestEventQueue>;
160 
161 }  // namespace chre
162