| /** |
| * 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 <stdlib.h> |
| #include <string.h> |
| |
| #include <android-base/logging.h> |
| #include <gtest/gtest.h> |
| |
| #include "installd_constants.h" |
| #include "otapreopt_parameters.h" |
| |
| namespace android { |
| namespace installd { |
| |
| static bool ParseBool(const char* in) { |
| if (strcmp(in, "true") == 0) { |
| return true; |
| } |
| return false; |
| } |
| |
| static const char* ParseNull(const char* arg) { |
| return (strcmp(arg, "!") == 0) ? nullptr : arg; |
| } |
| |
| class OTAPreoptTest : public testing::Test { |
| protected: |
| virtual void SetUp() { |
| setenv("ANDROID_LOG_TAGS", "*:f", 1); |
| android::base::InitLogging(nullptr, android::base::StderrLogger); |
| } |
| |
| void verifyPackageParameters(const OTAPreoptParameters& params, |
| uint32_t version, |
| bool versioned, |
| const char** args) { |
| // otapreopt target-slot [version] dexopt {DEXOPT_PARAMETERS} |
| int i = 0; |
| if (version > 2 || (version == 2 && versioned)) { |
| i += 4; |
| } else { |
| i += 3; |
| } |
| ASSERT_STREQ(params.target_slot.c_str(), args[1]); |
| ASSERT_STREQ(params.apk_path, args[i++]); |
| ASSERT_EQ(params.uid, static_cast<uid_t>(atoi(args[i++]))); |
| ASSERT_STREQ(params.pkgName, args[i++]); |
| ASSERT_STREQ(params.instruction_set, args[i++]); |
| ASSERT_EQ(params.dexopt_needed, atoi(args[i++])); |
| ASSERT_STREQ(params.oat_dir, args[i++]); |
| const int dexopt_flags = atoi(args[i++]); |
| ASSERT_STREQ(params.compiler_filter, args[i++]); |
| ASSERT_STREQ(params.volume_uuid, ParseNull(args[i++])); |
| ASSERT_STREQ(params.shared_libraries, ParseNull(args[i++])); |
| if (version > 1) { |
| ASSERT_STREQ(params.se_info, ParseNull(args[i++])); |
| } else { |
| ASSERT_EQ(params.se_info, nullptr); |
| } |
| if (version > 2) { |
| ASSERT_EQ(params.downgrade, ParseBool(args[i++])); |
| } else { |
| ASSERT_FALSE(params.downgrade); |
| } |
| if (version > 3) { |
| ASSERT_EQ(params.target_sdk_version, atoi(args[i++])); |
| } else { |
| ASSERT_EQ(params.target_sdk_version, 0); |
| } |
| if (version > 4) { |
| ASSERT_STREQ(params.profile_name, ParseNull(args[i++])); |
| } else { |
| ASSERT_STREQ(params.profile_name, "primary.prof"); |
| } |
| if (version > 5) { |
| ASSERT_STREQ(params.dex_metadata_path, ParseNull(args[i++])); |
| } else { |
| ASSERT_EQ(params.dex_metadata_path, nullptr); |
| } |
| if (version > 6) { |
| ASSERT_STREQ(params.compilation_reason, ParseNull(args[i++])); |
| } else { |
| ASSERT_STREQ(params.compilation_reason, "ab-ota"); |
| } |
| if (version > 7) { |
| ASSERT_EQ(params.dexopt_flags, dexopt_flags); |
| } else { |
| ASSERT_EQ(params.dexopt_flags, dexopt_flags | DEXOPT_GENERATE_COMPACT_DEX); |
| } |
| } |
| |
| const char* getVersionCStr(uint32_t version) { |
| switch (version) { |
| case 1: return "1"; |
| case 2: return "2"; |
| case 3: return "3"; |
| case 4: return "4"; |
| case 5: return "5"; |
| case 6: return "6"; |
| case 7: return "7"; |
| case 8: return "8"; |
| case 9: return "9"; |
| case 10: return "10"; |
| } |
| return nullptr; |
| } |
| |
| std::vector<const char*> getArgs(uint32_t version, |
| bool versioned, |
| const char* shared_libs = "shared.lib") { |
| std::vector<const char*> args; |
| args.push_back("otapreopt"); // "otapreopt" |
| args.push_back("a"); // slot |
| if (versioned) { |
| args.push_back(getVersionCStr(version)); |
| } |
| args.push_back("dexopt"); // "dexopt" |
| args.push_back("foo.apk"); // apk_path |
| args.push_back("123"); // uid |
| args.push_back("pkgname"); // pkg |
| args.push_back("arm"); // isa |
| args.push_back("1"); // dexopt_needed (DEX2OAT_FROM_SCRATCH) |
| args.push_back("oat_dir"); // oat_dir |
| args.push_back("0"); // dexopt_flags |
| args.push_back("speed"); // filter |
| args.push_back("!"); // volume |
| args.push_back(shared_libs); // libs |
| |
| if (version > 1) { |
| args.push_back("!"); // seinfo |
| } |
| if (version > 2) { |
| args.push_back("true"); // downgrade |
| } |
| if (version > 3) { |
| args.push_back("28"); // sdk_version |
| } |
| if (version > 4) { |
| args.push_back("split_a.prof"); // profile_name |
| } |
| if (version > 5) { |
| args.push_back("dex_metadata.dm"); // dex_metadata_path |
| } |
| if (version > 6) { |
| args.push_back("ab-ota-test"); // compilation_reason |
| } |
| args.push_back(nullptr); // we have to end with null. |
| return args; |
| } |
| |
| void VerifyReadArguments(uint32_t version, |
| bool versioned, |
| const char* shared_libs = "shared.lib") { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(version, versioned, shared_libs); |
| ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data())); |
| verifyPackageParameters(params, version, versioned, args.data()); |
| } |
| }; |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV1) { |
| VerifyReadArguments(1, false); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV2Unversioned) { |
| VerifyReadArguments(2, false); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV2) { |
| VerifyReadArguments(2, true); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV3) { |
| VerifyReadArguments(3, true); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV4) { |
| VerifyReadArguments(4, true); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV5) { |
| VerifyReadArguments(5, true); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV6) { |
| VerifyReadArguments(6, true); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV7) { |
| VerifyReadArguments(7, true); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV9SharedLibsAmpersand) { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(9, true, "&"); |
| ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data())); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsV10SharedLibsAmpersand) { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(10, true, "&"); |
| ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data())); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(5, true); |
| args[2] = "3"; // pretend it's version 3. It should fail since there are too many args. |
| ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data())); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsFailInsufficientArgs) { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(4, true); |
| args[2] = "5"; // pretend it's version 5. It should fail since there are insufficient args. |
| ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data())); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidDexopt) { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(4, true); |
| args[3] = "dexopt-invalid"; |
| ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data())); |
| } |
| |
| TEST_F(OTAPreoptTest, ReadArgumentsFailInvalidSlot) { |
| OTAPreoptParameters params; |
| std::vector<const char*> args = getArgs(3, true); |
| args[1] = "invalid-slot???"; |
| ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data())); |
| } |
| |
| } // namespace installd |
| } // namespace android |