Merge "Report optimized/unoptimized targets correctly" into main
diff --git a/core/Makefile b/core/Makefile
index 5e0d4df..92dd86d 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1654,6 +1654,8 @@
$(ALL_DEFAULT_INSTALLED_MODULES))
INTERNAL_VENDOR_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor_boot)/vendor_ramdisk.cpio$(RAMDISK_EXT)
+vendor_ramdisk_intermediates :=$= $(call intermediates-dir-for,PACKAGING,vendor_ramdisk)
+$(eval $(call write-partition-file-list,$(vendor_ramdisk_intermediates)/file_list.txt,$(TARGET_VENDOR_RAMDISK_OUT),$(INTERNAL_VENDOR_RAMDISK_FILES)))
# Exclude recovery files in the default vendor ramdisk if including a standalone
# recovery ramdisk in vendor_boot.
diff --git a/core/config.mk b/core/config.mk
index 485e8cc..b546ea1 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1307,10 +1307,6 @@
SOONG_VARIABLES :=
SOONG_EXTRA_VARIABLES :=
--include external/ltp/android/ltp_package_list.mk
-DEFAULT_DATA_OUT_MODULES := ltp $(ltp_packages)
-.KATI_READONLY := DEFAULT_DATA_OUT_MODULES
-
include $(BUILD_SYSTEM)/dumpvar.mk
ifdef BOARD_VNDK_VERSION
diff --git a/core/soong_config.mk b/core/soong_config.mk
index c5dd320..7c07010 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -430,6 +430,7 @@
# boot image stuff
$(call add_json_bool, BuildingRamdiskImage, $(filter true,$(BUILDING_RAMDISK_IMAGE)))
$(call add_json_bool, ProductBuildBootImage, $(filter true,$(PRODUCT_BUILD_BOOT_IMAGE)))
+ $(call add_json_str, ProductBuildVendorBootImage, $(PRODUCT_BUILD_VENDOR_BOOT_IMAGE))
$(call add_json_bool, ProductBuildInitBootImage, $(filter true,$(PRODUCT_BUILD_INIT_BOOT_IMAGE)))
$(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
$(call add_json_str, BoardPrebuiltBootimage, $(BOARD_PREBUILT_BOOT_IMAGE))
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index d6fc072..1901ed5 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -27,21 +27,9 @@
# Create an artifact to include all test config files in general-tests.
general_tests_configs_zip := $(PRODUCT_OUT)/general-tests_configs.zip
-# Copy kernel test modules to testcases directories
-include $(BUILD_SYSTEM)/tasks/tools/vts-kernel-tests.mk
-ltp_copy_pairs := \
- $(call target-native-copy-pairs,$(kernel_ltp_modules),$(kernel_ltp_host_out))
-copy_ltp_tests := $(call copy-many-files,$(ltp_copy_pairs))
-
-# PHONY target to be used to build and test `vts_ltp_tests` without building full vts
-.PHONY: vts_kernel_ltp_tests
-vts_kernel_ltp_tests: $(copy_ltp_tests)
-
general_tests_shared_libs_zip := $(PRODUCT_OUT)/general-tests_host-shared-libs.zip
$(general_tests_zip) : $(general_tests_shared_libs_zip)
-$(general_tests_zip) : $(copy_ltp_tests)
-$(general_tests_zip) : PRIVATE_KERNEL_LTP_HOST_OUT := $(kernel_ltp_host_out)
$(general_tests_zip) : PRIVATE_general_tests_list_zip := $(general_tests_list_zip)
$(general_tests_zip) : .KATI_IMPLICIT_OUTPUTS := $(general_tests_list_zip) $(general_tests_configs_zip)
$(general_tests_zip) : PRIVATE_TOOLS := $(general_tests_tools)
@@ -52,7 +40,6 @@
rm -f $@ $(PRIVATE_general_tests_list_zip)
mkdir -p $(PRIVATE_INTERMEDIATES_DIR) $(PRIVATE_INTERMEDIATES_DIR)/tools
echo $(sort $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
- find $(PRIVATE_KERNEL_LTP_HOST_OUT) >> $(PRIVATE_INTERMEDIATES_DIR)/list
grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/host.list || true
grep $(TARGET_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/target.list || true
grep -e .*\\.config$$ $(PRIVATE_INTERMEDIATES_DIR)/host.list > $(PRIVATE_INTERMEDIATES_DIR)/host-test-configs.list || true
diff --git a/core/tasks/tools/vts-kernel-tests.mk b/core/tasks/tools/vts-kernel-tests.mk
deleted file mode 100644
index e727dc1..0000000
--- a/core/tasks/tools/vts-kernel-tests.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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 external/ltp/android/ltp_package_list.mk
-
-include $(BUILD_SYSTEM)/tasks/tools/vts_package_utils.mk
-
-# Copy kernel test modules to testcases directories
-kernel_ltp_host_out := $(HOST_OUT_TESTCASES)/vts_kernel_ltp_tests
-kernel_ltp_vts_out := $(HOST_OUT)/$(test_suite_name)/android-$(test_suite_name)/testcases/vts_kernel_ltp_tests
-kernel_ltp_modules := \
- ltp \
- $(ltp_packages)
diff --git a/core/tasks/tools/vts_package_utils.mk b/core/tasks/tools/vts_package_utils.mk
deleted file mode 100644
index 1a819f2..0000000
--- a/core/tasks/tools/vts_package_utils.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright (C) 2020 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.
-#
-
-# $(1): List of target native files to copy.
-# $(2): Copy destination directory.
-# Evaluates to a list of ":"-separated pairs src:dst.
-define target-native-copy-pairs
-$(foreach m,$(1),\
- $(eval _built_files := $(strip $(ALL_MODULES.$(m).BUILT_INSTALLED)\
- $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).BUILT_INSTALLED)))\
- $(foreach i, $(sort $(_built_files)),\
- $(eval bui_ins := $(subst :,$(space),$(i)))\
- $(eval ins := $(word 2,$(bui_ins)))\
- $(if $(filter $(TARGET_OUT_ROOT)/%,$(ins)),\
- $(eval bui := $(word 1,$(bui_ins)))\
- $(eval my_copy_dest := $(patsubst data/%,DATA/%,\
- $(patsubst system/%,DATA/%,\
- $(patsubst $(PRODUCT_OUT)/%,%,$(ins)))))\
- $(call declare-copy-target-license-metadata,$(2)/$(my_copy_dest),$(bui))\
- $(bui):$(2)/$(my_copy_dest))))
-endef
diff --git a/core/tasks/vts-core-tests.mk b/core/tasks/vts-core-tests.mk
index 1eeb078..11bb932 100644
--- a/core/tasks/vts-core-tests.mk
+++ b/core/tasks/vts-core-tests.mk
@@ -16,15 +16,6 @@
test_suite_tradefed := vts-tradefed
test_suite_readme := test/vts/tools/vts-core-tradefed/README
-include $(BUILD_SYSTEM)/tasks/tools/vts-kernel-tests.mk
-
-ltp_copy_pairs := \
- $(call target-native-copy-pairs,$(kernel_ltp_modules),$(kernel_ltp_vts_out))
-
-copy_ltp_tests := $(call copy-many-files,$(ltp_copy_pairs))
-
-test_suite_extra_deps := $(copy_ltp_tests)
-
include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
.PHONY: vts
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index ea49af4..b1c3def 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -885,7 +885,7 @@
}
android_system_image {
- name: "generic_system_image",
+ name: "aosp_shared_system_image",
defaults: ["system_image_defaults"],
dirs: android_rootdirs,
symlinks: android_symlinks,
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index bfdf1a7..e2bb1ad 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -513,19 +513,11 @@
package com.android.aconfig.test;
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
- import android.os.Binder;
- import android.provider.DeviceConfig;
- import android.provider.DeviceConfig.Properties;
import android.aconfig.storage.StorageInternalReader;
- import java.nio.file.Files;
- import java.nio.file.Paths;
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
- private static final boolean isReadFromNew = Files.exists(Paths.get("/metadata/aconfig/boot/enable_only_new_storage"));
private static volatile boolean isCached = false;
- private static volatile boolean aconfig_test_is_cached = false;
- private static volatile boolean other_namespace_is_cached = false;
private static boolean disabledRw = false;
private static boolean disabledRwExported = false;
private static boolean disabledRwInOtherNamespace = false;
@@ -544,55 +536,6 @@
disabledRwInOtherNamespace = foundPackage ? reader.getBooleanFlagValue(3) : false;
isCached = true;
}
- private void load_overrides_aconfig_test() {
- final long ident = Binder.clearCallingIdentity();
- try {
- Properties properties = DeviceConfig.getProperties("aconfig_test");
- disabledRw =
- properties.getBoolean(Flags.FLAG_DISABLED_RW, false);
- disabledRwExported =
- properties.getBoolean(Flags.FLAG_DISABLED_RW_EXPORTED, false);
- enabledRw =
- properties.getBoolean(Flags.FLAG_ENABLED_RW, true);
- } catch (NullPointerException e) {
- throw new RuntimeException(
- "Cannot read value from namespace aconfig_test "
- + "from DeviceConfig. It could be that the code using flag "
- + "executed before SettingsProvider initialization. Please use "
- + "fixed read-only flag by adding is_fixed_read_only: true in "
- + "flag declaration.",
- e
- );
- } catch (SecurityException e) {
- // for isolated process case, skip loading flag value from the storage, use the default
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- aconfig_test_is_cached = true;
- }
-
- private void load_overrides_other_namespace() {
- final long ident = Binder.clearCallingIdentity();
- try {
- Properties properties = DeviceConfig.getProperties("other_namespace");
- disabledRwInOtherNamespace =
- properties.getBoolean(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false);
- } catch (NullPointerException e) {
- throw new RuntimeException(
- "Cannot read value from namespace other_namespace "
- + "from DeviceConfig. It could be that the code using flag "
- + "executed before SettingsProvider initialization. Please use "
- + "fixed read-only flag by adding is_fixed_read_only: true in "
- + "flag declaration.",
- e
- );
- } catch (SecurityException e) {
- // for isolated process case, skip loading flag value from the storage, use the default
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- other_namespace_is_cached = true;
- }
@Override
@com.android.aconfig.annotations.AconfigFlagAccessor
@@ -604,14 +547,8 @@
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRw() {
- if (isReadFromNew) {
- if (!isCached) {
- init();
- }
- } else {
- if (!aconfig_test_is_cached) {
- load_overrides_aconfig_test();
- }
+ if (!isCached) {
+ init();
}
return disabledRw;
}
@@ -619,14 +556,8 @@
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwExported() {
- if (isReadFromNew) {
- if (!isCached) {
- init();
- }
- } else {
- if (!aconfig_test_is_cached) {
- load_overrides_aconfig_test();
- }
+ if (!isCached) {
+ init();
}
return disabledRwExported;
}
@@ -634,14 +565,8 @@
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
- if (isReadFromNew) {
- if (!isCached) {
- init();
- }
- } else {
- if (!other_namespace_is_cached) {
- load_overrides_other_namespace();
- }
+ if (!isCached) {
+ init();
}
return disabledRwInOtherNamespace;
}
@@ -673,14 +598,8 @@
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRw() {
- if (isReadFromNew) {
- if (!isCached) {
- init();
- }
- } else {
- if (!aconfig_test_is_cached) {
- load_overrides_aconfig_test();
- }
+ if (!isCached) {
+ init();
}
return enabledRw;
}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index cb52150..d782f81 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -1,41 +1,22 @@
package {package_name};
{{ -if not is_test_mode }}
{{ -if allow_instrumentation }}
-{{ if not library_exported- }}
+{{ if not library_exported- }}{#- only new storage for prod mode #}
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
-{{ -endif }}
-
{{ -if runtime_lookup_required }}
-import android.os.Binder;
-import android.provider.DeviceConfig;
-import android.provider.DeviceConfig.Properties;
-
-{{ -if not library_exported }}
import android.aconfig.storage.StorageInternalReader;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-{{ -endif }}
-
{{ -endif }}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
-{{ -if not library_exported }}
- private static final boolean isReadFromNew = Files.exists(Paths.get("/metadata/aconfig/boot/enable_only_new_storage"));
private static volatile boolean isCached = false;
-{{ -endif }}
-{{ -for namespace_with_flags in namespace_flags }}
- private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
-{{ -endfor- }}
-
{{ for flag in flag_elements }}
{{ -if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
{{ -endif }}
{{ -endfor }}
-{{ if not library_exported }}
private void init() \{
StorageInternalReader reader = null;
boolean foundPackage = true;
@@ -53,9 +34,37 @@
{{ -endfor }}
isCached = true;
}
-{{ endif }}
-
-
+{{ -endif }}{#- end of runtime_lookup_required #}
+{{ -for flag in flag_elements }}
+ @Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
+ @UnsupportedAppUsage
+ public boolean {flag.method_name}() \{
+{{ -if flag.is_read_write }}
+ if (!isCached) \{
+ init();
+ }
+ return {flag.method_name};
+{{ -else }}
+ return {flag.default_value};
+{{ -endif }}
+ }
+{{ endfor }}
+}
+{{ -else- }}{#- device config for exproted mode #}
+import android.os.Binder;
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
+/** @hide */
+public final class FeatureFlagsImpl implements FeatureFlags \{
+{{ -for namespace_with_flags in namespace_flags }}
+ private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
+{{ -endfor- }}
+{{ for flag in flag_elements }}
+{{ -if flag.is_read_write }}
+ private static boolean {flag.method_name} = {flag.default_value};
+{{ -endif }}
+{{ -endfor }}
{{ for namespace_with_flags in namespace_flags }}
private void load_overrides_{namespace_with_flags.namespace}() \{
final long ident = Binder.clearCallingIdentity();
@@ -84,40 +93,17 @@
{namespace_with_flags.namespace}_is_cached = true;
}
{{ endfor- }}
-
-{{ -endif }}{#- end of runtime_lookup_required #}
{{ -for flag in flag_elements }}
@Override
-{{ -if not library_exported }}
- @com.android.aconfig.annotations.AconfigFlagAccessor
- @UnsupportedAppUsage
-{{ -endif }}
public boolean {flag.method_name}() \{
-{{ -if not library_exported }}
-{{ -if flag.is_read_write }}
- if (isReadFromNew) \{
- if (!isCached) \{
- init();
- }
- } else \{
- if (!{flag.device_config_namespace}_is_cached) \{
- load_overrides_{flag.device_config_namespace}();
- }
- }
- return {flag.method_name};
-{{ -else }}
- return {flag.default_value};
-{{ -endif }}
-{{ else }}
if (!{flag.device_config_namespace}_is_cached) \{
load_overrides_{flag.device_config_namespace}();
}
return {flag.method_name};
-{{ -endif }}
}
{{ endfor }}
}
-
+{{ -endif- }} {#- end exported mode #}
{{ else }} {#- else for allow_instrumentation is not enabled #}
{{ if not library_exported- }}
// TODO(b/303773055): Remove the annotation after access issue is resolved.
diff --git a/tools/edit_monitor/daemon_manager.py b/tools/edit_monitor/daemon_manager.py
index ef2a309..22782f7 100644
--- a/tools/edit_monitor/daemon_manager.py
+++ b/tools/edit_monitor/daemon_manager.py
@@ -33,7 +33,7 @@
DEFAULT_PROCESS_TERMINATION_TIMEOUT_SECONDS = 5
DEFAULT_MONITOR_INTERVAL_SECONDS = 5
-DEFAULT_MEMORY_USAGE_THRESHOLD = 3 * 1024 # 3GB
+DEFAULT_MEMORY_USAGE_THRESHOLD = 0.02 # 2% of total memory
DEFAULT_CPU_USAGE_THRESHOLD = 200
DEFAULT_REBOOT_TIMEOUT_SECONDS = 60 * 60 * 24
BLOCK_SIGN_FILE = "edit_monitor_block_sign"
@@ -70,6 +70,9 @@
self.max_memory_usage = 0
self.max_cpu_usage = 0
+ self.total_memory_size = os.sysconf("SC_PAGE_SIZE") * os.sysconf(
+ "SC_PHYS_PAGES"
+ )
pid_file_dir = pathlib.Path(tempfile.gettempdir()).joinpath("edit_monitor")
pid_file_dir.mkdir(parents=True, exist_ok=True)
@@ -142,10 +145,20 @@
logging.warning("Failed to monitor daemon process with error: %s", e)
if self.max_memory_usage >= memory_threshold:
- self._handle_resource_exhausted_error("memory")
+ self._send_error_event_to_clearcut(
+ edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE
+ )
+ logging.error(
+ "Daemon process is consuming too much memory, rebooting...")
+ self.reboot()
if self.max_cpu_usage >= cpu_threshold:
- self._handle_resource_exhausted_error("cpu")
+ self._send_error_event_to_clearcut(
+ edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_CPU_USAGE
+ )
+ logging.error(
+ "Daemon process is consuming too much cpu, killing...")
+ self._terminate_process(self.daemon_process.pid)
logging.info(
"Daemon process %d terminated. Max memory usage: %f, Max cpu"
@@ -345,7 +358,13 @@
stat_data = f.readline().split()
# RSS is the 24th field in /proc/[pid]/stat
rss_pages = int(stat_data[23])
- return rss_pages * 4 / 1024 # Covert to MB
+ process_memory = rss_pages * 4 * 1024 # Convert to bytes
+
+ return (
+ process_memory / self.total_memory_size
+ if self.total_memory_size
+ else 0.0
+ )
def _get_process_cpu_percent(self, pid: int, interval: int = 1) -> float:
total_start_time = self._get_total_cpu_time(pid)
@@ -386,20 +405,6 @@
return pids
- def _handle_resource_exhausted_error(self, resource_type:str):
- if resource_type == "memory":
- self._send_error_event_to_clearcut(
- edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE
- )
- else:
- self._send_error_event_to_clearcut(
- edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_CPU_USAGE
- )
- logging.error(
- "Daemon process is consuming too much %s, killing...", resource_type
- ),
- self._terminate_process(self.daemon_process.pid)
-
def _send_error_event_to_clearcut(self, error_type):
edit_monitor_error_event_proto = edit_event_pb2.EditEvent(
user_name=self.user_name,
diff --git a/tools/edit_monitor/daemon_manager_test.py b/tools/edit_monitor/daemon_manager_test.py
index 12aaab3..350739d 100644
--- a/tools/edit_monitor/daemon_manager_test.py
+++ b/tools/edit_monitor/daemon_manager_test.py
@@ -202,23 +202,31 @@
fake_cclient, edit_event_pb2.EditEvent.FAILED_TO_START_EDIT_MONITOR
)
- def test_monitor_daemon_subprocess_killed_high_memory_usage(self):
+ @mock.patch('os.execv')
+ def test_monitor_reboot_with_high_memory_usage(self, mock_execv):
fake_cclient = FakeClearcutClient()
+ binary_file = tempfile.NamedTemporaryFile(
+ dir=self.working_dir.name, delete=False
+ )
+
dm = daemon_manager.DaemonManager(
- TEST_BINARY_FILE,
+ binary_file.name,
daemon_target=memory_consume_daemon_target,
daemon_args=(2,),
cclient=fake_cclient,
)
+ # set the fake total_memory_size
+ dm.total_memory_size = 100 * 1024 *1024
dm.start()
- dm.monitor_daemon(interval=1, memory_threshold=2)
+ dm.monitor_daemon(interval=1)
- self.assertTrue(dm.max_memory_usage >= 2)
+ self.assertTrue(dm.max_memory_usage >= 0.02)
self.assert_no_subprocess_running()
self._assert_error_event_logged(
fake_cclient,
edit_event_pb2.EditEvent.KILLED_DUE_TO_EXCEEDED_MEMORY_USAGE,
)
+ mock_execv.assert_called_once()
def test_monitor_daemon_subprocess_killed_high_cpu_usage(self):
fake_cclient = FakeClearcutClient()