1 /*
2 * Copyright 2022 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 "ThreadPriorityController.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 namespace android {
23 namespace automotive {
24 namespace watchdog {
25 namespace {
26
27 using ::aidl::android::automotive::watchdog::internal::ThreadPolicyWithPriority;
28 using ::android::base::Result;
29 using ::testing::_;
30 using ::testing::Return;
31
32 MATCHER_P(PriorityEq, priority, "") {
33 return (arg->sched_priority) == priority;
34 }
35
36 class MockSystemCalls : public ThreadPriorityController::SystemCallsInterface {
37 public:
MockSystemCalls(int tid,int uid,int pid)38 MockSystemCalls(int tid, int uid, int pid) {
39 ON_CALL(*this, readPidStatusFileForPid(tid))
40 .WillByDefault(Return(std::make_tuple(uid, pid)));
41 }
42
43 MOCK_METHOD(int, setScheduler, (pid_t tid, int policy, const sched_param* param), (override));
44 MOCK_METHOD(int, getScheduler, (pid_t tid), (override));
45 MOCK_METHOD(int, getParam, (pid_t tid, sched_param* param), (override));
46 MOCK_METHOD((Result<std::tuple<uid_t, pid_t>>), readPidStatusFileForPid, (pid_t pid),
47 (override));
48 };
49
50 class ThreadPriorityControllerTest : public ::testing::Test {
51 public:
SetUp()52 virtual void SetUp() {
53 std::unique_ptr<MockSystemCalls> mockSystemCalls =
54 std::make_unique<MockSystemCalls>(TEST_TID, TEST_UID, TEST_PID);
55 mMockSystemCalls = mockSystemCalls.get();
56 mController = std::make_unique<ThreadPriorityController>(std::move(mockSystemCalls));
57 }
58
59 protected:
60 static constexpr pid_t TEST_PID = 1;
61 static constexpr pid_t TEST_TID = 2;
62 static constexpr uid_t TEST_UID = 3;
63
64 std::unique_ptr<ThreadPriorityController> mController;
65 MockSystemCalls* mMockSystemCalls;
66 };
67
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriority)68 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriority) {
69 int policy = SCHED_FIFO;
70 int priority = 1;
71 EXPECT_CALL(*mMockSystemCalls, setScheduler(TEST_TID, policy, PriorityEq(priority)))
72 .WillOnce(Return(0));
73
74 auto result = mController->setThreadPriority(TEST_PID, TEST_TID, TEST_UID, policy, priority);
75
76 ASSERT_TRUE(result.ok()) << result.error().message();
77 }
78
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityDefaultPolicy)79 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityDefaultPolicy) {
80 int policy = SCHED_OTHER;
81 int setPriority = 1;
82 // Default policy should ignore the provided priority.
83 int expectedPriority = 0;
84 EXPECT_CALL(*mMockSystemCalls, setScheduler(TEST_TID, policy, PriorityEq(expectedPriority)))
85 .WillOnce(Return(0));
86
87 auto result = mController->setThreadPriority(TEST_PID, TEST_TID, TEST_UID, policy, setPriority);
88
89 ASSERT_TRUE(result.ok()) << result.error().message();
90 }
91
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityInvalidPid)92 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityInvalidPid) {
93 auto result = mController->setThreadPriority(TEST_PID + 1, TEST_TID, TEST_UID, SCHED_FIFO, 1);
94
95 EXPECT_FALSE(result.ok());
96 EXPECT_EQ(result.error().code(), EX_ILLEGAL_STATE);
97 }
98
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityInvalidTid)99 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityInvalidTid) {
100 auto result = mController->setThreadPriority(TEST_PID, TEST_TID + 1, TEST_UID, SCHED_FIFO, 1);
101
102 EXPECT_FALSE(result.ok());
103 EXPECT_EQ(result.error().code(), EX_ILLEGAL_STATE);
104 }
105
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityInvalidUid)106 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityInvalidUid) {
107 auto result = mController->setThreadPriority(TEST_PID, TEST_TID, TEST_UID + 1, SCHED_FIFO, 1);
108
109 EXPECT_FALSE(result.ok());
110 EXPECT_EQ(result.error().code(), EX_ILLEGAL_STATE);
111 }
112
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityInvalidPolicy)113 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityInvalidPolicy) {
114 auto result = mController->setThreadPriority(TEST_PID, TEST_TID, TEST_UID, -1, 1);
115
116 EXPECT_FALSE(result.ok());
117 EXPECT_EQ(result.error().code(), EX_ILLEGAL_ARGUMENT);
118 }
119
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityInvalidPriority)120 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityInvalidPriority) {
121 auto result = mController->setThreadPriority(TEST_PID, TEST_TID, TEST_UID, SCHED_FIFO, 0);
122
123 EXPECT_FALSE(result.ok());
124 EXPECT_EQ(result.error().code(), EX_ILLEGAL_ARGUMENT);
125 }
126
TEST_F(ThreadPriorityControllerTest,TestSetThreadPriorityFailed)127 TEST_F(ThreadPriorityControllerTest, TestSetThreadPriorityFailed) {
128 int expectedPolicy = SCHED_FIFO;
129 int expectedPriority = 1;
130 EXPECT_CALL(*mMockSystemCalls,
131 setScheduler(TEST_TID, expectedPolicy, PriorityEq(expectedPriority)))
132 .WillOnce(Return(-1));
133
134 auto result = mController->setThreadPriority(TEST_PID, TEST_TID, TEST_UID, expectedPolicy,
135 expectedPriority);
136
137 EXPECT_FALSE(result.ok());
138 EXPECT_EQ(result.error().code(), EX_SERVICE_SPECIFIC);
139 }
140
TEST_F(ThreadPriorityControllerTest,TestGetThreadPriority)141 TEST_F(ThreadPriorityControllerTest, TestGetThreadPriority) {
142 int expectedPolicy = SCHED_FIFO;
143 int expectedPriority = 1;
144 EXPECT_CALL(*mMockSystemCalls, getScheduler(TEST_TID)).WillOnce(Return(expectedPolicy));
145 EXPECT_CALL(*mMockSystemCalls, getParam(TEST_TID, _))
146 .WillOnce([expectedPriority](pid_t, sched_param* param) {
147 param->sched_priority = expectedPriority;
148 return 0;
149 });
150
151 ThreadPolicyWithPriority actual;
152 auto result = mController->getThreadPriority(TEST_PID, TEST_TID, TEST_UID, &actual);
153
154 ASSERT_TRUE(result.ok()) << result.error().message();
155 EXPECT_EQ(actual.policy, expectedPolicy);
156 EXPECT_EQ(actual.priority, expectedPriority);
157 }
158
TEST_F(ThreadPriorityControllerTest,TestGetThreadPriorityInvalidPid)159 TEST_F(ThreadPriorityControllerTest, TestGetThreadPriorityInvalidPid) {
160 ThreadPolicyWithPriority actual;
161 auto result = mController->getThreadPriority(TEST_PID + 1, TEST_TID, TEST_UID, &actual);
162
163 EXPECT_FALSE(result.ok());
164 EXPECT_EQ(result.error().code(), EX_ILLEGAL_STATE);
165 }
166
TEST_F(ThreadPriorityControllerTest,TestGetThreadPriorityGetSchedulerFailed)167 TEST_F(ThreadPriorityControllerTest, TestGetThreadPriorityGetSchedulerFailed) {
168 EXPECT_CALL(*mMockSystemCalls, getScheduler(TEST_TID)).WillOnce(Return(-1));
169
170 ThreadPolicyWithPriority actual;
171 auto result = mController->getThreadPriority(TEST_PID, TEST_TID, TEST_UID, &actual);
172
173 EXPECT_FALSE(result.ok());
174 EXPECT_EQ(result.error().code(), EX_SERVICE_SPECIFIC);
175 }
176
TEST_F(ThreadPriorityControllerTest,TestGetThreadPriorityGetParamFailed)177 TEST_F(ThreadPriorityControllerTest, TestGetThreadPriorityGetParamFailed) {
178 EXPECT_CALL(*mMockSystemCalls, getScheduler(TEST_TID)).WillOnce(Return(0));
179 EXPECT_CALL(*mMockSystemCalls, getParam(TEST_TID, _)).WillOnce(Return(-1));
180
181 ThreadPolicyWithPriority actual;
182 auto result = mController->getThreadPriority(TEST_PID, TEST_TID, TEST_UID, &actual);
183
184 EXPECT_FALSE(result.ok());
185 EXPECT_EQ(result.error().code(), EX_SERVICE_SPECIFIC);
186 }
187
188 } // namespace
189 } // namespace watchdog
190 } // namespace automotive
191 } // namespace android
192