| /* |
| * 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 |