Don't spin up the ART runtime in art_standalone_dex2oat_cts_tests.
It was mistakenly based on CommonRuntimeTest, which starts a runtime
through unstable APIs. The test should only run dex2oat with minimal
arguments to make --force-palette-compilation-hooks work.
Some refactoring in Dex2oatEnvironmentTest and CommonArtTest to
separate out the scratch directory creation code.
Test: atest Dex2oatCtsTest
Check with temporary logging in
system/libartpalette/palette_android_partner.cc that
PaletteNotify(Start|End)Dex2oatCompilation still gets called.
Bug: 253937792
Change-Id: Ieaea0faeef9571c0a269d565acd105d0f74f3d13
diff --git a/dex2oat/dex2oat_cts_test.cc b/dex2oat/dex2oat_cts_test.cc
index 41c7015..2541264 100644
--- a/dex2oat/dex2oat_cts_test.cc
+++ b/dex2oat/dex2oat_cts_test.cc
@@ -14,11 +14,54 @@
* limitations under the License.
*/
+#include "base/file_utils.h"
#include "dex2oat_environment_test.h"
namespace art {
-class Dex2oatCtsTest : public Dex2oatEnvironmentTest {};
+class Dex2oatCtsTest : public CommonArtTest, public Dex2oatScratchDirs {
+ public:
+ void SetUp() override {
+ CommonArtTest::SetUp();
+ Dex2oatScratchDirs::SetUp(android_data_);
+ }
+
+ void TearDown() override {
+ Dex2oatScratchDirs::TearDown();
+ CommonArtTest::TearDown();
+ }
+
+ protected:
+ // Stripped down counterpart to Dex2oatEnvironmentTest::Dex2Oat that only adds
+ // enough arguments for our purposes.
+ int Dex2Oat(const std::vector<std::string>& dex2oat_args,
+ std::string* output,
+ std::string* error_msg) {
+ // This command line should work regardless of bitness, ISA, etc.
+ std::vector<std::string> argv = {std::string(kAndroidArtApexDefaultPath) + "/bin/dex2oat"};
+ argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
+
+ // We must set --android-root.
+ const char* android_root = getenv("ANDROID_ROOT");
+ CHECK(android_root != nullptr);
+ argv.push_back("--android-root=" + std::string(android_root));
+
+ // We need dex2oat to actually log things.
+ auto post_fork_fn = []() { return setenv("ANDROID_LOG_TAGS", "*:d", 1) == 0; };
+ ForkAndExecResult res = ForkAndExec(argv, post_fork_fn, output);
+ if (res.stage != ForkAndExecResult::kFinished) {
+ *error_msg = strerror(errno);
+ ::testing::AssertionFailure() << "Failed to finish dex2oat invocation: " << *error_msg;
+ }
+
+ if (!res.StandardSuccess()) {
+ // We cannot use ASSERT_TRUE since the method returns an int and not void.
+ ::testing::AssertionFailure() << "dex2oat fork/exec failed: " << *error_msg;
+ }
+
+ return res.status_code;
+ }
+};
// Run dex2oat with --enable-palette-compilation-hooks to force calls to
// PaletteNotify{Start,End}Dex2oatCompilation.
diff --git a/libartbase/base/common_art_test.h b/libartbase/base/common_art_test.h
index fccb217..f4935cc 100644
--- a/libartbase/base/common_art_test.h
+++ b/libartbase/base/common_art_test.h
@@ -146,6 +146,8 @@
static void TearDownAndroidDataDir(const std::string& android_data, bool fail_on_error);
+ static void ClearDirectory(const char* dirpath, bool recursive = true);
+
// Get the names of the libcore modules.
virtual std::vector<std::string> GetLibCoreModuleNames() const;
@@ -238,8 +240,6 @@
std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
- void ClearDirectory(const char* dirpath, bool recursive = true);
-
// Open a file (allows reading of framework jars).
std::vector<std::unique_ptr<const DexFile>> OpenDexFiles(const char* filename);
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
index 166464f..9ebc68d 100644
--- a/runtime/dex2oat_environment_test.h
+++ b/runtime/dex2oat_environment_test.h
@@ -41,21 +41,17 @@
static constexpr bool kDebugArgs = false;
-// Test class that provides some helpers to set a test up for compilation using dex2oat.
-class Dex2oatEnvironmentTest : public CommonRuntimeTest {
+class Dex2oatScratchDirs {
public:
- void SetUp() override {
- CommonRuntimeTest::SetUp();
- const ArtDexFileLoader dex_file_loader;
-
+ void SetUp(const std::string& android_data) {
// Create a scratch directory to work from.
// Get the realpath of the android data. The oat dir should always point to real location
// when generating oat files in dalvik-cache. This avoids complicating the unit tests
// when matching the expected paths.
- UniqueCPtr<const char[]> android_data_real(realpath(android_data_.c_str(), nullptr));
+ UniqueCPtr<const char[]> android_data_real(realpath(android_data.c_str(), nullptr));
ASSERT_TRUE(android_data_real != nullptr)
- << "Could not get the realpath of the android data" << android_data_ << strerror(errno);
+ << "Could not get the realpath of the android data" << android_data << strerror(errno);
scratch_dir_.assign(android_data_real.get());
scratch_dir_ += "/Dex2oatEnvironmentTest";
@@ -67,6 +63,41 @@
odex_dir_ = odex_oat_dir_ + "/" + std::string(GetInstructionSetString(kRuntimeISA));
ASSERT_EQ(0, mkdir(odex_dir_.c_str(), 0700));
+ }
+
+ void TearDown() {
+ CommonArtTest::ClearDirectory(odex_dir_.c_str());
+ ASSERT_EQ(0, rmdir(odex_dir_.c_str()));
+
+ CommonArtTest::ClearDirectory(odex_oat_dir_.c_str());
+ ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str()));
+
+ CommonArtTest::ClearDirectory(scratch_dir_.c_str());
+ ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
+ }
+
+ // Scratch directory, for dex and odex files (oat files will go in the
+ // dalvik cache).
+ const std::string& GetScratchDir() const { return scratch_dir_; }
+
+ // Odex directory is the subdirectory in the scratch directory where odex
+ // files should be located.
+ const std::string& GetOdexDir() const { return odex_dir_; }
+
+ private:
+ std::string scratch_dir_;
+ std::string odex_oat_dir_;
+ std::string odex_dir_;
+};
+
+// Test class that provides some helpers to set a test up for compilation using dex2oat.
+class Dex2oatEnvironmentTest : public Dex2oatScratchDirs, public CommonRuntimeTest {
+ public:
+ void SetUp() override {
+ CommonRuntimeTest::SetUp();
+ Dex2oatScratchDirs::SetUp(android_data_);
+
+ const ArtDexFileLoader dex_file_loader;
// Verify the environment is as we expect
std::vector<uint32_t> checksums;
@@ -122,15 +153,7 @@
}
void TearDown() override {
- ClearDirectory(odex_dir_.c_str());
- ASSERT_EQ(0, rmdir(odex_dir_.c_str()));
-
- ClearDirectory(odex_oat_dir_.c_str());
- ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str()));
-
- ClearDirectory(scratch_dir_.c_str());
- ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
-
+ Dex2oatScratchDirs::TearDown();
CommonRuntimeTest::TearDown();
}
@@ -165,18 +188,6 @@
return GetTestDexFileName("Nested");
}
- // Scratch directory, for dex and odex files (oat files will go in the
- // dalvik cache).
- const std::string& GetScratchDir() const {
- return scratch_dir_;
- }
-
- // Odex directory is the subdirectory in the scratch directory where odex
- // files should be located.
- const std::string& GetOdexDir() const {
- return odex_dir_;
- }
-
int Dex2Oat(const std::vector<std::string>& dex2oat_args,
std::string* output,
std::string* error_msg) {
@@ -249,11 +260,6 @@
fflush(file);
fclose(file);
}
-
- private:
- std::string scratch_dir_;
- std::string odex_oat_dir_;
- std::string odex_dir_;
};
} // namespace art