Loading README.md +13 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,16 @@ Running the tests # Or 64-bit device adb shell /data/nativetest64/recovery_unit_test/recovery_unit_test adb shell /data/nativetest64/recovery_component_test/recovery_component_test Running the manual tests ------------------------ `recovery-refresh` and `recovery-persist` executables exist only on systems without /cache partition. And we need to follow special steps to run tests for them. - Execute the test on an A/B device first. The test should fail but it will log some contents to pmsg. - Reboot the device immediately and run the test again. The test should save the contents of pmsg buffer into /data/misc/recovery/inject.txt. Test will pass if this file has expected contents. tests/Android.mk +12 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_SRC_FILES := \ unit/asn1_decoder_test.cpp \ unit/locale_test.cpp \ unit/recovery_test.cpp \ unit/sysutil_test.cpp \ unit/zip_test.cpp Loading @@ -42,6 +41,18 @@ LOCAL_C_INCLUDES := bootable/recovery LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_NATIVE_TEST) # Manual tests include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_CFLAGS := -Werror LOCAL_MODULE := recovery_manual_test LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libbase LOCAL_SRC_FILES := manual/recovery_test.cpp LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_NATIVE_TEST) # Component tests include $(CLEAR_VARS) LOCAL_CFLAGS := -Werror Loading tests/unit/recovery_test.cpp→tests/manual/recovery_test.cpp +87 −0 Original line number Diff line number Diff line Loading @@ -19,12 +19,15 @@ #include <sys/types.h> #include <unistd.h> #include <string> #include <android-base/file.h> #include <android/log.h> #include <gtest/gtest.h> #include <private/android_logger.h> static const char myFilename[] = "/data/misc/recovery/inject.txt"; static const char myContent[] = "Hello World\nWelcome to my recovery\n"; static const std::string myFilename = "/data/misc/recovery/inject.txt"; static const std::string 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 Loading @@ -34,10 +37,10 @@ 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); EXPECT_NE(std::string::npos, myFilename.find(filename)); EXPECT_EQ(myContent, buf); EXPECT_EQ(myContent.size(), len); EXPECT_EQ(nullptr, arg); return len; } Loading @@ -47,16 +50,15 @@ 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); LOG_ID_SYSTEM, ANDROID_LOG_INFO, "recovery/", __pmsg_fn, nullptr); 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 " EXPECT_LT(0, __android_log_pmsg_file_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, myFilename.c_str(), myContent.c_str(), myContent.size())); fprintf(stderr, "injected test data, requires two intervening reboots " "to check for replication\n"); } EXPECT_EQ((ssize_t)sizeof(myContent), ret); EXPECT_EQ(static_cast<ssize_t>(myContent.size()), ret); } // recovery.persist - Requires recovery.inject, then a reboot, then Loading @@ -65,27 +67,21 @@ 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); LOG_ID_SYSTEM, ANDROID_LOG_INFO, "recovery/", __pmsg_fn, nullptr); 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 " EXPECT_LT(0, __android_log_pmsg_file_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, myFilename.c_str(), myContent.c_str(), myContent.size())); 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) { std::string buf; EXPECT_TRUE(android::base::ReadFileToString(myFilename, &buf)); EXPECT_EQ(myContent, buf); if (access(myFilename.c_str(), O_RDONLY) == 0) { fprintf(stderr, "Removing persistent test data, " "check if reconstructed on reboot\n"); } EXPECT_EQ(0, unlink(myFilename)); EXPECT_EQ(0, unlink(myFilename.c_str())); } Loading
README.md +13 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,16 @@ Running the tests # Or 64-bit device adb shell /data/nativetest64/recovery_unit_test/recovery_unit_test adb shell /data/nativetest64/recovery_component_test/recovery_component_test Running the manual tests ------------------------ `recovery-refresh` and `recovery-persist` executables exist only on systems without /cache partition. And we need to follow special steps to run tests for them. - Execute the test on an A/B device first. The test should fail but it will log some contents to pmsg. - Reboot the device immediately and run the test again. The test should save the contents of pmsg buffer into /data/misc/recovery/inject.txt. Test will pass if this file has expected contents.
tests/Android.mk +12 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_SRC_FILES := \ unit/asn1_decoder_test.cpp \ unit/locale_test.cpp \ unit/recovery_test.cpp \ unit/sysutil_test.cpp \ unit/zip_test.cpp Loading @@ -42,6 +41,18 @@ LOCAL_C_INCLUDES := bootable/recovery LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_NATIVE_TEST) # Manual tests include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_CFLAGS := -Werror LOCAL_MODULE := recovery_manual_test LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libbase LOCAL_SRC_FILES := manual/recovery_test.cpp LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_NATIVE_TEST) # Component tests include $(CLEAR_VARS) LOCAL_CFLAGS := -Werror Loading
tests/unit/recovery_test.cpp→tests/manual/recovery_test.cpp +87 −0 Original line number Diff line number Diff line Loading @@ -19,12 +19,15 @@ #include <sys/types.h> #include <unistd.h> #include <string> #include <android-base/file.h> #include <android/log.h> #include <gtest/gtest.h> #include <private/android_logger.h> static const char myFilename[] = "/data/misc/recovery/inject.txt"; static const char myContent[] = "Hello World\nWelcome to my recovery\n"; static const std::string myFilename = "/data/misc/recovery/inject.txt"; static const std::string 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 Loading @@ -34,10 +37,10 @@ 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); EXPECT_NE(std::string::npos, myFilename.find(filename)); EXPECT_EQ(myContent, buf); EXPECT_EQ(myContent.size(), len); EXPECT_EQ(nullptr, arg); return len; } Loading @@ -47,16 +50,15 @@ 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); LOG_ID_SYSTEM, ANDROID_LOG_INFO, "recovery/", __pmsg_fn, nullptr); 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 " EXPECT_LT(0, __android_log_pmsg_file_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, myFilename.c_str(), myContent.c_str(), myContent.size())); fprintf(stderr, "injected test data, requires two intervening reboots " "to check for replication\n"); } EXPECT_EQ((ssize_t)sizeof(myContent), ret); EXPECT_EQ(static_cast<ssize_t>(myContent.size()), ret); } // recovery.persist - Requires recovery.inject, then a reboot, then Loading @@ -65,27 +67,21 @@ 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); LOG_ID_SYSTEM, ANDROID_LOG_INFO, "recovery/", __pmsg_fn, nullptr); 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 " EXPECT_LT(0, __android_log_pmsg_file_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, myFilename.c_str(), myContent.c_str(), myContent.size())); 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) { std::string buf; EXPECT_TRUE(android::base::ReadFileToString(myFilename, &buf)); EXPECT_EQ(myContent, buf); if (access(myFilename.c_str(), O_RDONLY) == 0) { fprintf(stderr, "Removing persistent test data, " "check if reconstructed on reboot\n"); } EXPECT_EQ(0, unlink(myFilename)); EXPECT_EQ(0, unlink(myFilename.c_str())); }