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 <gtest/gtest.h>
18 
19 #include <algorithm>
20 #include <thread>
21 
22 #include "perfmgr/RequestGroup.h"
23 
24 namespace android {
25 namespace perfmgr {
26 
27 using namespace std::chrono_literals;
28 
29 constexpr double kTIMING_TOLERANCE_MS = std::chrono::milliseconds(25).count();
30 
31 // Test GetRequestValue()
TEST(RequestGroupTest,GetRequestValueTest)32 TEST(RequestGroupTest, GetRequestValueTest) {
33     std::string test_str = "TESTREQ_1";
34     RequestGroup req(test_str);
35     EXPECT_EQ(test_str, req.GetRequestValue());
36 }
37 
38 // Test AddRequest()
TEST(RequestGroupTest,AddRequestTest)39 TEST(RequestGroupTest, AddRequestTest) {
40     RequestGroup req("");
41     auto start = std::chrono::steady_clock::now();
42     auto duration = 500ms;
43     bool ret = req.AddRequest("INTERACTION", start + duration);
44     EXPECT_EQ(true, ret);
45     auto sleep_time = 200ms;
46     std::this_thread::sleep_for(sleep_time);
47     std::chrono::milliseconds expire_time;
48     bool active = req.GetExpireTime(&expire_time);
49     EXPECT_NEAR((duration - sleep_time).count(), expire_time.count(),
50                 kTIMING_TOLERANCE_MS);
51     EXPECT_EQ(true, active);
52 }
53 
54 // Test AddRequest() with a huge expire time which could be done in some long
55 // persist power hint such as VR_MODE
TEST(RequestGroupTest,AddRequestNoExpireTest)56 TEST(RequestGroupTest, AddRequestNoExpireTest) {
57     RequestGroup req("");
58     bool ret = req.AddRequest("INTERACTION", ReqTime::max());
59     EXPECT_EQ(true, ret);
60     std::chrono::milliseconds expire_time;
61     bool active = req.GetExpireTime(&expire_time);
62     auto expect = std::chrono::duration_cast<std::chrono::milliseconds>(
63         ReqTime::max() - std::chrono::steady_clock::now());
64     EXPECT_NEAR(expect.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
65     // expire time is greater than 1 year
66     EXPECT_LE(365 * 24 * 60 * 60 * 1000, expire_time.count());
67     EXPECT_EQ(true, active);
68 }
69 
70 // Test AddRequest() and expires
TEST(RequestGroupTest,AddRequestTestExpire)71 TEST(RequestGroupTest, AddRequestTestExpire) {
72     RequestGroup req("");
73     auto start = std::chrono::steady_clock::now();
74     auto duration = 5ms;
75     bool ret = req.AddRequest("INTERACTION", start + duration);
76     EXPECT_EQ(true, ret);
77     ret = req.AddRequest("INTERACTION", start + duration + 1ms);
78     EXPECT_EQ(false, ret);
79     std::this_thread::sleep_for(duration + 10ms);
80     std::chrono::milliseconds expire_time;
81     bool active = req.GetExpireTime(&expire_time);
82     EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
83     EXPECT_EQ(false, active);
84 }
85 
86 // Test AddRequest() with new value
TEST(RequestGroupTest,AddRequestNewValue)87 TEST(RequestGroupTest, AddRequestNewValue) {
88     RequestGroup req("");
89     auto start = std::chrono::steady_clock::now();
90     auto duration = 5000ms;
91     bool ret = req.AddRequest("INTERACTION", start + duration);
92     EXPECT_EQ(true, ret);
93     std::chrono::milliseconds expire_time;
94     bool active = req.GetExpireTime(&expire_time);
95     EXPECT_NEAR(duration.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
96     EXPECT_EQ(true, active);
97     // Add a request shorter than the current outstanding one, expiration time
98     // not changed
99     auto shorter_duration = 100ms;
100     ret = req.AddRequest("INTERACTION", start + shorter_duration);
101     EXPECT_EQ(false, ret);
102     active = req.GetExpireTime(&expire_time);
103     EXPECT_NEAR(duration.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
104     EXPECT_EQ(true, active);
105     // Add a request longer than the current outstanding one, expiration time
106     // changed
107     duration = 10000ms;
108     ret = req.AddRequest("INTERACTION", start + duration);
109     EXPECT_EQ(false, ret);
110     active = req.GetExpireTime(&expire_time);
111     EXPECT_NEAR(duration.count(), expire_time.count(), kTIMING_TOLERANCE_MS);
112     EXPECT_EQ(true, active);
113 }
114 
115 // Test multiple AddRequest() with different hint_type
TEST(RequestGroupTest,AddRequestTestMultiple)116 TEST(RequestGroupTest, AddRequestTestMultiple) {
117     RequestGroup req("");
118     auto start = std::chrono::steady_clock::now();
119     auto duration_interact = 500ms;
120     req.AddRequest("INTERACTION", start + duration_interact);
121     auto duration_launch = 5000ms;
122     req.AddRequest("LAUNCH", start + duration_launch);
123     std::chrono::milliseconds expire_time;
124     bool active = req.GetExpireTime(&expire_time);
125     EXPECT_NEAR(std::min(duration_interact, duration_launch).count(),
126                 expire_time.count(), kTIMING_TOLERANCE_MS);
127     EXPECT_EQ(true, active);
128 }
129 
130 // Test RemoveRequest()
TEST(RequestGroupTest,RemoveRequestTest)131 TEST(RequestGroupTest, RemoveRequestTest) {
132     RequestGroup req("");
133     auto start = std::chrono::steady_clock::now();
134     auto duration_interact = 500ms;
135     req.AddRequest("INTERACTION", start + duration_interact);
136     bool ret = req.RemoveRequest("INTERACTION");
137     EXPECT_EQ(true, ret);
138     std::chrono::milliseconds expire_time;
139     bool active = req.GetExpireTime(&expire_time);
140     EXPECT_EQ(std::chrono::milliseconds::max(), expire_time);
141     EXPECT_EQ(false, active);
142     // Test removing an already-removed request
143     ret = req.RemoveRequest("INTERACTION");
144     EXPECT_EQ(false, ret);
145 }
146 
147 // Test multiple RemoveRequest() with different hint_type
TEST(RequestGroupTest,RemoveRequestTestMultiple)148 TEST(RequestGroupTest, RemoveRequestTestMultiple) {
149     RequestGroup req("");
150     auto start = std::chrono::steady_clock::now();
151     auto duration_interact = 500ms;
152     req.AddRequest("INTERACTION", start + duration_interact);
153     auto duration_launch = 50000ms;
154     req.AddRequest("LAUNCH", start + duration_launch);
155     req.RemoveRequest("INTERACTION");
156     std::chrono::milliseconds expire_time;
157     bool active = req.GetExpireTime(&expire_time);
158     EXPECT_NEAR(duration_launch.count(), expire_time.count(),
159                 kTIMING_TOLERANCE_MS);
160     EXPECT_EQ(true, active);
161 }
162 
163 }  // namespace perfmgr
164 }  // namespace android
165