/*
* Copyright (C) 2011 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 "parsed_options.h"
#include <memory>
#include "arch/instruction_set.h"
#include "base/common_art_test.h"
namespace art {
class ParsedOptionsTest : public CommonArtTest {
public:
static void SetUpTestCase() {
CommonArtTest::SetUpAndroidRootEnvVars();
}
};
TEST_F(ParsedOptionsTest, ParsedOptions) {
void* test_vfprintf = reinterpret_cast<void*>(0xa);
void* test_abort = reinterpret_cast<void*>(0xb);
void* test_exit = reinterpret_cast<void*>(0xc);
std::string boot_class_path;
std::string class_path;
boot_class_path += "-Xbootclasspath:";
bool first_dex_file = true;
for (const std::string& dex_file_name : GetLibCoreDexFileNames()) {
if (!first_dex_file) {
class_path += ":";
} else {
first_dex_file = false;
}
class_path += dex_file_name;
}
boot_class_path += class_path;
std::vector<std::string> expected_boot_class_path;
Split(class_path, ':', &expected_boot_class_path);
RuntimeOptions options;
options.push_back(std::make_pair(boot_class_path.c_str(), nullptr));
options.push_back(std::make_pair("-classpath", nullptr));
options.push_back(std::make_pair(class_path.c_str(), nullptr));
options.push_back(std::make_pair("-cp", nullptr));
options.push_back(std::make_pair(class_path.c_str(), nullptr));
options.push_back(std::make_pair("-Ximage:boot_image", nullptr));
options.push_back(std::make_pair("-Xcheck:jni", nullptr));
options.push_back(std::make_pair("-Xms2048", nullptr));
options.push_back(std::make_pair("-Xmx4k", nullptr));
options.push_back(std::make_pair("-Xss1m", nullptr));
options.push_back(std::make_pair("-XX:HeapTargetUtilization=0.75", nullptr));
options.push_back(std::make_pair("-Dfoo=bar", nullptr));
options.push_back(std::make_pair("-Dbaz=qux", nullptr));
options.push_back(std::make_pair("-verbose:gc,class,jni", nullptr));
options.push_back(std::make_pair("vfprintf", test_vfprintf));
options.push_back(std::make_pair("abort", test_abort));
options.push_back(std::make_pair("exit", test_exit));
RuntimeArgumentMap map;
bool parsed = ParsedOptions::Parse(options, false, &map);
ASSERT_TRUE(parsed);
ASSERT_NE(0u, map.Size());
using Opt = RuntimeArgumentMap;
#define EXPECT_PARSED_EQ(expected, actual_key) EXPECT_EQ(expected, map.GetOrDefault(actual_key))
#define EXPECT_PARSED_EQ_AS_STRING_VECTOR(expected, actual_key) \
EXPECT_EQ(expected, static_cast<std::vector<std::string>>(map.GetOrDefault(actual_key)))
#define EXPECT_PARSED_EXISTS(actual_key) EXPECT_TRUE(map.Exists(actual_key))
EXPECT_PARSED_EQ_AS_STRING_VECTOR(expected_boot_class_path, Opt::BootClassPath);
EXPECT_PARSED_EQ(class_path, Opt::ClassPath);
EXPECT_PARSED_EQ(std::string("boot_image"), Opt::Image);
EXPECT_PARSED_EXISTS(Opt::CheckJni);
EXPECT_PARSED_EQ(2048U, Opt::MemoryInitialSize);
EXPECT_PARSED_EQ(4 * KB, Opt::MemoryMaximumSize);
EXPECT_PARSED_EQ(1 * MB, Opt::StackSize);
EXPECT_DOUBLE_EQ(0.75, map.GetOrDefault(Opt::HeapTargetUtilization));
EXPECT_TRUE(test_vfprintf == map.GetOrDefault(Opt::HookVfprintf));
EXPECT_TRUE(test_exit == map.GetOrDefault(Opt::HookExit));
EXPECT_TRUE(test_abort == map.GetOrDefault(Opt::HookAbort));
EXPECT_TRUE(VLOG_IS_ON(class_linker));
EXPECT_FALSE(VLOG_IS_ON(compiler));
EXPECT_FALSE(VLOG_IS_ON(heap));
EXPECT_TRUE(VLOG_IS_ON(gc));
EXPECT_FALSE(VLOG_IS_ON(jdwp));
EXPECT_TRUE(VLOG_IS_ON(jni));
EXPECT_FALSE(VLOG_IS_ON(monitor));
EXPECT_FALSE(VLOG_IS_ON(signals));
EXPECT_FALSE(VLOG_IS_ON(simulator));
EXPECT_FALSE(VLOG_IS_ON(startup));
EXPECT_FALSE(VLOG_IS_ON(third_party_jni));
EXPECT_FALSE(VLOG_IS_ON(threads));
auto&& properties_list = map.GetOrDefault(Opt::PropertiesList);
ASSERT_EQ(2U, properties_list.size());
EXPECT_EQ("foo=bar", properties_list[0]);
EXPECT_EQ("baz=qux", properties_list[1]);
}
TEST_F(ParsedOptionsTest, ParsedOptionsGc) {
RuntimeOptions options;
options.push_back(std::make_pair("-Xgc:SS", nullptr));
RuntimeArgumentMap map;
bool parsed = ParsedOptions::Parse(options, false, &map);
ASSERT_TRUE(parsed);
ASSERT_NE(0u, map.Size());
using Opt = RuntimeArgumentMap;
EXPECT_TRUE(map.Exists(Opt::GcOption));
XGcOption xgc = map.GetOrDefault(Opt::GcOption);
EXPECT_EQ(gc::kCollectorTypeSS, xgc.collector_type_);
}
TEST_F(ParsedOptionsTest, ParsedOptionsGenerationalCC) {
RuntimeOptions options;
options.push_back(std::make_pair("-Xgc:generational_cc", nullptr));
RuntimeArgumentMap map;
bool parsed = ParsedOptions::Parse(options, false, &map);
ASSERT_TRUE(parsed);
ASSERT_NE(0u, map.Size());
using Opt = RuntimeArgumentMap;
EXPECT_TRUE(map.Exists(Opt::GcOption));
XGcOption xgc = map.GetOrDefault(Opt::GcOption);
ASSERT_TRUE(xgc.generational_cc);
}
TEST_F(ParsedOptionsTest, ParsedOptionsInstructionSet) {
using Opt = RuntimeArgumentMap;
{
// Nothing set, should be kRuntimeISA.
RuntimeOptions options;
RuntimeArgumentMap map;
bool parsed = ParsedOptions::Parse(options, false, &map);
ASSERT_TRUE(parsed);
InstructionSet isa = map.GetOrDefault(Opt::ImageInstructionSet);
EXPECT_EQ(kRuntimeISA, isa);
}
const char* isa_strings[] = { "arm", "arm64", "x86", "x86_64", "mips", "mips64" };
InstructionSet ISAs[] = { InstructionSet::kArm,
InstructionSet::kArm64,
InstructionSet::kX86,
InstructionSet::kX86_64,
InstructionSet::kMips,
InstructionSet::kMips64 };
static_assert(arraysize(isa_strings) == arraysize(ISAs), "Need same amount.");
for (size_t i = 0; i < arraysize(isa_strings); ++i) {
RuntimeOptions options;
options.push_back(std::make_pair("imageinstructionset", isa_strings[i]));
RuntimeArgumentMap map;
bool parsed = ParsedOptions::Parse(options, false, &map);
ASSERT_TRUE(parsed);
InstructionSet isa = map.GetOrDefault(Opt::ImageInstructionSet);
EXPECT_EQ(ISAs[i], isa);
}
}
} // namespace art