1 /*
2 * Copyright (C) 2016 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 #define LOG_TAG "libhidl-gen-utils"
18
19 #include <vector>
20
21 #include <gtest/gtest.h>
22
23 #include <ConstantExpression.h>
24 #include <Coordinator.h>
25 #include <hidl-util/FQName.h>
26
27 #define EXPECT_EQ_OK(expectResult, call, ...) \
28 do { \
29 std::string result; \
30 status_t err = (call)(__VA_ARGS__, &result); \
31 EXPECT_EQ(err, ::android::OK); \
32 EXPECT_EQ(expectResult, result); \
33 } while (false)
34
35 namespace android {
36
37 class HidlGenHostTest : public ::testing::Test {};
38
39 class HidlGenHostDeathTest : public ::testing::Test {};
40
TEST_F(HidlGenHostTest,CoordinatorTest)41 TEST_F(HidlGenHostTest, CoordinatorTest) {
42 Coordinator coordinator;
43
44 std::string error;
45 EXPECT_EQ(OK, coordinator.addPackagePath("a.b", "a1/b1", &error));
46 EXPECT_TRUE(error.empty());
47 EXPECT_NE(OK, coordinator.addPackagePath("a.b", "a2/b2/", &error));
48 EXPECT_FALSE(error.empty());
49
50 coordinator.addDefaultPackagePath("a.b", "a3/b3/"); // should take path above
51 coordinator.addDefaultPackagePath("a.c", "a4/b4/"); // should succeed
52
53 EXPECT_EQ_OK("a.b", coordinator.getPackageRoot, FQName("a.b.foo", "1.0"));
54 EXPECT_EQ_OK("a.c", coordinator.getPackageRoot, FQName("a.c.foo.bar", "1.0", "IFoo"));
55
56 // getPackagePath(fqname, relative, sanitized, ...)
57 EXPECT_EQ_OK("a1/b1/foo/1.0/", coordinator.getPackagePath, FQName("a.b.foo", "1.0"), false,
58 false);
59 EXPECT_EQ_OK("a4/b4/foo/bar/1.0/", coordinator.getPackagePath,
60 FQName("a.c.foo.bar", "1.0", "IFoo"), false, false);
61 EXPECT_EQ_OK("a1/b1/foo/V1_0/", coordinator.getPackagePath, FQName("a.b.foo", "1.0"), false,
62 true);
63 EXPECT_EQ_OK("a4/b4/foo/bar/V1_0/", coordinator.getPackagePath,
64 FQName("a.c.foo.bar", "1.0", "IFoo"), false, true);
65 EXPECT_EQ_OK("foo/1.0/", coordinator.getPackagePath, FQName("a.b.foo", "1.0"), true, false);
66 EXPECT_EQ_OK("foo/bar/1.0/", coordinator.getPackagePath, FQName("a.c.foo.bar", "1.0", "IFoo"),
67 true, false);
68 EXPECT_EQ_OK("foo/V1_0/", coordinator.getPackagePath, FQName("a.b.foo", "1.0"), true, true);
69 EXPECT_EQ_OK("foo/bar/V1_0/", coordinator.getPackagePath, FQName("a.c.foo.bar", "1.0", "IFoo"),
70 true, true);
71 }
72
TEST_F(HidlGenHostTest,CoordinatorFilepathTest)73 TEST_F(HidlGenHostTest, CoordinatorFilepathTest) {
74 using Location = Coordinator::Location;
75
76 Coordinator coordinator;
77 coordinator.setOutputPath("foo/");
78 coordinator.setRootPath("bar/");
79
80 std::string error;
81 EXPECT_EQ(OK, coordinator.addPackagePath("a.b", "a1/b1", &error));
82 EXPECT_TRUE(error.empty());
83
84 const static FQName kName = FQName("a.b.c", "1.2");
85
86 // get file names
87 EXPECT_EQ_OK("foo/x.y", coordinator.getFilepath, kName, Location::DIRECT, "x.y");
88 EXPECT_EQ_OK("foo/a1/b1/c/1.2/x.y", coordinator.getFilepath, kName, Location::PACKAGE_ROOT,
89 "x.y");
90 EXPECT_EQ_OK("foo/a/b/c/1.2/x.y", coordinator.getFilepath, kName, Location::GEN_OUTPUT, "x.y");
91 EXPECT_EQ_OK("foo/a/b/c/V1_2/x.y", coordinator.getFilepath, kName, Location::GEN_SANITIZED,
92 "x.y");
93
94 // get directories
95 EXPECT_EQ_OK("foo/", coordinator.getFilepath, kName, Location::DIRECT, "");
96 EXPECT_EQ_OK("foo/a1/b1/c/1.2/", coordinator.getFilepath, kName, Location::PACKAGE_ROOT, "");
97 EXPECT_EQ_OK("foo/a/b/c/1.2/", coordinator.getFilepath, kName, Location::GEN_OUTPUT, "");
98 EXPECT_EQ_OK("foo/a/b/c/V1_2/", coordinator.getFilepath, kName, Location::GEN_SANITIZED, "");
99 }
100
TEST_F(HidlGenHostTest,LocationTest)101 TEST_F(HidlGenHostTest, LocationTest) {
102 Location a{{"file", 3, 4}, {"file", 3, 5}};
103 Location b{{"file", 3, 6}, {"file", 3, 7}};
104 Location c{{"file", 4, 4}, {"file", 4, 5}};
105
106 Location other{{"other", 0, 0}, {"other", 0, 1}};
107
108 EXPECT_LT(a, b);
109 EXPECT_LT(b, c);
110 EXPECT_LT(a, c);
111 EXPECT_FALSE(Location::inSameFile(a, other));
112 }
113
populateArgv(std::vector<const char * > options,char ** argv)114 void populateArgv(std::vector<const char*> options, char** argv) {
115 for (int i = 0; i < options.size(); i++) {
116 argv[i] = const_cast<char*>(options.at(i));
117 }
118 }
119
TEST_F(HidlGenHostTest,CoordinatorRootPathTest)120 TEST_F(HidlGenHostTest, CoordinatorRootPathTest) {
121 // Test that rootPath is set correctly
122 Coordinator coordinator;
123
124 std::vector<const char*> options = {"hidl-gen", "-p", "~/"};
125 char* argv[options.size()];
126
127 populateArgv(options, argv);
128 coordinator.parseOptions(options.size(), argv, "", [&](int /* res */, char* /* arg */) {
129 // Coordinator should always handle -p
130 FAIL() << "Coordinator should handle -p";
131 });
132
133 EXPECT_EQ("~/", coordinator.getRootPath());
134 }
135
TEST_F(HidlGenHostDeathTest,CoordinatorTooManyRootPathsTest)136 TEST_F(HidlGenHostDeathTest, CoordinatorTooManyRootPathsTest) {
137 // Test that cannot set multiple rootPaths
138 Coordinator coordinator;
139
140 std::vector<const char*> options = {"hidl-gen", "-p", "~/", "-p", "."};
141 char* argv[options.size()];
142
143 populateArgv(options, argv);
144 EXPECT_DEATH(coordinator.parseOptions(options.size(), argv, "",
145 [&](int /* res */, char* /* arg */) {
146 // Coordinator should always handle -p
147 FAIL() << "Coordinator should handle -p";
148 }),
149 "ERROR: -p <root path> can only be specified once.");
150 }
151
TEST_F(HidlGenHostTest,CoordinatorNoDefaultRootTest)152 TEST_F(HidlGenHostTest, CoordinatorNoDefaultRootTest) {
153 // Test that overrides default root paths without specifying new roots
154 Coordinator coordinator;
155
156 std::vector<const char*> options = {"hidl-gen", "-R"};
157 char* argv[options.size()];
158
159 populateArgv(options, argv);
160 coordinator.parseOptions(options.size(), argv, "", [&](int /* res */, char* /* arg */) {
161 // Coordinator should always handle -R
162 FAIL() << "Coordinator should handle -R";
163 });
164
165 // android.hardware is a default path. with -R specified it should not be set
166 std::string root;
167 EXPECT_NE(::android::OK,
168 coordinator.getPackageRoot(FQName("android.hardware.tests.Baz", "1.0"), &root));
169 EXPECT_EQ("", root);
170 }
171
TEST_F(HidlGenHostTest,CoordinatorCustomArgParseTest)172 TEST_F(HidlGenHostTest, CoordinatorCustomArgParseTest) {
173 // Test custom args are sent to the function
174 Coordinator coordinator;
175
176 std::string optstring = "xy:";
177 std::vector<const char*> options = {"hidl-gen", "-y", "yvalue", "-x"};
178 char* argv[options.size()];
179
180 populateArgv(options, argv);
181
182 bool xCalled = false;
183 bool yCalled = false;
184 coordinator.parseOptions(options.size(), argv, optstring, [&](int res, char* arg) {
185 switch (res) {
186 case 'x': {
187 EXPECT_STREQ(nullptr, arg);
188 xCalled = true;
189 break;
190 }
191 case 'y': {
192 EXPECT_STREQ(argv[2] /* "yvalue" */, arg);
193 yCalled = true;
194 break;
195 }
196 default: { FAIL() << "Coordinator sent invalid param " << (char)res; }
197 }
198 });
199
200 // Ensure the function was called with both x and y
201 EXPECT_TRUE(xCalled);
202 EXPECT_TRUE(yCalled);
203 }
204
main(int argc,char ** argv)205 int main(int argc, char **argv) {
206 ::testing::InitGoogleTest(&argc, argv);
207 return RUN_ALL_TESTS();
208 }
209
210 } // namespace android