blob: 66dd51ecb4fbd3eb2ef56c866f64e4e1c9a622fe [file] [log] [blame]
/**
* 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