blob: d567af64b16a49027f066dcd72880f837869c2db [file] [log] [blame]
Mårten Kongstad02751232018-04-27 13:16:32 +02001/*
2 * Copyright (C) 2018 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 <sys/mman.h>
18#include <sys/stat.h>
19#include <sys/types.h>
20#include <unistd.h>
21
22#include <fstream>
23#include <memory>
24#include <sstream>
25#include <string>
26#include <vector>
27
28#include "gmock/gmock.h"
29#include "gtest/gtest.h"
30
31#include "android-base/file.h"
32#include "androidfw/ApkAssets.h"
33#include "androidfw/Idmap.h"
34#include "androidfw/LoadedArsc.h"
35
36#include "idmap2/CommandLineOptions.h"
37#include "idmap2/Idmap.h"
38
39#include "TestHelpers.h"
40
Mårten Kongstad0eba72a2018-11-29 08:23:14 +010041namespace android::idmap2 {
Mårten Kongstad02751232018-04-27 13:16:32 +020042
43TEST(CommandLineOptionsTests, Flag) {
Mårten Kongstadb8779022018-11-29 09:53:17 +010044 bool foo = true;
45 bool bar = false;
Mårten Kongstad02751232018-04-27 13:16:32 +020046 CommandLineOptions opts =
47 CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar);
48
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +010049 auto success = opts.Parse({"--foo", "--bar"});
Mårten Kongstad02751232018-04-27 13:16:32 +020050 ASSERT_TRUE(success);
51 ASSERT_TRUE(foo);
52 ASSERT_TRUE(bar);
53
54 foo = bar = false;
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +010055 success = opts.Parse({"--foo"});
Mårten Kongstad02751232018-04-27 13:16:32 +020056 ASSERT_TRUE(success);
57 ASSERT_TRUE(foo);
58 ASSERT_FALSE(bar);
59}
60
61TEST(CommandLineOptionsTests, MandatoryOption) {
Mårten Kongstadb8779022018-11-29 09:53:17 +010062 std::string foo;
63 std::string bar;
Mårten Kongstad02751232018-04-27 13:16:32 +020064 CommandLineOptions opts = CommandLineOptions("test")
65 .MandatoryOption("--foo", "", &foo)
66 .MandatoryOption("--bar", "", &bar);
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +010067 auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"});
Mårten Kongstad02751232018-04-27 13:16:32 +020068 ASSERT_TRUE(success);
69 ASSERT_EQ(foo, "FOO");
70 ASSERT_EQ(bar, "BAR");
71
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +010072 success = opts.Parse({"--foo"});
Mårten Kongstad02751232018-04-27 13:16:32 +020073 ASSERT_FALSE(success);
74}
75
76TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) {
77 std::string foo;
78 CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &foo);
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +010079 auto success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"});
Mårten Kongstad02751232018-04-27 13:16:32 +020080 ASSERT_TRUE(success);
81 ASSERT_EQ(foo, "SECOND");
82}
83
84TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore) {
85 std::vector<std::string> args;
86 CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &args);
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +010087 auto success = opts.Parse({"--foo", "FOO", "--foo", "BAR"});
Mårten Kongstad02751232018-04-27 13:16:32 +020088 ASSERT_TRUE(success);
Mårten Kongstadb8779022018-11-29 09:53:17 +010089 ASSERT_EQ(args.size(), 2U);
Mårten Kongstad02751232018-04-27 13:16:32 +020090 ASSERT_EQ(args[0], "FOO");
91 ASSERT_EQ(args[1], "BAR");
92}
93
94TEST(CommandLineOptionsTests, OptionalOption) {
Mårten Kongstadb8779022018-11-29 09:53:17 +010095 std::string foo;
96 std::string bar;
Mårten Kongstad02751232018-04-27 13:16:32 +020097 CommandLineOptions opts = CommandLineOptions("test")
98 .OptionalOption("--foo", "", &foo)
99 .OptionalOption("--bar", "", &bar);
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100100 auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200101 ASSERT_TRUE(success);
102 ASSERT_EQ(foo, "FOO");
103 ASSERT_EQ(bar, "BAR");
104
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100105 success = opts.Parse({"--foo", "BAZ"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200106 ASSERT_TRUE(success);
107 ASSERT_EQ(foo, "BAZ");
108
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100109 success = opts.Parse({"--foo"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200110 ASSERT_FALSE(success);
111
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100112 success = opts.Parse({"--foo", "--bar", "BAR"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200113 ASSERT_FALSE(success);
114
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100115 success = opts.Parse({"--foo", "FOO", "--bar"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200116 ASSERT_FALSE(success);
117}
118
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800119TEST(CommandLineOptionsTests, OptionalOptionList) {
120 std::vector<std::string> foo;
121 std::vector<std::string> bar;
122 CommandLineOptions opts = CommandLineOptions("test")
123 .OptionalOption("--foo", "", &foo)
124 .OptionalOption("--bar", "", &bar);
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100125 auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"});
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800126 ASSERT_TRUE(success);
127 ASSERT_EQ(foo.size(), 1U);
128 ASSERT_EQ(foo[0], "FOO");
129 ASSERT_EQ(bar.size(), 1U);
130 ASSERT_EQ(bar[0], "BAR");
131
132 foo.clear();
133 bar.clear();
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100134 success = opts.Parse({"--foo", "BAZ"});
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800135 ASSERT_TRUE(success);
136 ASSERT_EQ(foo.size(), 1U);
137 ASSERT_EQ(foo[0], "BAZ");
138 ASSERT_EQ(bar.size(), 0U);
139
140 foo.clear();
141 bar.clear();
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100142 success = opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"});
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800143 ASSERT_TRUE(success);
144 ASSERT_EQ(foo.size(), 2U);
145 ASSERT_EQ(foo[0], "BAZ");
146 ASSERT_EQ(foo[1], "BIZ");
147 ASSERT_EQ(bar.size(), 2U);
148 ASSERT_EQ(bar[0], "FIZ");
149 ASSERT_EQ(bar[1], "FUZZ");
150
151 foo.clear();
152 bar.clear();
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100153 success = opts.Parse({"--foo"});
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800154 ASSERT_FALSE(success);
155
156 foo.clear();
157 bar.clear();
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100158 success = opts.Parse({"--foo", "--bar", "BAR"});
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800159 ASSERT_FALSE(success);
160
161 foo.clear();
162 bar.clear();
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100163 success = opts.Parse({"--foo", "FOO", "--bar"});
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800164 ASSERT_FALSE(success);
165}
166
Mårten Kongstad02751232018-04-27 13:16:32 +0200167TEST(CommandLineOptionsTests, CornerCases) {
Mårten Kongstadb8779022018-11-29 09:53:17 +0100168 std::string foo;
169 std::string bar;
Mårten Kongstad02751232018-04-27 13:16:32 +0200170 bool baz = false;
171 CommandLineOptions opts = CommandLineOptions("test")
172 .MandatoryOption("--foo", "", &foo)
173 .OptionalFlag("--baz", "", &baz)
174 .OptionalOption("--bar", "", &bar);
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100175 auto success = opts.Parse({"--unexpected"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200176 ASSERT_FALSE(success);
177
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100178 success = opts.Parse({"--bar", "BAR"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200179 ASSERT_FALSE(success);
180
Mårten Kongstad0c6ff1d2019-02-07 02:21:56 +0100181 success = opts.Parse({"--baz", "--foo", "FOO"});
Mårten Kongstad02751232018-04-27 13:16:32 +0200182 ASSERT_TRUE(success);
183 ASSERT_TRUE(baz);
184 ASSERT_EQ(foo, "FOO");
185}
186
187TEST(CommandLineOptionsTests, ConvertArgvToVector) {
188 const char* argv[] = {
189 "program-name",
190 "--foo",
191 "FOO",
192 nullptr,
193 };
194 std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(3, argv);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100195 ASSERT_EQ(v->size(), 2UL);
Mårten Kongstad02751232018-04-27 13:16:32 +0200196 ASSERT_EQ((*v)[0], "--foo");
197 ASSERT_EQ((*v)[1], "FOO");
198}
199
200TEST(CommandLineOptionsTests, ConvertArgvToVectorNoArgs) {
201 const char* argv[] = {
202 "program-name",
203 nullptr,
204 };
205 std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(1, argv);
Mårten Kongstadb8779022018-11-29 09:53:17 +0100206 ASSERT_EQ(v->size(), 0UL);
Mårten Kongstad02751232018-04-27 13:16:32 +0200207}
208
209TEST(CommandLineOptionsTests, Usage) {
Mårten Kongstadb8779022018-11-29 09:53:17 +0100210 std::string arg1;
211 std::string arg2;
212 std::string arg3;
213 std::string arg4;
214 bool arg5 = false;
215 bool arg6 = false;
Mårten Kongstad02751232018-04-27 13:16:32 +0200216 std::vector<std::string> arg7;
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800217 std::vector<std::string> arg8;
Mårten Kongstad02751232018-04-27 13:16:32 +0200218 CommandLineOptions opts = CommandLineOptions("test")
219 .MandatoryOption("--aa", "description-aa", &arg1)
220 .OptionalFlag("--bb", "description-bb", &arg5)
221 .OptionalOption("--cc", "description-cc", &arg2)
222 .OptionalOption("--dd", "description-dd", &arg3)
223 .MandatoryOption("--ee", "description-ee", &arg4)
224 .OptionalFlag("--ff", "description-ff", &arg6)
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800225 .MandatoryOption("--gg", "description-gg", &arg7)
226 .OptionalOption("--hh", "description-hh", &arg8);
Mårten Kongstad02751232018-04-27 13:16:32 +0200227 std::stringstream stream;
228 opts.Usage(stream);
229 const std::string s = stream.str();
230 ASSERT_NE(s.find("usage: test --aa arg [--bb] [--cc arg] [--dd arg] --ee arg [--ff] --gg arg "
Mårten Kongstadd10d06d2019-01-07 17:26:25 -0800231 "[--gg arg [..]] [--hh arg [..]]"),
Mårten Kongstad02751232018-04-27 13:16:32 +0200232 std::string::npos);
233 ASSERT_NE(s.find("--aa arg description-aa"), std::string::npos);
234 ASSERT_NE(s.find("--ff description-ff"), std::string::npos);
235 ASSERT_NE(s.find("--gg arg description-gg (can be provided multiple times)"),
236 std::string::npos);
237}
238
Mårten Kongstad0eba72a2018-11-29 08:23:14 +0100239} // namespace android::idmap2