Add value parameterized test support for runtime tests
Usage is demonstrated in type_lookup_table_test.
Bug: 10245322
Change-Id: Ife6eb1ed57cb12edecce9ef101215ff15ae032e1
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 2184f0a..e89c5af 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -117,14 +117,15 @@
static bool unstarted_initialized_ = false;
-CommonRuntimeTest::CommonRuntimeTest() {}
-CommonRuntimeTest::~CommonRuntimeTest() {
+CommonRuntimeTestImpl::CommonRuntimeTestImpl() {}
+
+CommonRuntimeTestImpl::~CommonRuntimeTestImpl() {
// Ensure the dex files are cleaned up before the runtime.
loaded_dex_files_.clear();
runtime_.reset();
}
-void CommonRuntimeTest::SetUpAndroidRoot() {
+void CommonRuntimeTestImpl::SetUpAndroidRoot() {
if (IsHost()) {
// $ANDROID_ROOT is set on the device, but not necessarily on the host.
// But it needs to be set so that icu4c can find its locale data.
@@ -166,7 +167,7 @@
}
}
-void CommonRuntimeTest::SetUpAndroidData(std::string& android_data) {
+void CommonRuntimeTestImpl::SetUpAndroidData(std::string& android_data) {
// On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
if (IsHost()) {
const char* tmpdir = getenv("TMPDIR");
@@ -185,7 +186,8 @@
setenv("ANDROID_DATA", android_data.c_str(), 1);
}
-void CommonRuntimeTest::TearDownAndroidData(const std::string& android_data, bool fail_on_error) {
+void CommonRuntimeTestImpl::TearDownAndroidData(const std::string& android_data,
+ bool fail_on_error) {
if (fail_on_error) {
ASSERT_EQ(rmdir(android_data.c_str()), 0);
} else {
@@ -235,13 +237,13 @@
return founddir;
}
-std::string CommonRuntimeTest::GetAndroidHostToolsDir() {
+std::string CommonRuntimeTestImpl::GetAndroidHostToolsDir() {
return GetAndroidToolsDir("prebuilts/gcc/linux-x86/host",
"x86_64-linux-glibc2.15",
"x86_64-linux");
}
-std::string CommonRuntimeTest::GetAndroidTargetToolsDir(InstructionSet isa) {
+std::string CommonRuntimeTestImpl::GetAndroidTargetToolsDir(InstructionSet isa) {
switch (isa) {
case kArm:
case kThumb2:
@@ -269,15 +271,16 @@
return "";
}
-std::string CommonRuntimeTest::GetCoreArtLocation() {
+std::string CommonRuntimeTestImpl::GetCoreArtLocation() {
return GetCoreFileLocation("art");
}
-std::string CommonRuntimeTest::GetCoreOatLocation() {
+std::string CommonRuntimeTestImpl::GetCoreOatLocation() {
return GetCoreFileLocation("oat");
}
-std::unique_ptr<const DexFile> CommonRuntimeTest::LoadExpectSingleDexFile(const char* location) {
+std::unique_ptr<const DexFile> CommonRuntimeTestImpl::LoadExpectSingleDexFile(
+ const char* location) {
std::vector<std::unique_ptr<const DexFile>> dex_files;
std::string error_msg;
MemMap::Init();
@@ -290,7 +293,7 @@
}
}
-void CommonRuntimeTest::SetUp() {
+void CommonRuntimeTestImpl::SetUp() {
SetUpAndroidRoot();
SetUpAndroidData(android_data_);
dalvik_cache_.append(android_data_.c_str());
@@ -345,7 +348,7 @@
FinalizeSetup();
}
-void CommonRuntimeTest::FinalizeSetup() {
+void CommonRuntimeTestImpl::FinalizeSetup() {
// Initialize maps for unstarted runtime. This needs to be here, as running clinits needs this
// set up.
if (!unstarted_initialized_) {
@@ -369,7 +372,7 @@
runtime_->GetHeap()->SetMinIntervalHomogeneousSpaceCompactionByOom(0U);
}
-void CommonRuntimeTest::ClearDirectory(const char* dirpath) {
+void CommonRuntimeTestImpl::ClearDirectory(const char* dirpath) {
ASSERT_TRUE(dirpath != nullptr);
DIR* dir = opendir(dirpath);
ASSERT_TRUE(dir != nullptr);
@@ -396,7 +399,7 @@
closedir(dir);
}
-void CommonRuntimeTest::TearDown() {
+void CommonRuntimeTestImpl::TearDown() {
const char* android_data = getenv("ANDROID_DATA");
ASSERT_TRUE(android_data != nullptr);
ClearDirectory(dalvik_cache_.c_str());
@@ -453,12 +456,12 @@
return StringPrintf("%s/framework/%s%s.jar", path.c_str(), jar_prefix.c_str(), suffix.c_str());
}
-std::vector<std::string> CommonRuntimeTest::GetLibCoreDexFileNames() {
+std::vector<std::string> CommonRuntimeTestImpl::GetLibCoreDexFileNames() {
return std::vector<std::string>({GetDexFileName("core-oj", IsHost()),
GetDexFileName("core-libart", IsHost())});
}
-std::string CommonRuntimeTest::GetTestAndroidRoot() {
+std::string CommonRuntimeTestImpl::GetTestAndroidRoot() {
if (IsHost()) {
const char* host_dir = getenv("ANDROID_HOST_OUT");
CHECK(host_dir != nullptr);
@@ -478,7 +481,7 @@
#define ART_TARGET_NATIVETEST_DIR_STRING ""
#endif
-std::string CommonRuntimeTest::GetTestDexFileName(const char* name) {
+std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) {
CHECK(name != nullptr);
std::string filename;
if (IsHost()) {
@@ -493,7 +496,8 @@
return filename;
}
-std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTest::OpenTestDexFiles(const char* name) {
+std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTestImpl::OpenTestDexFiles(
+ const char* name) {
std::string filename = GetTestDexFileName(name);
std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
@@ -506,13 +510,13 @@
return dex_files;
}
-std::unique_ptr<const DexFile> CommonRuntimeTest::OpenTestDexFile(const char* name) {
+std::unique_ptr<const DexFile> CommonRuntimeTestImpl::OpenTestDexFile(const char* name) {
std::vector<std::unique_ptr<const DexFile>> vector = OpenTestDexFiles(name);
EXPECT_EQ(1U, vector.size());
return std::move(vector[0]);
}
-std::vector<const DexFile*> CommonRuntimeTest::GetDexFiles(jobject jclass_loader) {
+std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(jobject jclass_loader) {
std::vector<const DexFile*> ret;
ScopedObjectAccess soa(Thread::Current());
@@ -572,7 +576,7 @@
return ret;
}
-const DexFile* CommonRuntimeTest::GetFirstDexFile(jobject jclass_loader) {
+const DexFile* CommonRuntimeTestImpl::GetFirstDexFile(jobject jclass_loader) {
std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
DCHECK(!tmp.empty());
const DexFile* ret = tmp[0];
@@ -580,7 +584,7 @@
return ret;
}
-jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
+jobject CommonRuntimeTestImpl::LoadDex(const char* dex_name) {
std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name);
std::vector<const DexFile*> class_path;
CHECK_NE(0U, dex_files.size());
@@ -596,7 +600,7 @@
return class_loader;
}
-std::string CommonRuntimeTest::GetCoreFileLocation(const char* suffix) {
+std::string CommonRuntimeTestImpl::GetCoreFileLocation(const char* suffix) {
CHECK(suffix != nullptr);
std::string location;
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 7223b6e..0ce40e8 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -64,8 +64,10 @@
std::unique_ptr<File> file_;
};
-class CommonRuntimeTest : public testing::Test {
+class CommonRuntimeTestImpl {
public:
+ CommonRuntimeTestImpl();
+ virtual ~CommonRuntimeTestImpl();
static void SetUpAndroidRoot();
// Note: setting up ANDROID_DATA may create a temporary directory. If this is used in a
@@ -74,19 +76,25 @@
static void TearDownAndroidData(const std::string& android_data, bool fail_on_error);
- CommonRuntimeTest();
- ~CommonRuntimeTest();
-
// Gets the paths of the libcore dex files.
static std::vector<std::string> GetLibCoreDexFileNames();
// Returns bin directory which contains host's prebuild tools.
static std::string GetAndroidHostToolsDir();
- // Returns bin directory which contains target's prebuild tools.
+ // Returns bin directory wahich contains target's prebuild tools.
static std::string GetAndroidTargetToolsDir(InstructionSet isa);
protected:
+ // Allow subclases such as CommonCompilerTest to add extra options.
+ virtual void SetUpRuntimeOptions(RuntimeOptions* options ATTRIBUTE_UNUSED) {}
+
+ // Called before the runtime is created.
+ virtual void PreRuntimeCreate() {}
+
+ // Called after the runtime is created.
+ virtual void PostRuntimeCreate() {}
+
static bool IsHost() {
return !kIsTargetBuild;
}
@@ -99,25 +107,8 @@
std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
- virtual void SetUp();
-
- // Allow subclases such as CommonCompilerTest to add extra options.
- virtual void SetUpRuntimeOptions(RuntimeOptions* options ATTRIBUTE_UNUSED) {}
-
void ClearDirectory(const char* dirpath);
- virtual void TearDown();
-
- // Called before the runtime is created.
- virtual void PreRuntimeCreate() {}
-
- // Called after the runtime is created.
- virtual void PostRuntimeCreate() {}
-
- // Called to finish up runtime creation and filling test fields. By default runs root
- // initializers, initialize well-known classes, and creates the heap thread pool.
- virtual void FinalizeSetup();
-
std::string GetTestAndroidRoot();
std::string GetTestDexFileName(const char* name);
@@ -150,12 +141,45 @@
std::unique_ptr<CompilerCallbacks> callbacks_;
+ void SetUp();
+
+ void TearDown();
+
+ void FinalizeSetup();
+
private:
static std::string GetCoreFileLocation(const char* suffix);
std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
};
+template <typename TestType>
+class CommonRuntimeTestBase : public TestType, public CommonRuntimeTestImpl {
+ public:
+ CommonRuntimeTestBase() {}
+ virtual ~CommonRuntimeTestBase() {}
+
+ protected:
+ virtual void SetUp() {
+ CommonRuntimeTestImpl::SetUp();
+ }
+
+ virtual void TearDown() {
+ CommonRuntimeTestImpl::TearDown();
+ }
+
+ // Called to finish up runtime creation and filling test fields. By default runs root
+ // initializers, initialize well-known classes, and creates the heap thread pool.
+ virtual void FinalizeSetup() {
+ CommonRuntimeTestImpl::FinalizeSetup();
+ }
+};
+
+using CommonRuntimeTest = CommonRuntimeTestBase<testing::Test>;
+
+template <typename Param>
+using CommonRuntimeTestWithParam = CommonRuntimeTestBase<testing::TestWithParam<Param>>;
+
// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on
// rather than aborting, so be careful!
class CheckJniAbortCatcher {
diff --git a/runtime/type_lookup_table_test.cc b/runtime/type_lookup_table_test.cc
index 7f500cc..ea4d8b5 100644
--- a/runtime/type_lookup_table_test.cc
+++ b/runtime/type_lookup_table_test.cc
@@ -25,10 +25,10 @@
namespace art {
-class TypeLookupTableTest : public CommonRuntimeTest {
- public:
- size_t kDexNoIndex = DexFile::kDexNoIndex; // Make copy to prevent linking errors.
-};
+static const size_t kDexNoIndex = DexFile::kDexNoIndex; // Make copy to prevent linking errors.
+
+using DescriptorClassDefIdxPair = std::pair<const char*, uint32_t>;
+class TypeLookupTableTest : public CommonRuntimeTestWithParam<DescriptorClassDefIdxPair> {};
TEST_F(TypeLookupTableTest, CreateLookupTable) {
ScopedObjectAccess soa(Thread::Current());
@@ -39,48 +39,28 @@
ASSERT_EQ(32U, table->RawDataLength());
}
-TEST_F(TypeLookupTableTest, FindNonExistingClassWithoutCollisions) {
+TEST_P(TypeLookupTableTest, Find) {
ScopedObjectAccess soa(Thread::Current());
std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup"));
std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file));
ASSERT_NE(nullptr, table.get());
- const char* descriptor = "LBA;";
+ auto pair = GetParam();
+ const char* descriptor = pair.first;
size_t hash = ComputeModifiedUtf8Hash(descriptor);
uint32_t class_def_idx = table->Lookup(descriptor, hash);
- ASSERT_EQ(kDexNoIndex, class_def_idx);
+ ASSERT_EQ(pair.second, class_def_idx);
}
-TEST_F(TypeLookupTableTest, FindNonExistingClassWithCollisions) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup"));
- std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file));
- ASSERT_NE(nullptr, table.get());
- const char* descriptor = "LDA;";
- size_t hash = ComputeModifiedUtf8Hash(descriptor);
- uint32_t class_def_idx = table->Lookup(descriptor, hash);
- ASSERT_EQ(kDexNoIndex, class_def_idx);
-}
-
-TEST_F(TypeLookupTableTest, FindClassNoCollisions) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup"));
- std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file));
- ASSERT_NE(nullptr, table.get());
- const char* descriptor = "LC;";
- size_t hash = ComputeModifiedUtf8Hash(descriptor);
- uint32_t class_def_idx = table->Lookup(descriptor, hash);
- ASSERT_EQ(2U, class_def_idx);
-}
-
-TEST_F(TypeLookupTableTest, FindClassWithCollisions) {
- ScopedObjectAccess soa(Thread::Current());
- std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Lookup"));
- std::unique_ptr<TypeLookupTable> table(TypeLookupTable::Create(*dex_file));
- ASSERT_NE(nullptr, table.get());
- const char* descriptor = "LAB;";
- size_t hash = ComputeModifiedUtf8Hash(descriptor);
- uint32_t class_def_idx = table->Lookup(descriptor, hash);
- ASSERT_EQ(1U, class_def_idx);
-}
-
+INSTANTIATE_TEST_CASE_P(FindNonExistingClassWithoutCollisions,
+ TypeLookupTableTest,
+ testing::Values(DescriptorClassDefIdxPair("LAB;", 1U)));
+INSTANTIATE_TEST_CASE_P(FindNonExistingClassWithCollisions,
+ TypeLookupTableTest,
+ testing::Values(DescriptorClassDefIdxPair("LDA;", kDexNoIndex)));
+INSTANTIATE_TEST_CASE_P(FindClassNoCollisions,
+ TypeLookupTableTest,
+ testing::Values(DescriptorClassDefIdxPair("LC;", 2U)));
+INSTANTIATE_TEST_CASE_P(FindClassWithCollisions,
+ TypeLookupTableTest,
+ testing::Values(DescriptorClassDefIdxPair("LAB;", 1U)));
} // namespace art