1 /*
2 * Copyright (C) 2017 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 specic language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android-base/file.h>
18 #include <gtest/gtest.h>
19
20 #include <algorithm>
21 #include <thread>
22
23 #include "perfmgr/FileNode.h"
24 #include "perfmgr/NodeLooperThread.h"
25
26 namespace android {
27 namespace perfmgr {
28
29 using std::literals::chrono_literals::operator""ms;
30
31 constexpr auto kSLEEP_TOLERANCE_MS = 50ms;
32
33 class NodeLooperThreadTest : public ::testing::Test {
34 protected:
SetUp()35 virtual void SetUp() {
36 std::unique_ptr<TemporaryFile> tf = std::make_unique<TemporaryFile>();
37 nodes_.emplace_back(new FileNode(
38 "n0", tf->path, {{"n0_value0"}, {"n0_value1"}, {"n0_value2"}}, 2,
39 false));
40 files_.emplace_back(std::move(tf));
41 tf = std::make_unique<TemporaryFile>();
42 nodes_.emplace_back(new FileNode(
43 "n1", tf->path, {{"n1_value0"}, {"n1_value1"}, {"n1_value2"}}, 2,
44 true));
45 files_.emplace_back(std::move(tf));
46 }
47
TearDown()48 virtual void TearDown() {
49 nodes_.clear();
50 files_.clear();
51 }
52 std::vector<std::unique_ptr<Node>> nodes_;
53 std::vector<std::unique_ptr<TemporaryFile>> files_;
54 };
55
_VerifyPathValue(const std::string & path,const std::string & value)56 static inline void _VerifyPathValue(const std::string& path,
57 const std::string& value) {
58 std::string s;
59 EXPECT_TRUE(android::base::ReadFileToString(path, &s)) << strerror(errno);
60 EXPECT_EQ(value, s);
61 }
62
63 // Test default value init
TEST_F(NodeLooperThreadTest,InitRunTest)64 TEST_F(NodeLooperThreadTest, InitRunTest) {
65 sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
66 EXPECT_TRUE(th->Start());
67 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
68 EXPECT_TRUE(th->isRunning());
69 _VerifyPathValue(files_[0]->path, "");
70 _VerifyPathValue(files_[1]->path, "n1_value2");
71 th->Stop();
72 EXPECT_FALSE(th->isRunning());
73 }
74
75 // Test add request
TEST_F(NodeLooperThreadTest,AddRequest)76 TEST_F(NodeLooperThreadTest, AddRequest) {
77 sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
78 EXPECT_TRUE(th->Start());
79 EXPECT_TRUE(th->isRunning());
80 // Dummy LAUNCH boost actions:
81 // Node0, value0, 200ms
82 // Node1, value1, 400ms
83 std::vector<NodeAction> actions{{0, 0, 200ms}, {1, 1, 400ms}};
84 EXPECT_TRUE(th->Request(actions, "LAUNCH"));
85 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
86 _VerifyPathValue(files_[0]->path, "n0_value0");
87 _VerifyPathValue(files_[1]->path, "n1_value1");
88 std::this_thread::sleep_for(200ms);
89 _VerifyPathValue(files_[0]->path, "n0_value2");
90 _VerifyPathValue(files_[1]->path, "n1_value1");
91 std::this_thread::sleep_for(200ms);
92 _VerifyPathValue(files_[0]->path, "n0_value2");
93 _VerifyPathValue(files_[1]->path, "n1_value2");
94 th->Stop();
95 EXPECT_FALSE(th->isRunning());
96 }
97
98 // Test request to override expire time
TEST_F(NodeLooperThreadTest,AddRequestOverride)99 TEST_F(NodeLooperThreadTest, AddRequestOverride) {
100 sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
101 EXPECT_TRUE(th->Start());
102 EXPECT_TRUE(th->isRunning());
103 // Dummy LAUNCH boost actions:
104 // Node0, value0, 200ms
105 // Node1, value1, 500ms
106 std::vector<NodeAction> actions{{0, 0, 200ms}, {1, 1, 500ms}};
107 EXPECT_TRUE(th->Request(actions, "LAUNCH"));
108 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
109 _VerifyPathValue(files_[0]->path, "n0_value0");
110 _VerifyPathValue(files_[1]->path, "n1_value1");
111 // Dummy LAUNCH boost actions:
112 // Node0, value0, 300ms will extend
113 // Node1, value1, 100ms will not extend
114 actions = std::vector<NodeAction>{{0, 0, 300ms}, {1, 1, 100ms}};
115 EXPECT_TRUE(th->Request(actions, "LAUNCH"));
116 std::this_thread::sleep_for(200ms);
117 _VerifyPathValue(files_[0]->path, "n0_value0");
118 _VerifyPathValue(files_[1]->path, "n1_value1");
119 std::this_thread::sleep_for(150ms);
120 // Node0 value0 expired
121 _VerifyPathValue(files_[0]->path, "n0_value2");
122 _VerifyPathValue(files_[1]->path, "n1_value1");
123 std::this_thread::sleep_for(150ms);
124 _VerifyPathValue(files_[0]->path, "n0_value2");
125 _VerifyPathValue(files_[1]->path, "n1_value2");
126 th->Stop();
127 EXPECT_FALSE(th->isRunning());
128 }
129
130 // Test cancel request
TEST_F(NodeLooperThreadTest,CancelRequest)131 TEST_F(NodeLooperThreadTest, CancelRequest) {
132 sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
133 EXPECT_TRUE(th->Start());
134 EXPECT_TRUE(th->isRunning());
135 // Dummy LAUNCH boost actions:
136 // Node0, value0, forever
137 // Node1, value1, forever
138 std::vector<NodeAction> actions{{0, 0, 0ms}, {1, 1, 0ms}};
139 EXPECT_TRUE(th->Request(actions, "LAUNCH"));
140 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
141 _VerifyPathValue(files_[0]->path, "n0_value0");
142 _VerifyPathValue(files_[1]->path, "n1_value1");
143 EXPECT_TRUE(th->Cancel(actions, "LAUNCH"));
144 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
145 _VerifyPathValue(files_[0]->path, "n0_value2");
146 _VerifyPathValue(files_[1]->path, "n1_value2");
147 th->Stop();
148 EXPECT_FALSE(th->isRunning());
149 }
150
151 // Test multiple request
TEST_F(NodeLooperThreadTest,MultipleRequest)152 TEST_F(NodeLooperThreadTest, MultipleRequest) {
153 sp<NodeLooperThread> th = new NodeLooperThread(std::move(nodes_));
154 EXPECT_TRUE(th->Start());
155 EXPECT_TRUE(th->isRunning());
156 // Dummy LAUNCH boost actions:
157 // Node0, value1, 800ms
158 // Node1, value1, forever
159 std::vector<NodeAction> actions_interaction{{0, 1, 800ms}, {1, 1, 0ms}};
160 EXPECT_TRUE(th->Request(actions_interaction, "INTERACTION"));
161 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
162 _VerifyPathValue(files_[0]->path, "n0_value1");
163 _VerifyPathValue(files_[1]->path, "n1_value1");
164 // Dummy LAUNCH boost actions:
165 // Node0, value0, forever
166 // Node1, value0, 400ms
167 std::vector<NodeAction> actions_launch{{0, 0, 0ms}, {1, 0, 400ms}};
168 EXPECT_TRUE(th->Request(actions_launch, "LAUNCH"));
169 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
170 _VerifyPathValue(files_[0]->path, "n0_value0");
171 _VerifyPathValue(files_[1]->path, "n1_value0");
172 std::this_thread::sleep_for(400ms);
173 // "LAUNCH" node1 expired
174 _VerifyPathValue(files_[0]->path, "n0_value0");
175 _VerifyPathValue(files_[1]->path, "n1_value1");
176 EXPECT_TRUE(th->Cancel(actions_launch, "LAUNCH"));
177 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
178 // "LAUNCH" canceled
179 _VerifyPathValue(files_[0]->path, "n0_value1");
180 _VerifyPathValue(files_[1]->path, "n1_value1");
181 std::this_thread::sleep_for(400ms);
182 // "INTERACTION" node0 expired
183 _VerifyPathValue(files_[0]->path, "n0_value2");
184 _VerifyPathValue(files_[1]->path, "n1_value1");
185 EXPECT_TRUE(th->Cancel(actions_interaction, "INTERACTION"));
186 std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS);
187 // "INTERACTION" canceled
188 _VerifyPathValue(files_[0]->path, "n0_value2");
189 _VerifyPathValue(files_[1]->path, "n1_value2");
190 th->Stop();
191 EXPECT_FALSE(th->isRunning());
192 }
193
194 } // namespace perfmgr
195 } // namespace android
196