diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-01-10 18:43:23 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-01-10 18:43:23 +0000 |
commit | 020d24fd5bec32e81801b8853f6a354f38231ca1 (patch) | |
tree | 6804cfcf20e128b9aea4c8e8c23ed353bf179c95 | |
parent | 571ed3b561677201fb4594d7c3b5e84bc664ce58 (diff) | |
parent | 9a918fca32a0cfdf28372e15cac4ef9c63a2ae6e (diff) | |
download | art-aml_tz4_332714010.tar.gz |
Snap for 11293587 from 9a918fca32a0cfdf28372e15cac4ef9c63a2ae6e to mainline-tzdata4-releaseaml_tz4_332714070aml_tz4_332714050aml_tz4_332714010aml_tz4_332714010
Change-Id: I011f7774f4b0e83ed30d014369a94158103e75eb
-rw-r--r-- | dex2oat/Android.bp | 2 | ||||
-rw-r--r-- | dex2oat/dex2oat_cts_test.cc | 238 | ||||
-rw-r--r-- | libartpalette/Android.bp | 16 | ||||
-rw-r--r-- | libartpalette/apex/palette_test.cc | 6 | ||||
-rw-r--r-- | libdexfile/Android.bp | 7 | ||||
-rw-r--r-- | test/Android.bp | 37 | ||||
-rw-r--r-- | test/art-gtests-target-standalone-cts-template.xml | 2 |
7 files changed, 295 insertions, 13 deletions
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp index 941b9e0e95..d344d2d0a8 100644 --- a/dex2oat/Android.bp +++ b/dex2oat/Android.bp @@ -591,7 +591,7 @@ art_cc_test { // Counterpart to art_standalone_dex2oat_tests for tests that go into CTS. art_cc_test { name: "art_standalone_dex2oat_cts_tests", - defaults: ["art_standalone_gtest_defaults"], + defaults: ["art_cts_gtest_defaults"], srcs: ["dex2oat_cts_test.cc"], data: [ ":art-gtest-jars-Main", diff --git a/dex2oat/dex2oat_cts_test.cc b/dex2oat/dex2oat_cts_test.cc index 254126446d..25cd94bb93 100644 --- a/dex2oat/dex2oat_cts_test.cc +++ b/dex2oat/dex2oat_cts_test.cc @@ -14,24 +14,252 @@ * limitations under the License. */ +#include <dirent.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <fstream> +#include <functional> +#include <memory> +#include <string> +#include <vector> + +#include "android-base/file.h" +#include "android-base/unique_fd.h" #include "base/file_utils.h" -#include "dex2oat_environment_test.h" +#include "base/os.h" +#include "base/stl_util.h" +#include "base/unix_file/fd_file.h" +#include "gtest/gtest.h" namespace art { +namespace { + +void ClearDirectory(const char* dirpath, bool recursive = true) { + ASSERT_TRUE(dirpath != nullptr); + DIR* dir = opendir(dirpath); + ASSERT_TRUE(dir != nullptr); + dirent* e; + struct stat s; + while ((e = readdir(dir)) != nullptr) { + if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) { + continue; + } + std::string filename(dirpath); + filename.push_back('/'); + filename.append(e->d_name); + int stat_result = lstat(filename.c_str(), &s); + ASSERT_EQ(0, stat_result) << "unable to stat " << filename; + if (S_ISDIR(s.st_mode)) { + if (recursive) { + ClearDirectory(filename.c_str()); + int rmdir_result = rmdir(filename.c_str()); + ASSERT_EQ(0, rmdir_result) << filename; + } + } else { + int unlink_result = unlink(filename.c_str()); + ASSERT_EQ(0, unlink_result) << filename; + } + } + closedir(dir); +} + +class Dex2oatScratchDirs { + public: + 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)); + ASSERT_TRUE(android_data_real != nullptr) + << "Could not get the realpath of the android data" << android_data << strerror(errno); + + scratch_dir_.assign(android_data_real.get()); + scratch_dir_ += "/Dex2oatEnvironmentTest"; + ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700)); + + // Create a subdirectory in scratch for odex files. + odex_oat_dir_ = scratch_dir_ + "/oat"; + ASSERT_EQ(0, mkdir(odex_oat_dir_.c_str(), 0700)); + + odex_dir_ = odex_oat_dir_ + "/" + std::string(GetInstructionSetString(kRuntimeISA)); + ASSERT_EQ(0, mkdir(odex_dir_.c_str(), 0700)); + } + + void TearDown() { + ClearDirectory(odex_dir_.c_str()); + ASSERT_EQ(0, rmdir(odex_dir_.c_str())); -class Dex2oatCtsTest : public CommonArtTest, public Dex2oatScratchDirs { + 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())); + } + + // 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_; +}; + +class Dex2oatCtsTest : public Dex2oatScratchDirs, public testing::Test { public: + void SetUpAndroidDataDir(std::string& android_data) { + android_data = "/data/local/tmp"; + android_data += "/art-data-XXXXXX"; + if (mkdtemp(&android_data[0]) == nullptr) { + PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed"; + } + setenv("ANDROID_DATA", android_data.c_str(), 1); + } + + void TearDownAndroidDataDir(const std::string& android_data, + bool fail_on_error) { + if (fail_on_error) { + ASSERT_EQ(rmdir(android_data.c_str()), 0); + } else { + rmdir(android_data.c_str()); + } + } + + std::string GetTestDexFileName(const char* name) const { + CHECK(name != nullptr); + // The needed jar files for gtest are located next to the gtest binary itself. + std::string executable_dir = android::base::GetExecutableDirectory(); + for (auto ext : {".jar", ".dex"}) { + std::string path = executable_dir + "/art-gtest-jars-" + name + ext; + if (OS::FileExists(path.c_str())) { + return path; + } + } + LOG(FATAL) << "Test file " << name << " not found"; + UNREACHABLE(); + } + void SetUp() override { - CommonArtTest::SetUp(); + SetUpAndroidDataDir(android_data_); Dex2oatScratchDirs::SetUp(android_data_); } void TearDown() override { Dex2oatScratchDirs::TearDown(); - CommonArtTest::TearDown(); + TearDownAndroidDataDir(android_data_, true); + } + + struct ForkAndExecResult { + enum Stage { + kLink, + kFork, + kWaitpid, + kFinished, + }; + Stage stage; + int status_code; + + bool StandardSuccess() { + return stage == kFinished && WIFEXITED(status_code) && WEXITSTATUS(status_code) == 0; + } + }; + using OutputHandlerFn = std::function<void(char*, size_t)>; + using PostForkFn = std::function<bool()>; + + ForkAndExecResult ForkAndExec( + const std::vector<std::string>& argv, + const PostForkFn& post_fork, + const OutputHandlerFn& handler) { + ForkAndExecResult result; + result.status_code = 0; + result.stage = ForkAndExecResult::kLink; + + std::vector<const char*> c_args; + c_args.reserve(argv.size() + 1); + for (const std::string& str : argv) { + c_args.push_back(str.c_str()); + } + c_args.push_back(nullptr); + + android::base::unique_fd link[2]; + { + int link_fd[2]; + + if (pipe(link_fd) == -1) { + return result; + } + link[0].reset(link_fd[0]); + link[1].reset(link_fd[1]); + } + + result.stage = ForkAndExecResult::kFork; + + pid_t pid = fork(); + if (pid == -1) { + return result; + } + + if (pid == 0) { + if (!post_fork()) { + LOG(ERROR) << "Failed post-fork function"; + exit(1); + UNREACHABLE(); + } + + // Redirect stdout and stderr. + dup2(link[1].get(), STDOUT_FILENO); + dup2(link[1].get(), STDERR_FILENO); + + link[0].reset(); + link[1].reset(); + + execv(c_args[0], const_cast<char* const*>(c_args.data())); + exit(1); + UNREACHABLE(); + } + + result.stage = ForkAndExecResult::kWaitpid; + link[1].reset(); + + char buffer[128] = { 0 }; + ssize_t bytes_read = 0; + while (TEMP_FAILURE_RETRY(bytes_read = read(link[0].get(), buffer, 128)) > 0) { + handler(buffer, bytes_read); + } + handler(buffer, 0u); // End with a virtual write of zero length to simplify clients. + + link[0].reset(); + + if (waitpid(pid, &result.status_code, 0) == -1) { + return result; + } + + result.stage = ForkAndExecResult::kFinished; + return result; + } + + ForkAndExecResult ForkAndExec( + const std::vector<std::string>& argv, const PostForkFn& post_fork, std::string* output) { + auto string_collect_fn = [output](char* buf, size_t len) { + *output += std::string(buf, len); + }; + return ForkAndExec(argv, post_fork, string_collect_fn); } protected: + std::string android_data_; + // Stripped down counterpart to Dex2oatEnvironmentTest::Dex2Oat that only adds // enough arguments for our purposes. int Dex2Oat(const std::vector<std::string>& dex2oat_args, @@ -63,6 +291,8 @@ class Dex2oatCtsTest : public CommonArtTest, public Dex2oatScratchDirs { } }; +} // namespace + // Run dex2oat with --enable-palette-compilation-hooks to force calls to // PaletteNotify{Start,End}Dex2oatCompilation. TEST_F(Dex2oatCtsTest, CompilationHooks) { diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp index 37464f0832..773e7c16ed 100644 --- a/libartpalette/Android.bp +++ b/libartpalette/Android.bp @@ -111,10 +111,6 @@ art_cc_library { art_cc_defaults { name: "art_libartpalette_tests_defaults", srcs: ["apex/palette_test.cc"], - shared_libs: [ - "libartpalette", - "libnativehelper", - ], } // Version of ART gtest `art_libartpalette_tests` bundled with the ART APEX on target. @@ -125,6 +121,10 @@ art_cc_test { "art_gtest_defaults", "art_libartpalette_tests_defaults", ], + shared_libs: [ + "libartpalette", + "libnativehelper", + ], host_supported: true, } @@ -133,9 +133,15 @@ art_cc_test { art_cc_test { name: "art_standalone_libartpalette_tests", defaults: [ - "art_standalone_gtest_defaults", + "art_cts_gtest_defaults", "art_libartpalette_tests_defaults", ], + static_libs: [ + "libartpalette", + // libnativehelper_lazy has the glue we need to dlsym the platform-only + // APIs we need, like JniInvocationInit. + "libnativehelper_lazy", + ], test_config_template: ":art-gtests-target-standalone-cts-template", test_suites: ["cts"], } diff --git a/libartpalette/apex/palette_test.cc b/libartpalette/apex/palette_test.cc index 0bcc09329b..16f283872b 100644 --- a/libartpalette/apex/palette_test.cc +++ b/libartpalette/apex/palette_test.cc @@ -22,6 +22,7 @@ #include <unistd.h> #include "gtest/gtest.h" +#include "nativehelper/JniInvocation.h" \ namespace { @@ -78,6 +79,11 @@ TEST_F(PaletteClientTest, JniInvocation) { bool enabled; EXPECT_EQ(PALETTE_STATUS_OK, PaletteShouldReportJniInvocations(&enabled)); + // This calls JniInvocationInit, which is necessary to load the VM. It's not + // public but still stable. + JniInvocation jni_invocation; + ASSERT_TRUE(jni_invocation.Init(nullptr)); + JavaVMInitArgs vm_args; JavaVMOption options[] = { {.optionString = "-verbose:jni", .extraInfo = nullptr}, diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp index fdc57d0f17..3d910f2c41 100644 --- a/libdexfile/Android.bp +++ b/libdexfile/Android.bp @@ -370,7 +370,6 @@ art_cc_defaults { "external/dex_file_ext_test.cc", ], shared_libs: [ - "libartbase", "libdexfile", ], header_libs: [ @@ -387,6 +386,9 @@ art_cc_test { "art_test_defaults", "art_libdexfile_external_tests_defaults", ], + shared_libs: [ + "libartbase", + ], } // Standalone version of ART gtest `art_libdexfile_external_tests`, not bundled with the ART APEX on @@ -397,6 +399,9 @@ art_cc_test { "art_standalone_test_defaults", "art_libdexfile_external_tests_defaults", ], + static_libs: [ + "libartbase", + ], // Support multilib variants (using different suffix per sub-architecture), which is needed on // build targets with secondary architectures, as the CTS test suite packaging logic flattens diff --git a/test/Android.bp b/test/Android.bp index 4289c18f41..1effa969b5 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -314,6 +314,43 @@ art_cc_defaults { ], } +// Variant of art_standalone_gtest_defaults that doesn't link dynamically to any +// internal ART libraries. +art_cc_defaults { + name: "art_cts_gtest_defaults", + defaults: [ + // Note: We don't include "art_debug_defaults" here, as standalone ART + // gtests link with the "non-d" versions of the libraries contained in + // the ART APEX, so that they can be used with all ART APEX flavors + // (including the Release ART APEX). + "art_standalone_test_defaults", + "art_gtest_common_defaults", + ], + gtest: true, + + // Support multilib variants (using different suffix per sub-architecture), which is needed on + // build targets with secondary architectures, as the MTS test suite packaging logic flattens + // all test artifacts into a single `testcases` directory. + compile_multilib: "both", + multilib: { + lib32: { + suffix: "32", + }, + lib64: { + suffix: "64", + }, + }, + + static_libs: [ + "libartbase", + ], + + test_suites: [ + "general-tests", + "mts-art", + ], +} + // Properties common to `libart-gtest-defaults` and `libartd-gtest-defaults`. art_cc_defaults { name: "libart-gtest-common-defaults", diff --git a/test/art-gtests-target-standalone-cts-template.xml b/test/art-gtests-target-standalone-cts-template.xml index 3749c3e990..e862f171e2 100644 --- a/test/art-gtests-target-standalone-cts-template.xml +++ b/test/art-gtests-target-standalone-cts-template.xml @@ -30,8 +30,6 @@ <test class="com.android.tradefed.testtype.GTest" > <option name="native-test-device-path" value="/data/local/tmp/{MODULE}" /> <option name="module-name" value="{MODULE}" /> - <option name="ld-library-path-32" value="/apex/com.android.art/lib" /> - <option name="ld-library-path-64" value="/apex/com.android.art/lib64" /> </test> <!-- When this test is run in a Mainline context (e.g. with `mts-tradefed`), only enable it if |