diff options
Diffstat (limited to 'libartbase/base/testing.cc')
-rw-r--r-- | libartbase/base/testing.cc | 144 |
1 files changed, 131 insertions, 13 deletions
diff --git a/libartbase/base/testing.cc b/libartbase/base/testing.cc index 3cd2836876..6ec207eded 100644 --- a/libartbase/base/testing.cc +++ b/libartbase/base/testing.cc @@ -14,19 +14,123 @@ * limitations under the License. */ +#include "testing.h" + #include <string> #include <vector> +#include "android-base/file.h" #include "android-base/stringprintf.h" +#include "android-base/strings.h" #include "base/file_utils.h" #include "base/globals.h" +#include "base/os.h" namespace art { namespace testing { -namespace { +std::string GetAndroidBuildTop() { + CHECK(IsHost()); + std::string android_build_top; + + // Look at how we were invoked to find the expected directory. + std::string argv; + if (android::base::ReadFileToString("/proc/self/cmdline", &argv)) { + // /proc/self/cmdline is the programs 'argv' with elements delimited by '\0'. + std::filesystem::path path(argv.substr(0, argv.find('\0'))); + path = std::filesystem::absolute(path); + // Walk up until we find the one of the well-known directories. + for (; path.parent_path() != path; path = path.parent_path()) { + // We are running tests from out/host/linux-x86 on developer machine. + if (path.filename() == std::filesystem::path("linux-x86")) { + android_build_top = path.parent_path().parent_path().parent_path(); + break; + } + // We are running tests from testcases (extracted from zip) on tradefed. + // The first path is for remote runs and the second path for local runs. + if (path.filename() == std::filesystem::path("testcases") || + path.filename().string().starts_with("host_testcases")) { + android_build_top = path.append("art_common"); + break; + } + } + } + CHECK(!android_build_top.empty()); + + // Check that the expected directory matches the environment variable. + const char* android_build_top_from_env = getenv("ANDROID_BUILD_TOP"); + android_build_top = std::filesystem::path(android_build_top).string(); + CHECK(!android_build_top.empty()); + if (android_build_top_from_env != nullptr) { + if (std::filesystem::weakly_canonical(android_build_top).string() != + std::filesystem::weakly_canonical(android_build_top_from_env).string()) { + android_build_top = android_build_top_from_env; + } + } else { + setenv("ANDROID_BUILD_TOP", android_build_top.c_str(), /*overwrite=*/0); + } + if (android_build_top.back() != '/') { + android_build_top += '/'; + } + return android_build_top; +} + +std::string GetAndroidHostOut() { + CHECK(IsHost()); + + // Check that the expected directory matches the environment variable. + // ANDROID_HOST_OUT is set by envsetup or unset and is the full path to host binaries/libs + const char* android_host_out_from_env = getenv("ANDROID_HOST_OUT"); + // OUT_DIR is a user-settable ENV_VAR that controls where soong puts build artifacts. It can + // either be relative to ANDROID_BUILD_TOP or a concrete path. + const char* android_out_dir = getenv("OUT_DIR"); + // Take account of OUT_DIR setting. + if (android_out_dir == nullptr) { + android_out_dir = "out"; + } + std::string android_host_out; + if (android_out_dir[0] == '/') { + android_host_out = (std::filesystem::path(android_out_dir) / "host" / "linux-x86").string(); + } else { + android_host_out = + (std::filesystem::path(GetAndroidBuildTop()) / android_out_dir / "host" / "linux-x86") + .string(); + } + std::filesystem::path expected(android_host_out); + if (android_host_out_from_env != nullptr) { + std::filesystem::path from_env(std::filesystem::weakly_canonical(android_host_out_from_env)); + if (std::filesystem::weakly_canonical(expected).string() != from_env.string()) { + LOG(WARNING) << "Execution path (" << expected << ") not below ANDROID_HOST_OUT (" << from_env + << ")! Using env-var."; + expected = from_env; + } + } else { + setenv("ANDROID_HOST_OUT", android_host_out.c_str(), /*overwrite=*/0); + } + return expected.string(); +} + +std::string GetHostBootClasspathInstallRoot() { + CHECK(IsHost()); + std::string build_install_root = GetAndroidHostOut() + "/testcases/art_common/out/host/linux-x86"; + // Look for the `apex` subdirectory as a discriminator to check the location. + if (OS::DirectoryExists((build_install_root + "/apex").c_str())) { + // This is the path where "m art-host-tests" installs support files for host + // tests, so use it when the tests are run in a build tree (which is the + // case when testing locally). + return build_install_root; + } + if (OS::DirectoryExists((GetAndroidRoot() + "/apex").c_str())) { + // This is the location for host tests in CI when the files are unzipped + // from art-host-tests.zip. + return GetAndroidRoot(); + } + LOG(ERROR) << "Neither location has a boot classpath (forgot \"m art-host-tests\"?): " + << build_install_root << " or " << GetAndroidRoot(); + return "<no boot classpath found>"; +} -std::string GetDexFileName(const std::string& jar_prefix, const std::string& prefix) { +static std::string GetDexFileName(const std::string& jar_prefix, const std::string& prefix) { const char* apexPath = (jar_prefix == "conscrypt") ? kAndroidConscryptApexDefaultPath : @@ -35,7 +139,15 @@ std::string GetDexFileName(const std::string& jar_prefix, const std::string& pre "%s%s/javalib/%s.jar", prefix.c_str(), apexPath, jar_prefix.c_str()); } -} // namespace +static std::vector<std::string> GetPrefixedDexFileNames(const std::string& prefix, + const std::vector<std::string>& modules) { + std::vector<std::string> result; + result.reserve(modules.size()); + for (const std::string& module : modules) { + result.push_back(GetDexFileName(module, prefix)); + } + return result; +} std::vector<std::string> GetLibCoreModuleNames(bool core_only) { // Note: This must start with the CORE_IMG_JARS in Android.common_path.mk because that's what we @@ -59,23 +171,25 @@ std::vector<std::string> GetLibCoreModuleNames(bool core_only) { return modules; } -std::vector<std::string> GetLibCoreDexFileNames(const std::string& prefix, - const std::vector<std::string>& modules) { - std::vector<std::string> result; - result.reserve(modules.size()); - for (const std::string& module : modules) { - result.push_back(GetDexFileName(module, prefix)); - } - return result; +std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules) { + return GetPrefixedDexFileNames(kIsTargetBuild ? "" : GetHostBootClasspathInstallRoot(), modules); } std::vector<std::string> GetLibCoreDexFileNames(const std::string& prefix, bool core_only) { std::vector<std::string> modules = GetLibCoreModuleNames(core_only); - return GetLibCoreDexFileNames(prefix, modules); + return GetPrefixedDexFileNames(prefix, modules); } std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) { - return GetLibCoreDexFileNames(/*prefix=*/"", modules); + std::string prefix = ""; + if (IsHost()) { + std::string android_root = GetAndroidRoot(); + std::string build_top = GetAndroidBuildTop(); + CHECK(android_root.starts_with(build_top)) + << " android_root=" << android_root << " build_top=" << build_top; + prefix = android_root.substr(build_top.size()); + } + return GetPrefixedDexFileNames(prefix, modules); } std::vector<std::string> GetLibCoreDexLocations(bool core_only) { @@ -83,5 +197,9 @@ std::vector<std::string> GetLibCoreDexLocations(bool core_only) { return GetLibCoreDexLocations(modules); } +std::string GetClassPathOption(const char* option, const std::vector<std::string>& class_path) { + return option + android::base::Join(class_path, ':'); +} + } // namespace testing } // namespace art |