From a4f701af93a5a739f34823cde0c493dfbc63537a Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 9 Mar 2016 14:58:16 -0800 Subject: recovery: use __android_log_pmsg_file_write for log files - Add call to __android_log_pmsg_file_write for recovery logging. - Add call to refresh pmsg if we reboot back into recovery and then allow overwrite of those logs. - Add a new one-time executable recovery-refresh that refreshes pmsg in post-fs phase of init. We rely on pmsg eventually scrolling off to age the content after recovery-persist has done its job. - Add a new one-time executable recovery-persist that transfers from pmsg to /data/misc/recovery/ directory if /cache is not mounted in post-fs-data phase of init. - Build and appropriately trigger the above two as required if BOARD_CACHEIMAGE_PARTITION_SIZE is undefined. - Add some simple unit tests NB: Test failure is expected on systems that do not deliver either the recovery-persist or recovery-refresh executables, e.g. systems with /cache. Tests also require a timely reboot sequence of test to truly verify, tests provide guidance on stderr to direct. Bug: 27176738 Change-Id: I17bb95980234984f6b2087fd5941b0a3126b706b --- tests/Android.mk | 2 + tests/unit/recovery_test.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 tests/unit/recovery_test.cpp (limited to 'tests') diff --git a/tests/Android.mk b/tests/Android.mk index 262fb8bfd..8f55fc0df 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -23,7 +23,9 @@ LOCAL_MODULE := recovery_unit_test LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libverifier LOCAL_SRC_FILES := unit/asn1_decoder_test.cpp +LOCAL_SRC_FILES += unit/recovery_test.cpp LOCAL_C_INCLUDES := bootable/recovery +LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_NATIVE_TEST) # Component tests diff --git a/tests/unit/recovery_test.cpp b/tests/unit/recovery_test.cpp new file mode 100644 index 000000000..f397f258e --- /dev/null +++ b/tests/unit/recovery_test.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 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 +#include +#include +#include + +#include +#include +#include +#include + +static const char myFilename[] = "/data/misc/recovery/inject.txt"; +static const char myContent[] = "Hello World\nWelcome to my recovery\n"; + +// Failure is expected on systems that do not deliver either the +// recovery-persist or recovery-refresh executables. Tests also require +// a reboot sequence of test to truly verify. + +static ssize_t __pmsg_fn(log_id_t logId, char prio, const char *filename, + const char *buf, size_t len, void *arg) { + EXPECT_EQ(LOG_ID_SYSTEM, logId); + EXPECT_EQ(ANDROID_LOG_INFO, prio); + EXPECT_EQ(0, NULL == strstr(myFilename,filename)); + EXPECT_EQ(0, strcmp(myContent, buf)); + EXPECT_EQ(sizeof(myContent), len); + EXPECT_EQ(0, NULL != arg); + return len; +} + +// recovery.refresh - May fail. Requires recovery.inject, two reboots, +// then expect success after second reboot. +TEST(recovery, refresh) { + EXPECT_EQ(0, access("/system/bin/recovery-refresh", F_OK)); + + ssize_t ret = __android_log_pmsg_file_read( + LOG_ID_SYSTEM, ANDROID_LOG_INFO, "recovery/", __pmsg_fn, NULL); + if (ret == -ENOENT) { + EXPECT_LT(0, __android_log_pmsg_file_write( + LOG_ID_SYSTEM, ANDROID_LOG_INFO, + myFilename, myContent, sizeof(myContent))); + fprintf(stderr, "injected test data, " + "requires two intervening reboots " + "to check for replication\n"); + } + EXPECT_EQ((ssize_t)sizeof(myContent), ret); +} + +// recovery.persist - Requires recovery.inject, then a reboot, then +// expect success after for this test on that boot. +TEST(recovery, persist) { + EXPECT_EQ(0, access("/system/bin/recovery-persist", F_OK)); + + ssize_t ret = __android_log_pmsg_file_read( + LOG_ID_SYSTEM, ANDROID_LOG_INFO, "recovery/", __pmsg_fn, NULL); + if (ret == -ENOENT) { + EXPECT_LT(0, __android_log_pmsg_file_write( + LOG_ID_SYSTEM, ANDROID_LOG_INFO, + myFilename, myContent, sizeof(myContent))); + fprintf(stderr, "injected test data, " + "requires intervening reboot " + "to check for storage\n"); + } + + int fd = open(myFilename, O_RDONLY); + EXPECT_LE(0, fd); + + char buf[sizeof(myContent) + 32]; + ret = read(fd, buf, sizeof(buf)); + close(fd); + EXPECT_EQ(ret, (ssize_t)sizeof(myContent)); + EXPECT_EQ(0, strcmp(myContent, buf)); + if (fd >= 0) { + fprintf(stderr, "Removing persistent test data, " + "check if reconstructed on reboot\n"); + } + EXPECT_EQ(0, unlink(myFilename)); +} -- cgit v1.2.3