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