| /* | |
| * Copyright (C) 2018 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include <sys/mman.h> | |
| #include <sys/stat.h> | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
| #include <fstream> | |
| #include <memory> | |
| #include <sstream> | |
| #include <string> | |
| #include <vector> | |
| #include "TestHelpers.h" | |
| #include "android-base/file.h" | |
| #include "androidfw/ApkAssets.h" | |
| #include "androidfw/Idmap.h" | |
| #include "androidfw/LoadedArsc.h" | |
| #include "gmock/gmock.h" | |
| #include "gtest/gtest.h" | |
| #include "idmap2/CommandLineOptions.h" | |
| #include "idmap2/Idmap.h" | |
| namespace android::idmap2 { | |
| TEST(CommandLineOptionsTests, Flag) { | |
| bool foo = true; | |
| bool bar = false; | |
| CommandLineOptions opts = | |
| CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar); | |
| auto success = opts.Parse({"--foo", "--bar"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_TRUE(foo); | |
| ASSERT_TRUE(bar); | |
| foo = bar = false; | |
| success = opts.Parse({"--foo"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_TRUE(foo); | |
| ASSERT_FALSE(bar); | |
| } | |
| TEST(CommandLineOptionsTests, MandatoryOption) { | |
| std::string foo; | |
| std::string bar; | |
| CommandLineOptions opts = CommandLineOptions("test") | |
| .MandatoryOption("--foo", "", &foo) | |
| .MandatoryOption("--bar", "", &bar); | |
| auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo, "FOO"); | |
| ASSERT_EQ(bar, "BAR"); | |
| success = opts.Parse({"--foo"}); | |
| ASSERT_FALSE(success); | |
| } | |
| TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) { | |
| std::string foo; | |
| CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &foo); | |
| auto success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo, "SECOND"); | |
| } | |
| TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore) { | |
| std::vector<std::string> args; | |
| CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &args); | |
| auto success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(args.size(), 2U); | |
| ASSERT_EQ(args[0], "FOO"); | |
| ASSERT_EQ(args[1], "BAR"); | |
| } | |
| TEST(CommandLineOptionsTests, OptionalOption) { | |
| std::string foo; | |
| std::string bar; | |
| CommandLineOptions opts = CommandLineOptions("test") | |
| .OptionalOption("--foo", "", &foo) | |
| .OptionalOption("--bar", "", &bar); | |
| auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo, "FOO"); | |
| ASSERT_EQ(bar, "BAR"); | |
| success = opts.Parse({"--foo", "BAZ"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo, "BAZ"); | |
| success = opts.Parse({"--foo"}); | |
| ASSERT_FALSE(success); | |
| success = opts.Parse({"--foo", "--bar", "BAR"}); | |
| ASSERT_FALSE(success); | |
| success = opts.Parse({"--foo", "FOO", "--bar"}); | |
| ASSERT_FALSE(success); | |
| } | |
| TEST(CommandLineOptionsTests, OptionalOptionList) { | |
| std::vector<std::string> foo; | |
| std::vector<std::string> bar; | |
| CommandLineOptions opts = CommandLineOptions("test") | |
| .OptionalOption("--foo", "", &foo) | |
| .OptionalOption("--bar", "", &bar); | |
| auto success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo.size(), 1U); | |
| ASSERT_EQ(foo[0], "FOO"); | |
| ASSERT_EQ(bar.size(), 1U); | |
| ASSERT_EQ(bar[0], "BAR"); | |
| foo.clear(); | |
| bar.clear(); | |
| success = opts.Parse({"--foo", "BAZ"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo.size(), 1U); | |
| ASSERT_EQ(foo[0], "BAZ"); | |
| ASSERT_EQ(bar.size(), 0U); | |
| foo.clear(); | |
| bar.clear(); | |
| success = opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_EQ(foo.size(), 2U); | |
| ASSERT_EQ(foo[0], "BAZ"); | |
| ASSERT_EQ(foo[1], "BIZ"); | |
| ASSERT_EQ(bar.size(), 2U); | |
| ASSERT_EQ(bar[0], "FIZ"); | |
| ASSERT_EQ(bar[1], "FUZZ"); | |
| foo.clear(); | |
| bar.clear(); | |
| success = opts.Parse({"--foo"}); | |
| ASSERT_FALSE(success); | |
| foo.clear(); | |
| bar.clear(); | |
| success = opts.Parse({"--foo", "--bar", "BAR"}); | |
| ASSERT_FALSE(success); | |
| foo.clear(); | |
| bar.clear(); | |
| success = opts.Parse({"--foo", "FOO", "--bar"}); | |
| ASSERT_FALSE(success); | |
| } | |
| TEST(CommandLineOptionsTests, CornerCases) { | |
| std::string foo; | |
| std::string bar; | |
| bool baz = false; | |
| CommandLineOptions opts = CommandLineOptions("test") | |
| .MandatoryOption("--foo", "", &foo) | |
| .OptionalFlag("--baz", "", &baz) | |
| .OptionalOption("--bar", "", &bar); | |
| auto success = opts.Parse({"--unexpected"}); | |
| ASSERT_FALSE(success); | |
| success = opts.Parse({"--bar", "BAR"}); | |
| ASSERT_FALSE(success); | |
| success = opts.Parse({"--baz", "--foo", "FOO"}); | |
| ASSERT_TRUE(success); | |
| ASSERT_TRUE(baz); | |
| ASSERT_EQ(foo, "FOO"); | |
| } | |
| TEST(CommandLineOptionsTests, ConvertArgvToVector) { | |
| const char* argv[] = { | |
| "program-name", | |
| "--foo", | |
| "FOO", | |
| nullptr, | |
| }; | |
| std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(3, argv); | |
| ASSERT_EQ(v->size(), 2UL); | |
| ASSERT_EQ((*v)[0], "--foo"); | |
| ASSERT_EQ((*v)[1], "FOO"); | |
| } | |
| TEST(CommandLineOptionsTests, ConvertArgvToVectorNoArgs) { | |
| const char* argv[] = { | |
| "program-name", | |
| nullptr, | |
| }; | |
| std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(1, argv); | |
| ASSERT_EQ(v->size(), 0UL); | |
| } | |
| TEST(CommandLineOptionsTests, Usage) { | |
| std::string arg1; | |
| std::string arg2; | |
| std::string arg3; | |
| std::string arg4; | |
| bool arg5 = false; | |
| bool arg6 = false; | |
| std::vector<std::string> arg7; | |
| std::vector<std::string> arg8; | |
| CommandLineOptions opts = CommandLineOptions("test") | |
| .MandatoryOption("--aa", "description-aa", &arg1) | |
| .OptionalFlag("--bb", "description-bb", &arg5) | |
| .OptionalOption("--cc", "description-cc", &arg2) | |
| .OptionalOption("--dd", "description-dd", &arg3) | |
| .MandatoryOption("--ee", "description-ee", &arg4) | |
| .OptionalFlag("--ff", "description-ff", &arg6) | |
| .MandatoryOption("--gg", "description-gg", &arg7) | |
| .OptionalOption("--hh", "description-hh", &arg8); | |
| std::stringstream stream; | |
| opts.Usage(stream); | |
| const std::string s = stream.str(); | |
| ASSERT_NE(s.find("usage: test --aa arg [--bb] [--cc arg] [--dd arg] --ee arg [--ff] --gg arg " | |
| "[--gg arg [..]] [--hh arg [..]]"), | |
| std::string::npos); | |
| ASSERT_NE(s.find("--aa arg description-aa"), std::string::npos); | |
| ASSERT_NE(s.find("--ff description-ff"), std::string::npos); | |
| ASSERT_NE(s.find("--gg arg description-gg (can be provided multiple times)"), | |
| std::string::npos); | |
| } | |
| } // namespace android::idmap2 |