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 specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "serviceutils/PriorityDumper.h"
18
19#include <vector>
20
21#include <gmock/gmock.h>
22#include <gtest/gtest.h>
23
24#include <utils/String16.h>
25#include <utils/Vector.h>
26
27using namespace android;
28
29using ::testing::ElementsAreArray;
30using ::testing::Mock;
31using ::testing::Test;
32
33class PriorityDumperMock : public PriorityDumper {
34public:
35    MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
36    MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
37    MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
38    MOCK_METHOD3(dumpAll, status_t(int, const Vector<String16>&, bool));
39};
40
41class DumpAllMock : public PriorityDumper {
42public:
43    MOCK_METHOD3(dumpCritical, status_t(int, const Vector<String16>&, bool));
44    MOCK_METHOD3(dumpHigh, status_t(int, const Vector<String16>&, bool));
45    MOCK_METHOD3(dumpNormal, status_t(int, const Vector<String16>&, bool));
46};
47
48class PriorityDumperTest : public Test {
49public:
50    PriorityDumperTest() : dumper_(), dumpAlldumper_(), fd(1) {}
51    PriorityDumperMock dumper_;
52    DumpAllMock dumpAlldumper_;
53    int fd;
54};
55
56static void addAll(Vector<String16>& av, const std::vector<std::string>& v) {
57    for (auto element : v) {
58        av.add(String16(element.c_str()));
59    }
60}
61
62TEST_F(PriorityDumperTest, noArgsPassed) {
63    Vector<String16> args;
64    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
65    dumper_.priorityDump(fd, args);
66}
67
68TEST_F(PriorityDumperTest, noPriorityArgsPassed) {
69    Vector<String16> args;
70    addAll(args, {"bunch", "of", "args"});
71    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(args), /*asProto=*/false));
72    dumper_.priorityDump(fd, args);
73}
74
75TEST_F(PriorityDumperTest, priorityArgsOnly) {
76    Vector<String16> args;
77    addAll(args, {"--dump-priority", "CRITICAL"});
78    Vector<String16> strippedArgs;
79    EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
80    dumper_.priorityDump(fd, args);
81}
82
83TEST_F(PriorityDumperTest, dumpCritical) {
84    Vector<String16> args;
85    addAll(args, {"--dump-priority", "CRITICAL", "args", "left", "behind"});
86    Vector<String16> strippedArgs;
87    addAll(strippedArgs, {"args", "left", "behind"});
88
89    EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
90    dumper_.priorityDump(fd, args);
91}
92
93TEST_F(PriorityDumperTest, dumpCriticalInMiddle) {
94    Vector<String16> args;
95    addAll(args, {"args", "left", "--dump-priority", "CRITICAL", "behind"});
96    Vector<String16> strippedArgs;
97    addAll(strippedArgs, {"args", "left", "behind"});
98
99    EXPECT_CALL(dumper_, dumpCritical(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
100    dumper_.priorityDump(fd, args);
101}
102
103TEST_F(PriorityDumperTest, dumpHigh) {
104    Vector<String16> args;
105    addAll(args, {"--dump-priority", "HIGH", "args", "left", "behind"});
106    Vector<String16> strippedArgs;
107    addAll(strippedArgs, {"args", "left", "behind"});
108
109    EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
110    dumper_.priorityDump(fd, args);
111}
112
113TEST_F(PriorityDumperTest, dumpHighInEnd) {
114    Vector<String16> args;
115    addAll(args, {"args", "left", "behind", "--dump-priority", "HIGH"});
116    Vector<String16> strippedArgs;
117    addAll(strippedArgs, {"args", "left", "behind"});
118
119    EXPECT_CALL(dumper_, dumpHigh(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
120    dumper_.priorityDump(fd, args);
121}
122
123TEST_F(PriorityDumperTest, dumpNormal) {
124    Vector<String16> args;
125    addAll(args, {"--dump-priority", "NORMAL", "args", "left", "behind"});
126    Vector<String16> strippedArgs;
127    addAll(strippedArgs, {"args", "left", "behind"});
128
129    EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
130    dumper_.priorityDump(fd, args);
131}
132
133TEST_F(PriorityDumperTest, dumpAll) {
134    Vector<String16> args;
135    addAll(args, {"args", "left", "behind"});
136
137    EXPECT_CALL(dumpAlldumper_, dumpCritical(fd, ElementsAreArray(args), /*asProto=*/false));
138    EXPECT_CALL(dumpAlldumper_, dumpHigh(fd, ElementsAreArray(args), /*asProto=*/false));
139    EXPECT_CALL(dumpAlldumper_, dumpNormal(fd, ElementsAreArray(args), /*asProto=*/false));
140
141    dumpAlldumper_.priorityDump(fd, args);
142}
143
144TEST_F(PriorityDumperTest, priorityArgWithPriorityMissing) {
145    Vector<String16> args;
146    addAll(args, {"--dump-priority"});
147    Vector<String16> strippedArgs;
148    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
149
150    dumper_.priorityDump(fd, args);
151}
152
153TEST_F(PriorityDumperTest, priorityArgWithInvalidPriority) {
154    Vector<String16> args;
155    addAll(args, {"--dump-priority", "REALLY_HIGH"});
156    Vector<String16> strippedArgs;
157    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/false));
158
159    dumper_.priorityDump(fd, args);
160}
161
162TEST_F(PriorityDumperTest, protoArg) {
163    Vector<String16> args;
164    addAll(args, {"--proto"});
165    Vector<String16> strippedArgs;
166    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
167
168    dumper_.priorityDump(fd, args);
169}
170
171TEST_F(PriorityDumperTest, protoArgWithPriorityArgs) {
172    Vector<String16> args;
173    addAll(args, {"--proto", "args", "--dump-priority", "NORMAL", "left", "behind"});
174    Vector<String16> strippedArgs;
175    addAll(strippedArgs, {"args", "left", "behind"});
176    EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
177
178    dumper_.priorityDump(fd, args);
179}
180
181TEST_F(PriorityDumperTest, protoArgWithPriorityArgsInReverseOrder) {
182    Vector<String16> args;
183    addAll(args, {"--dump-priority", "NORMAL", "--proto", "args", "left", "behind"});
184    Vector<String16> strippedArgs;
185    addAll(strippedArgs, {"args", "left", "behind"});
186    EXPECT_CALL(dumper_, dumpNormal(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
187
188    dumper_.priorityDump(fd, args);
189}
190
191TEST_F(PriorityDumperTest, protoArgInMiddle) {
192    Vector<String16> args;
193    addAll(args, {"--unknown", "args", "--proto", "args", "left", "behind"});
194    Vector<String16> strippedArgs;
195    addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
196    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
197
198    dumper_.priorityDump(fd, args);
199}
200
201TEST_F(PriorityDumperTest, protoArgAtEnd) {
202    Vector<String16> args;
203    addAll(args, {"--unknown", "args", "args", "left", "behind", "--proto"});
204    Vector<String16> strippedArgs;
205    addAll(strippedArgs, {"--unknown", "args", "args", "left", "behind"});
206    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
207
208    dumper_.priorityDump(fd, args);
209}
210
211TEST_F(PriorityDumperTest, protoArgWithInvalidPriorityType) {
212    Vector<String16> args;
213    addAll(args, {"--dump-priority", "NOT_SO_HIGH", "--proto", "args", "left", "behind"});
214    Vector<String16> strippedArgs;
215    addAll(strippedArgs, {"args", "left", "behind"});
216    EXPECT_CALL(dumper_, dumpAll(fd, ElementsAreArray(strippedArgs), /*asProto=*/true));
217
218    dumper_.priorityDump(fd, args);
219}