Add artd unit tests.
This change adds `art_artd_tests`, which contains the unit tests of
artd. The change also splits the code into artd.h/artd.cc and
artd_main.cc, where artd.h/artd.cc contains the implementation that is
unit-testable, while artd_main.cc contains the main function of the artd
binary.
Bug: 177273468
Test: m test-art-host-gtest-art_artd_tests
Test: ArtGtestsTargetChroot:ArtdTest
Ignore-AOSP-First: Will cherry-pick later.
Change-Id: I19701d7ca83f541becdcd413e740eff93d03037d
diff --git a/artd/Android.bp b/artd/Android.bp
index e69483a..7f99685 100644
--- a/artd/Android.bp
+++ b/artd/Android.bp
@@ -22,23 +22,32 @@
default_applicable_licenses: ["art_license"],
}
-art_cc_binary {
- name: "artd",
+cc_defaults {
+ name: "artd_defaults",
defaults: ["art_defaults"],
-
srcs: [
"artd.cc",
],
-
shared_libs: [
- "artd-aidl-ndk",
- "libart",
- "libartbase",
"libarttools",
"libbase",
"libbinder_ndk",
],
+ static_libs: [
+ "artd-aidl-ndk",
+ ],
+}
+art_cc_binary {
+ name: "artd",
+ defaults: ["artd_defaults"],
+ srcs: [
+ "artd_main.cc",
+ ],
+ shared_libs: [
+ "libart",
+ "libartbase",
+ ],
apex_available: [
"com.android.art",
"com.android.art.debug",
@@ -51,3 +60,35 @@
filename: "init.rc",
installable: false,
}
+
+art_cc_defaults {
+ name: "art_artd_tests_defaults",
+ defaults: ["artd_defaults"],
+ // TODO(b/235464166): The host test does not build on master-art because of
+ // the dependency on libbinder_ndk.
+ host_supported: false,
+ srcs: [
+ "artd_test.cc",
+ ],
+}
+
+// Version of ART gtest `art_artd_tests` bundled with the ART APEX on target.
+// TODO(b/192274705): Remove this module when the migration to standalone ART
+// gtests is complete.
+art_cc_test {
+ name: "art_artd_tests",
+ defaults: [
+ "art_gtest_defaults",
+ "art_artd_tests_defaults",
+ ],
+}
+
+// Standalone version of ART gtest `art_artd_tests`, not bundled with the ART
+// APEX on target.
+art_cc_test {
+ name: "art_standalone_artd_tests",
+ defaults: [
+ "art_standalone_gtest_defaults",
+ "art_artd_tests_defaults",
+ ],
+}
diff --git a/artd/artd.cc b/artd/artd.cc
index a8c6084..98693cb 100644
--- a/artd/artd.cc
+++ b/artd/artd.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "artd.h"
+
#include <stdlib.h>
#include <unistd.h>
@@ -43,7 +45,6 @@
namespace {
using ::aidl::com::android::server::art::ArtifactsPath;
-using ::aidl::com::android::server::art::BnArtd;
using ::aidl::com::android::server::art::GetOptimizationStatusResult;
using ::android::base::Error;
using ::android::base::GetBoolProperty;
@@ -51,6 +52,8 @@
using ::android::base::Split;
using ::ndk::ScopedAStatus;
+constexpr const char* kServiceName = "artd";
+
constexpr const char* kPhenotypeFlagPrefix = "persist.device_config.runtime_native_boot.";
constexpr const char* kDalvikVmFlagPrefix = "dalvik.vm.";
@@ -91,128 +94,94 @@
} // namespace
-class Artd : public BnArtd {
- constexpr static const char* kServiceName = "artd";
+ScopedAStatus Artd::isAlive(bool* _aidl_return) {
+ *_aidl_return = true;
+ return ScopedAStatus::ok();
+}
- public:
- ScopedAStatus isAlive(bool* _aidl_return) override {
- *_aidl_return = true;
- return ScopedAStatus::ok();
+ScopedAStatus Artd::deleteArtifacts(const ArtifactsPath& in_artifactsPath, int64_t* _aidl_return) {
+ (void)in_artifactsPath;
+ (void)_aidl_return;
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus Artd::getOptimizationStatus(const std::string& in_dexFile,
+ const std::string& in_instructionSet,
+ const std::string& in_classLoaderContext,
+ GetOptimizationStatusResult* _aidl_return) {
+ Result<OatFileAssistant::RuntimeOptions> runtime_options = GetRuntimeOptions();
+ if (!runtime_options.ok()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_STATE,
+ ("Failed to get runtime options: " + runtime_options.error().message()).c_str());
}
- ScopedAStatus deleteArtifacts(const ArtifactsPath& in_artifactsPath,
- int64_t* _aidl_return) override {
- (void)in_artifactsPath;
- (void)_aidl_return;
- return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ std::string error_msg;
+ if (!OatFileAssistant::GetOptimizationStatus(
+ in_dexFile.c_str(),
+ in_instructionSet.c_str(),
+ in_classLoaderContext.c_str(),
+ std::make_unique<OatFileAssistant::RuntimeOptions>(std::move(*runtime_options)),
+ &_aidl_return->compilerFilter,
+ &_aidl_return->compilationReason,
+ &_aidl_return->locationDebugString,
+ &error_msg)) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_STATE, ("Failed to get optimization status: " + error_msg).c_str());
}
- ScopedAStatus getOptimizationStatus(const std::string& in_dexFile,
- const std::string& in_instructionSet,
- const std::string& in_classLoaderContext,
- GetOptimizationStatusResult* _aidl_return) override {
- Result<OatFileAssistant::RuntimeOptions> runtime_options = GetRuntimeOptions();
- if (!runtime_options.ok()) {
- return ScopedAStatus::fromExceptionCodeWithMessage(
- EX_ILLEGAL_STATE,
- ("Failed to get runtime options: " + runtime_options.error().message()).c_str());
- }
+ return ScopedAStatus::ok();
+}
- std::string error_msg;
- if (!OatFileAssistant::GetOptimizationStatus(
- in_dexFile.c_str(),
- in_instructionSet.c_str(),
- in_classLoaderContext.c_str(),
- std::make_unique<OatFileAssistant::RuntimeOptions>(std::move(*runtime_options)),
- &_aidl_return->compilerFilter,
- &_aidl_return->compilationReason,
- &_aidl_return->locationDebugString,
- &error_msg)) {
- return ScopedAStatus::fromExceptionCodeWithMessage(
- EX_ILLEGAL_STATE, ("Failed to get optimization status: " + error_msg).c_str());
- }
-
- return ScopedAStatus::ok();
+Result<void> Artd::Start() {
+ ScopedAStatus status = ScopedAStatus::fromStatus(
+ AServiceManager_registerLazyService(this->asBinder().get(), kServiceName));
+ if (!status.isOk()) {
+ return Error() << status.getDescription();
}
- Result<void> Start() {
- LOG(INFO) << "Starting artd";
+ ABinderProcess_startThreadPool();
- ScopedAStatus status = ScopedAStatus::fromStatus(
- AServiceManager_registerLazyService(this->asBinder().get(), kServiceName));
- if (!status.isOk()) {
- return Error() << status.getDescription();
- }
+ return {};
+}
- ABinderProcess_startThreadPool();
+Result<OatFileAssistant::RuntimeOptions> Artd::GetRuntimeOptions() {
+ // We don't cache this system property because it can change.
+ bool use_jit_zygote = UseJitZygote();
- return {};
+ if (!HasRuntimeOptionsCache()) {
+ OR_RETURN(BuildRuntimeOptionsCache());
}
- private:
- Result<OatFileAssistant::RuntimeOptions> GetRuntimeOptions() {
- // We don't cache this system property because it can change.
- bool use_jit_zygote = UseJitZygote();
+ return OatFileAssistant::RuntimeOptions{
+ .image_locations = cached_boot_image_locations_,
+ .boot_class_path = cached_boot_class_path_,
+ .boot_class_path_locations = cached_boot_class_path_,
+ .use_jit_zygote = use_jit_zygote,
+ .deny_art_apex_data_files = cached_deny_art_apex_data_files_,
+ .apex_versions = cached_apex_versions_,
+ };
+}
- if (!HasRuntimeOptionsCache()) {
- OR_RETURN(BuildRuntimeOptionsCache());
- }
+Result<void> Artd::BuildRuntimeOptionsCache() {
+ // This system property can only be set by odsign on boot, so it won't change.
+ bool deny_art_apex_data_files = DenyArtApexDataFiles();
- return OatFileAssistant::RuntimeOptions{
- .image_locations = cached_boot_image_locations_,
- .boot_class_path = cached_boot_class_path_,
- .boot_class_path_locations = cached_boot_class_path_,
- .use_jit_zygote = use_jit_zygote,
- .deny_art_apex_data_files = cached_deny_art_apex_data_files_,
- .apex_versions = cached_apex_versions_,
- };
- }
+ std::vector<std::string> image_locations =
+ OR_RETURN(GetBootImageLocations(deny_art_apex_data_files));
+ std::vector<std::string> boot_class_path = OR_RETURN(GetBootClassPath());
+ std::string apex_versions =
+ Runtime::GetApexVersions(ArrayRef<const std::string>(boot_class_path));
- Result<void> BuildRuntimeOptionsCache() {
- // This system property can only be set by odsign on boot, so it won't change.
- bool deny_art_apex_data_files = DenyArtApexDataFiles();
+ cached_boot_image_locations_ = std::move(image_locations);
+ cached_boot_class_path_ = std::move(boot_class_path);
+ cached_apex_versions_ = std::move(apex_versions);
+ cached_deny_art_apex_data_files_ = deny_art_apex_data_files;
- std::vector<std::string> image_locations =
- OR_RETURN(GetBootImageLocations(deny_art_apex_data_files));
- std::vector<std::string> boot_class_path = OR_RETURN(GetBootClassPath());
- std::string apex_versions =
- Runtime::GetApexVersions(ArrayRef<const std::string>(boot_class_path));
+ return {};
+}
- cached_boot_image_locations_ = std::move(image_locations);
- cached_boot_class_path_ = std::move(boot_class_path);
- cached_apex_versions_ = std::move(apex_versions);
- cached_deny_art_apex_data_files_ = deny_art_apex_data_files;
-
- return {};
- }
-
- bool HasRuntimeOptionsCache() {
- return !cached_boot_image_locations_.empty();
- }
-
- std::vector<std::string> cached_boot_image_locations_;
- std::vector<std::string> cached_boot_class_path_;
- std::string cached_apex_versions_;
- bool cached_deny_art_apex_data_files_;
-};
+bool Artd::HasRuntimeOptionsCache() const { return !cached_boot_image_locations_.empty(); }
} // namespace artd
} // namespace art
-
-int main(const int argc __attribute__((unused)), char* argv[]) {
- setenv("ANDROID_LOG_TAGS", "*:v", 1);
- android::base::InitLogging(argv);
-
- art::artd::Artd artd;
-
- if (auto ret = artd.Start(); !ret.ok()) {
- LOG(ERROR) << "Unable to start artd: " << ret.error();
- exit(1);
- }
-
- ABinderProcess_joinThreadPool();
-
- LOG(INFO) << "artd shutting down";
-
- return 0;
-}
diff --git a/artd/artd.h b/artd/artd.h
new file mode 100644
index 0000000..2a05267
--- /dev/null
+++ b/artd/artd.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#ifndef ART_ARTD_ARTD_H_
+#define ART_ARTD_ARTD_H_
+
+#include <string>
+#include <vector>
+
+#include "aidl/com/android/server/art/BnArtd.h"
+#include "android-base/result.h"
+#include "android/binder_auto_utils.h"
+#include "oat_file_assistant.h"
+
+namespace art {
+namespace artd {
+
+class Artd : public aidl::com::android::server::art::BnArtd {
+ public:
+ ndk::ScopedAStatus isAlive(bool* _aidl_return) override;
+
+ ndk::ScopedAStatus deleteArtifacts(
+ const aidl::com::android::server::art::ArtifactsPath& in_artifactsPath,
+ int64_t* _aidl_return) override;
+
+ ndk::ScopedAStatus getOptimizationStatus(
+ const std::string& in_dexFile,
+ const std::string& in_instructionSet,
+ const std::string& in_classLoaderContext,
+ aidl::com::android::server::art::GetOptimizationStatusResult* _aidl_return) override;
+
+ android::base::Result<void> Start();
+
+ private:
+ android::base::Result<OatFileAssistant::RuntimeOptions> GetRuntimeOptions();
+
+ android::base::Result<void> BuildRuntimeOptionsCache();
+
+ bool HasRuntimeOptionsCache() const;
+
+ std::vector<std::string> cached_boot_image_locations_;
+ std::vector<std::string> cached_boot_class_path_;
+ std::string cached_apex_versions_;
+ bool cached_deny_art_apex_data_files_;
+};
+
+} // namespace artd
+} // namespace art
+
+#endif // ART_ARTD_ARTD_H_
diff --git a/artd/artd_main.cc b/artd/artd_main.cc
new file mode 100644
index 0000000..3644eba
--- /dev/null
+++ b/artd/artd_main.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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 <stdlib.h>
+
+#include "android-base/logging.h"
+#include "android-base/macros.h"
+#include "android/binder_interface_utils.h"
+#include "android/binder_process.h"
+#include "artd.h"
+
+int main(int argc ATTRIBUTE_UNUSED, char* argv[]) {
+ android::base::InitLogging(argv);
+
+ auto artd = ndk::SharedRefBase::make<art::artd::Artd>();
+
+ LOG(INFO) << "Starting artd";
+
+ if (auto ret = artd->Start(); !ret.ok()) {
+ LOG(ERROR) << "Unable to start artd: " << ret.error();
+ exit(1);
+ }
+
+ ABinderProcess_joinThreadPool();
+
+ LOG(INFO) << "artd shutting down";
+
+ return 0;
+}
diff --git a/artd/artd_test.cc b/artd/artd_test.cc
new file mode 100644
index 0000000..14bccc2
--- /dev/null
+++ b/artd/artd_test.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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 "artd.h"
+
+#include <memory>
+
+#include "android/binder_interface_utils.h"
+#include "base/common_art_test.h"
+#include "gtest/gtest.h"
+
+namespace art {
+namespace artd {
+namespace {
+
+class ArtdTest : public CommonArtTest {
+ protected:
+ void SetUp() override {
+ CommonArtTest::SetUp();
+ artd_ = ndk::SharedRefBase::make<Artd>();
+ }
+
+ void TearDown() override { CommonArtTest::TearDown(); }
+
+ std::shared_ptr<Artd> artd_;
+};
+
+TEST_F(ArtdTest, isAlive) {
+ bool result = false;
+ artd_->isAlive(&result);
+ EXPECT_TRUE(result);
+}
+
+} // namespace
+} // namespace artd
+} // namespace art
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index d9a75e4..c9becd7 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -132,7 +132,10 @@
art_runtime_tests \
art_sigchain_tests \
-ART_TEST_MODULES_TARGET := $(ART_TEST_MODULES_COMMON) art_odrefresh_tests
+ART_TEST_MODULES_TARGET := $(ART_TEST_MODULES_COMMON) \
+ art_artd_tests \
+ art_odrefresh_tests \
+
ART_TEST_MODULES_HOST := $(ART_TEST_MODULES_COMMON)
ART_TARGET_GTEST_NAMES := $(foreach tm,$(ART_TEST_MODULES_TARGET),\
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 890de9d..9ad5eee 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -400,6 +400,7 @@
// ART gtests with dependencies on internal ART APEX libraries.
art_gtests = [
+ "art_artd_tests",
"art_cmdline_tests",
"art_compiler_tests",
"art_dex2oat_tests",
diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py
index 556bb78..a13a7d3 100755
--- a/build/apex/art_apex_test.py
+++ b/build/apex/art_apex_test.py
@@ -558,7 +558,6 @@
# Check internal libraries for ART.
self._checker.check_native_library('libartservice')
self._checker.check_native_library('libperfetto_hprof')
- self._checker.check_prefer64_library('artd-aidl-ndk')
# Check internal Java libraries
self._checker.check_java_library("service-art")
@@ -672,6 +671,7 @@
def run(self):
# Check ART test binaries.
+ self._checker.check_art_test_executable('art_artd_tests')
self._checker.check_art_test_executable('art_cmdline_tests')
self._checker.check_art_test_executable('art_compiler_tests')
self._checker.check_art_test_executable('art_dex2oat_tests')
diff --git a/test/utils/regen-test-files b/test/utils/regen-test-files
index 7ddffe6..1522758 100755
--- a/test/utils/regen-test-files
+++ b/test/utils/regen-test-files
@@ -215,6 +215,7 @@
# ART gtests that do not need root access to the device.
art_gtest_user_module_names = [
"art_libnativebridge_cts_tests",
+ "art_standalone_artd_tests",
"art_standalone_cmdline_tests",
"art_standalone_compiler_tests",
"art_standalone_dex2oat_tests",