diff --git a/OAT.xml b/OAT.xml index 0cfc6f85984101a02c77fe7ebbd15e9adbbacd7a..62bc1e52b366f0817b98e398d7380a99db126e51 100644 --- a/OAT.xml +++ b/OAT.xml @@ -23,6 +23,7 @@ + diff --git a/begetd.gni b/begetd.gni index 3b74061ca808dc8adcc1993d438841b88e8adfcc..bfa7bf33e6dff6a6829f2f89d2638d196f494ae3 100644 --- a/begetd.gni +++ b/begetd.gni @@ -13,6 +13,8 @@ init_innerkits_path = "//base/startup/init/interfaces/innerkits" +# init ota rollback +init_feature_ota_rollback = true declare_args() { enable_ohos_startup_init_feature_watcher = true enable_ohos_startup_init_feature_deviceinfo = true diff --git a/interfaces/innerkits/fs_manager/BUILD.gn b/interfaces/innerkits/fs_manager/BUILD.gn index e0a93d2e707acc35130857bbf6114f90da355ae7..0b9c81ed08c916370de7f0cd5c40fb5e28a42e11 100755 --- a/interfaces/innerkits/fs_manager/BUILD.gn +++ b/interfaces/innerkits/fs_manager/BUILD.gn @@ -53,11 +53,11 @@ ohos_static_library("libfsmanager_static") { if ((defined(global_parts_info) && defined(global_parts_info.startup_hvb)) || init_startup_feature_erofs_overlay) { - sources += [ + sources += [ "libfs_dm/fs_dm.c", "libfs_dm/fs_dm_linear.c", "libfs_dm/fs_dm_snapshot.c", - ] + ] include_dirs += [ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_dm/include", "//base/startup/init/ueventd/include", @@ -90,6 +90,9 @@ ohos_static_library("libfsmanager_static") { defines += [ "EROFS_OVERLAY" ] } + if (init_feature_ota_rollback) { + defines += [ "OTA_ROLLBACK_SUPPORT" ] + } } public_configs = [ ":libfsmanager_exported_configs" ] @@ -118,6 +121,7 @@ ohos_static_library("libfsmanager_static_real") { "bounds_checking_function:libsec_static", "cJSON:cjson_static", ] + defines = [] deps = [ "//base/startup/init/services/utils:libinit_utils" ] if (defined(global_parts_info) && defined(global_parts_info.startup_hvb)) { sources += [ @@ -136,10 +140,13 @@ ohos_static_library("libfsmanager_static_real") { "//base/startup/init/ueventd/include", ] - defines = [ "SUPPORT_HVB" ] + defines += [ "SUPPORT_HVB" ] external_deps += [ "hvb:libhvb_static" ] deps += [ "//base/startup/init/ueventd:libueventd_ramdisk_static_real" ] } + if (init_feature_ota_rollback) { + defines += [ "OTA_ROLLBACK_SUPPORT" ] + } } public_configs = [ ":libfsmanager_exported_configs" ] diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c index a067b6198f918878ccf1ca7877f833cd218b11be..10e29198cb96bdf2d8662c681f2e771a42543da6 100755 --- a/interfaces/innerkits/fs_manager/fstab_mount.c +++ b/interfaces/innerkits/fs_manager/fstab_mount.c @@ -50,6 +50,8 @@ extern "C" { #define RESIZE_BUFFER_SIZE 1024 const off_t PARTITION_ACTIVE_SLOT_OFFSET = 1024; const off_t PARTITION_ACTIVE_SLOT_SIZE = 4; +const off_t PARTITION_CHECKPOINT_OFFSET = 1032; +const off_t PARTITION_CHECKPOINT_SIZE = 4; int g_bootSlots = -1; int g_currentSlot = -1; @@ -459,6 +461,42 @@ static int GetSlotInfoFromBootctrl(off_t offset, off_t size) return slotInfo; } +static int GetCheckpointFromBootctrl(off_t offset, off_t size) +{ + char bootctrlDev[MAX_BUFFER_LEN] = {0}; + // default checkpoint not set, normal mode + int checkpoint = 0; + // Get bootctrl device path + if (GetBlockDevicePath("/bootctrl", bootctrlDev, MAX_BUFFER_LEN) != 0) { + BEGET_LOGE("Failed to get bootctrl device"); + return -1; + } + char *realPath = GetRealPath(bootctrlDev); + if (realPath == NULL) { + BEGET_LOGE("Failed to get bootctrl device real path"); + return -1; + } + int fd = open(realPath, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + free(realPath); + if (fd < 0) { + BEGET_LOGE("Failed to open bootctrl device, errno %d", errno); + return -1; + } + if (lseek(fd, offset, SEEK_SET) < 0) { + close(fd); + BEGET_LOGE("Failed to lseek bootctrl device fd, errno %d", errno); + return -1; + } + if (read(fd, &checkpoint, sizeof(checkpoint)) != size) { + close(fd); + BEGET_LOGE("Failed to read current checkpoint from bootctrl, errno %d", errno); + return -1; + } + close(fd); + BEGET_LOGI("get checkpoint: %d", checkpoint); + return checkpoint; +} + int GetBootSlots(void) { if (g_bootSlots != -1) { @@ -468,6 +506,33 @@ int GetBootSlots(void) return g_bootSlots; } +int GetCurrentCheckpoint(void) +{ + return GetCheckpointFromBootctrl(PARTITION_CHECKPOINT_OFFSET, PARTITION_CHECKPOINT_SIZE); +} + +#ifdef OTA_ROLLBACK_SUPPORT +static int DoOtaRollBack(FstabItem *item) +{ + // Get the checkpoint of the current bootctrl + if (strcmp(item->mountPoint, "/data") == 0) { + if (GetCurrentCheckpoint() == 1) { + const char *mountPoint = "/data"; + // Remount data, set checkpoint=disable + const char *options = "checkpoint=disable"; + const char *fsType = NULL; + BEGET_LOGI("remount_point = %s.", mountPoint); + int result = mount(mountPoint, mountPoint, fsType, MS_REMOUNT, options); + if (result != 0) { + BEGET_LOGE("Failed to remount /data"); + return -1; + } + } + } + return 0; +} +#endif + int GetCurrentSlot(void) { if (g_currentSlot != -1) { @@ -598,6 +663,13 @@ int MountOneItem(FstabItem *item) if (rc == 0 && (strcmp(item->mountPoint, "/usr") == 0)) { SwitchRoot("/usr"); } +#endif +#ifdef OTA_ROLLBACK_SUPPORT + // OTA rollback data + int ret = DoOtaRollBack(item); + if (ret != 0) { + BEGET_LOGW("Failed to rollback data"); + } #endif if (disableCheckpointRet == 0 && rc == 0) { BEGET_LOGI("start health check process"); diff --git a/interfaces/innerkits/include/fs_manager/fs_manager.h b/interfaces/innerkits/include/fs_manager/fs_manager.h index a77a3a34982f3c365385840d7ef1cfde519255fe..a1d16f3df357548e67f088d55a7d7a0b619a9ef7 100644 --- a/interfaces/innerkits/include/fs_manager/fs_manager.h +++ b/interfaces/innerkits/include/fs_manager/fs_manager.h @@ -92,6 +92,7 @@ typedef struct SlotInfo { Fstab* LoadFstabFromCommandLine(void); int GetBootSlots(void); int GetCurrentSlot(void); +int GetCurrentCheckpoint(void); void ReleaseFstab(Fstab *fstab); Fstab *ReadFstabFromFile(const char *file, bool procMounts); FstabItem *FindFstabItemForPath(Fstab fstab, const char *path); diff --git a/services/begetctl/BUILD.gn b/services/begetctl/BUILD.gn index 77f143fc5167ac17fa2164c9b0d56c36cf1843b2..82ddef1426369d4451632e30d35fa7dba3d0fe61 100755 --- a/services/begetctl/BUILD.gn +++ b/services/begetctl/BUILD.gn @@ -137,7 +137,7 @@ if (defined(ohos_lite)) { if (init_feature_ab_partition) { sources += [ "partitionslot.cpp" ] external_deps += [ - "drivers_interface_partitionslot:libpartitionslot_proxy_1.0", + "drivers_interface_partitionslot:libpartitionslot_proxy_1.1", "hdf_core:libhdi", "hdf_core:libpub_utils", ] diff --git a/services/begetctl/partitionslot.cpp b/services/begetctl/partitionslot.cpp index 2f8ee450b5667c67c715340208820c3d566dd7c5..99c34921878cfbf1adca6d1007491edc5aafde18 100644 --- a/services/begetctl/partitionslot.cpp +++ b/services/begetctl/partitionslot.cpp @@ -17,9 +17,9 @@ #include "begetctl.h" #include "idevmgr_hdi.h" -#include "v1_0/ipartition_slot.h" +#include "v1_1/ipartition_slot.h" -using namespace OHOS::HDI::Partitionslot::V1_0; +using namespace OHOS::HDI::Partitionslot::V1_1; using OHOS::HDI::DeviceManager::V1_0::IDeviceManager; static const int32_t PARTITION_ARGC = 2; diff --git a/services/modules/bootevent/BUILD.gn b/services/modules/bootevent/BUILD.gn index 281d4adf9b700ebf3a2e2de7bfcf9e9bdee9b8fb..ee49f28622f6edd403ca67a799f15fa35a6c7d92 100755 --- a/services/modules/bootevent/BUILD.gn +++ b/services/modules/bootevent/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("//base/startup/init/begetd.gni") import("//build/ohos.gni") config("bootevent_static_config") { @@ -25,6 +26,11 @@ config("bootevent_static_config") { } ohos_source_set("libbootevent_static") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } sources = [ "bootevent.c" ] include_dirs = [ ".." ] include_dirs += [ @@ -33,7 +39,10 @@ ohos_source_set("libbootevent_static") { ] sources += [ "//base/startup/init/services/utils/init_utils.c" ] public_configs = [ ":bootevent_static_config" ] - external_deps = [ "cJSON:cjson" ] + deps = [ "//base/startup/init/services/utils:libinit_utils" ] + defines = [] + external_deps = [] + external_deps += [ "cJSON:cjson" ] public_external_deps = [ "config_policy:configpolicy_util" ] public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ] public_external_deps += [ "bounds_checking_function:libsec_static" ] @@ -43,6 +52,12 @@ ohos_source_set("libbootevent_static") { "selinux:libselinux", "selinux_adapter:librestorecon", ] - defines = [ "WITH_SELINUX" ] + defines += [ "WITH_SELINUX" ] + } + if (init_feature_ota_rollback) { + defines += [ "OTA_ROLLBACK_SUPPORT" ] + external_deps += [ "updater:libotainfo" ] } + part_name = "init" + subsystem_name = "startup" } diff --git a/services/modules/bootevent/bootevent.c b/services/modules/bootevent/bootevent.c index 67b68e5c3e1f3a9238e6d6ab1176d41807bcb1ec..bfcc68881b0840b6ccda62c3d6d11f390d474048 100755 --- a/services/modules/bootevent/bootevent.c +++ b/services/modules/bootevent/bootevent.c @@ -29,10 +29,25 @@ #include "init_cmds.h" #include "config_policy_utils.h" +#ifdef OTA_ROLLBACK_SUPPORT +#include "ota_event/ota_event.h" +#include +#endif + #ifdef WITH_SELINUX #include #endif +#ifdef OTA_ROLLBACK_SUPPORT +enum ReturnSetOtaStatus { + SET_OTA_STATUS_FAILED = -1, // Failed to call SetOTAStatus to set information. + BOOT_SUCCESS_IN_OTA = 0, // In the ota stage, startup is complete. + BOOT_SUCCESS_IN_NORMAL = 1, // In the non-ota stage, startup is complete. + BOOT_FAILD_IN_OTA = 2, // In the ota stage, startup is failed. + BOOT_FAILD_IN_NORMAL = 3, // In the non-ota stage, startup is failed. +}; +#endif + static int GetBootSwitchEnable(const char *paramName) { char bootEventOpen[6] = ""; // 6 is length of bool value @@ -315,6 +330,60 @@ static void WriteBooteventSysParam(const char *paramName) SystemWriteParam(name, buf); } +#ifdef OTA_ROLLBACK_SUPPORT +static int OTARollback(void) +{ + // Determine if the system is starting up abnormally + int retOta = SET_OTA_STATUS_FAILED; + int bootStatus = IsBootCompleted(); + + INIT_LOGI("bootStatus = %d.", bootStatus); + retOta = SetOTAStatus(bootStatus); + if (retOta == SET_OTA_STATUS_FAILED) { + INIT_LOGI("Set OTA status failed."); + return -1; + } + + INIT_LOGI("retOta = %d.", retOta); + const char *mountPoint = "/data"; + const char *fsType = NULL; + const char *options = "checkpoint=enable"; + int result; + + switch (retOta) { + case BOOT_SUCCESS_IN_OTA: + INIT_LOGI("boot success in OTA, start to remount data."); + // remount data, set checkpoint=enable + BEGET_LOGI("remount_point = %s.", mountPoint); + result = mount(mountPoint, mountPoint, fsType, MS_REMOUNT, options); + if (result != 0) { + BEGET_LOGE("Failed to remount /data"); + return -1; + } + break; + + case BOOT_SUCCESS_IN_NORMAL: + INIT_LOGI("boot success in normal, no process."); + break; + + case BOOT_FAILD_IN_OTA: + INIT_LOGI("boot faild in OTA, start to reboot."); + // reboot system + ExecReboot("reboot"); + break; + + case BOOT_FAILD_IN_NORMAL: + INIT_LOGI("boot faild in normal, no process."); + break; + + default: + INIT_LOGI("boot status is unknown."); + break; + } + return 1; +} +#endif + static int BootEventParaFireByName(const char *paramName) { BOOT_EVENT_PARAM_ITEM *found = NULL; @@ -347,6 +416,14 @@ static int BootEventParaFireByName(const char *paramName) INIT_LOGI("All boot events are fired, boot complete now ..."); SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "true"); SetBootCompleted(true); +#ifdef OTA_ROLLBACK_SUPPORT + // First reboot in ota phase, check if rollback is needed + int retOta = OTARollback(); + if (retOta != 1) { + INIT_LOGI("boot failed, no process."); + return 0; + } +#endif SaveServiceBootEvent(); // report complete event ReportSysEvent(); @@ -470,6 +547,14 @@ static int DoUnsetBootEventCmd(int id, const char *name, int argc, const char ** SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "false"); SetBootCompleted(false); g_finished = 0; +#ifdef OTA_ROLLBACK_SUPPORT + // First reboot in ota phase, check if rollback is needed + int retOta = OTARollback(); + if (retOta != 1) { + INIT_LOGI("boot failed, no process."); + return 0; + } +#endif } item->timestamp[BOOTEVENT_READY].tv_sec = 0; diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 51192116318e5918ead865cdc062250c3b85a4d6..4a46b48809c72b57151bf40d9c63708d908b1588 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -116,6 +116,7 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/modules/bootchart/bootchart_static.c", "//base/startup/init/services/modules/bootevent/bootevent.c", "//base/startup/init/services/modules/crashhandler/crash_handler.c", + "//base/startup/init/services/modules/encaps/encaps_static.c", "//base/startup/init/services/modules/init_eng/init_eng.c", "//base/startup/init/services/modules/init_eng/init_eng_static.c", "//base/startup/init/services/modules/init_hook/init_hook.c", @@ -126,7 +127,6 @@ ohos_unittest("init_unittest") { "//base/startup/init/services/modules/udid/udid_adp.c", "//base/startup/init/services/modules/udid/udid_comm.c", "//base/startup/init/services/modules/udid/udid_static.c", - "//base/startup/init/services/modules/encaps/encaps_static.c", "//base/startup/init/services/param/adapter/param_dac.c", "//base/startup/init/services/param/adapter/param_persistadp.c", "//base/startup/init/services/param/base/param_base.c", @@ -372,7 +372,7 @@ ohos_unittest("init_unittest") { if (init_feature_ab_partition) { sources += [ "//base/startup/init/services/begetctl/partitionslot.cpp" ] external_deps += [ - "drivers_interface_partitionslot:libpartitionslot_proxy_1.0", + "drivers_interface_partitionslot:libpartitionslot_proxy_1.1", "hdf_core:libhdi", "hdf_core:libpub_utils", ] @@ -456,6 +456,12 @@ ohos_unittest("init_unittest") { # test atomic operation sources += [ "//base/startup/init/test/unittest/param/atomic_unittest.cpp" ] + # test ota remount data + sources += [ "//base/startup/init/test/unittest/fs_manager/ota_rollback/ota_data_mount_unittest.cpp" ] + + # test ota check boot success + sources += [ "//base/startup/init/test/unittest/fs_manager/ota_rollback/ota_boot_success_unittest.cpp" ] + cflags_cc = [ "-fexceptions" ] } @@ -485,8 +491,8 @@ ohos_unittest("init_dmverify_unittest") { if (defined(global_parts_info) && defined(global_parts_info.startup_hvb)) { external_deps += [ "hvb:libhvb_static" ] sources += [ - "//base/startup/init/test/mock/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c", "//base/startup/init/interfaces/innerkits/fs_manager/dm_verity/dm_verity.c", + "//base/startup/init/test/mock/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c", "//base/startup/init/test/unittest/fs_manager/dm_verify/dm_verify_unittest.cpp", ] } @@ -539,11 +545,11 @@ ohos_unittest("init_fshvb_unittest") { sources += [ "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/fs_hvb.c", "//base/startup/init/interfaces/innerkits/fs_manager/libfs_hvb/hvb_ops.c", - "//base/startup/init/test/unittest/fs_manager/libfs_hvb_unittest.cpp", + "//base/startup/init/test/mock/hvb/libhvb/auth/hvb.c", "//base/startup/init/test/mock/hvb/libhvb/cert/hvb_cert.c", "//base/startup/init/test/mock/hvb/libhvb/crypto/hvb_hash_sha256.c", - "//base/startup/init/test/mock/hvb/libhvb/auth/hvb.c", "//base/startup/init/test/mock/hvb/libhvb/crypto/hvb_sm3.c", + "//base/startup/init/test/unittest/fs_manager/libfs_hvb_unittest.cpp", ] } cflags_cc = [ "-fexceptions" ] diff --git a/test/unittest/fs_manager/ota_rollback/ota_boot_success_unittest.cpp b/test/unittest/fs_manager/ota_rollback/ota_boot_success_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0292294e7d9c6162e1c495659fe7cdc949f1e7ed --- /dev/null +++ b/test/unittest/fs_manager/ota_rollback/ota_boot_success_unittest.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 "securec.h" +#include "bootevent.h" +#include +#include "init_utils.h" +#include +#include +#include +#include +#include + +#define BOOTEVENT_LEN 4 +using namespace std; +using namespace testing::ext; +namespace init_ut { +const char* g_bootEventOta1[] = {"bootEvent1", "bootEvent3"}; +const char* g_bootEventOta2[] = {"bootEvent1", "bootEvent4"}; +const char* g_bootEventOta3[] = {"bootEvent2", "bootEvent3"}; +const char* g_bootEventOta4[] = {"bootEvent2", "bootEvent4"}; + +// Define the possible return values for OTA status +enum ReturnSetOtaStatus { + SET_OTA_STATUS_FAILED = -1, // Failed to call SetOTAStatus to set information. + BOOT_SUCCESS_IN_OTA = 0, // In the ota stage, startup is complete. + BOOT_SUCCESS_IN_NORMAL = 1, // In the non-ota stage, startup is complete. + BOOT_FAILD_IN_OTA = 2, // In the ota stage, startup is failed. + BOOT_FAILD_IN_NORMAL = 3, // In the non-ota stage, startup is failed. +}; + +void SystemReadParam(const char* param, char* value, uint32_t* len) +{ + if (strcmp(param, "bootEvent1") == 0 || strcmp(param, "bootEvent3") == 0) { + int ret = strncpy_s(value, *len, "true", strlen("true")); + if (ret != 0) { + printf("strncpy_s failed\n"); + } + } else if (strcmp(param, "bootEvent2") == 0 || strcmp(param, "bootEvent4") == 0) { + int ret = strncpy_s(value, *len, "false", strlen("false")); + if (ret != 0) { + printf("strncpy_s failed\n"); + } + } else { + int ret = strncpy_s(value, *len, "unknown", strlen("unknown")); + if (ret != 0) { + printf("strncpy_s failed\n"); + } + } +} +static int BootEventJudgeBootComplete1(void) +{ + char value[6] = ""; + uint32_t len = sizeof(value); + int booteventLength = sizeof(g_bootEventOta1) / sizeof(g_bootEventOta1[0]); + + for (int i = 0; i < booteventLength; i++) { + SystemReadParam(g_bootEventOta1[i], value, &len); + if (strncmp(value, "true", BOOTEVENT_LEN) != 0) { + return 0; + } + } + return 1; +} +static int BootEventJudgeBootComplete2(void) +{ + char value[6] = ""; + uint32_t len = sizeof(value); + int booteventLength = sizeof(g_bootEventOta2) / sizeof(g_bootEventOta2[0]); + + for (int i = 0; i < booteventLength; i++) { + SystemReadParam(g_bootEventOta2[i], value, &len); + if (strncmp(value, "true", BOOTEVENT_LEN) != 0) { + return 0; + } + } + return 1; +} +static int BootEventJudgeBootComplete3(void) +{ + char value[6] = ""; + uint32_t len = sizeof(value); + int booteventLength = sizeof(g_bootEventOta3) / sizeof(g_bootEventOta3[0]); + + for (int i = 0; i < booteventLength; i++) { + SystemReadParam(g_bootEventOta3[i], value, &len); + if (strncmp(value, "true", BOOTEVENT_LEN) != 0) { + return 0; + } + } + return 1; +} + +static int BootEventJudgeBootComplete4(void) +{ + char value[6] = ""; + uint32_t len = sizeof(value); + int booteventLength = sizeof(g_bootEventOta4) / sizeof(g_bootEventOta4[0]); + + for (int i = 0; i < booteventLength; i++) { + SystemReadParam(g_bootEventOta4[i], value, &len); + if (strncmp(value, "true", BOOTEVENT_LEN) != 0) { + return 0; + } + } + return 1; +} +void RebootSystem() +{ + printf("System is rebooting...\n"); +} +int Mount(const char *source, const char *target, const char *filesystemtype, + unsigned long mountflags, const void *data) +{ + return 0; // Simulate successful mount +} +static int HandleBootStatus(int retOta) +{ + switch (retOta) { + case BOOT_SUCCESS_IN_OTA: + { + const char *mountPoint = "/data"; + const char *fsType = "f2fs"; + const char *options = "checkpoint=enable"; + int result = Mount(mountPoint, mountPoint, fsType, MS_REMOUNT, options); + if (result != 0) { + return -1; + } + printf("boot success in normal, no process.\n"); + break; + } + + case BOOT_SUCCESS_IN_NORMAL: + printf("boot success in normal, no process.\n"); + break; + + case BOOT_FAILD_IN_OTA: + printf("boot faild in OTA, start to reboot.\n"); + RebootSystem(); + break; + + case BOOT_FAILD_IN_NORMAL: + printf("boot faild in normal, no process.\n"); + break; + + case SET_OTA_STATUS_FAILED: + printf("Set OTA status failed, no process.\n"); + break; + + default: + printf("Unknown boot status, no process.\n"); + break; + } + return 1; +} +class OtaRollbackUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + cout << "OTA Rollback Unittest Begin!" << endl; + }; + static void TearDownTestCase(void) + { + cout << "OTA Rollback Unittest End!" << endl; + }; + void SetUp(void) {}; + void TearDown(void) {}; +}; +HWTEST_F(OtaRollbackUnitTest, BootEventJudgeBootComplete_001, TestSize.Level0) +{ + int result1 = BootEventJudgeBootComplete1(); + EXPECT_EQ(result1, 1); + + int result2 = BootEventJudgeBootComplete2(); + EXPECT_EQ(result2, 0); + + int result3 = BootEventJudgeBootComplete3(); + EXPECT_EQ(result3, 0); + + int result4 = BootEventJudgeBootComplete4(); + EXPECT_EQ(result4, 0); +} + +HWTEST_F(OtaRollbackUnitTest, Init_OtaRollback_001, TestSize.Level0) +{ + int result1 = HandleBootStatus(BOOT_SUCCESS_IN_OTA); + EXPECT_EQ(result1, 1); + + int result2 = HandleBootStatus(BOOT_SUCCESS_IN_NORMAL); + EXPECT_EQ(result2, 1); + + int result3 = HandleBootStatus(BOOT_FAILD_IN_OTA); + EXPECT_EQ(result3, 1); + + int result4 = HandleBootStatus(BOOT_FAILD_IN_NORMAL); + EXPECT_EQ(result4, 1); + + int result5 = HandleBootStatus(SET_OTA_STATUS_FAILED); + EXPECT_EQ(result5, 1); + + int result6 = HandleBootStatus(999); + EXPECT_EQ(result6, 1); + + int result7 = HandleBootStatus(-1); + EXPECT_EQ(result7, 1); +} +} diff --git a/test/unittest/fs_manager/ota_rollback/ota_data_mount_unittest.cpp b/test/unittest/fs_manager/ota_rollback/ota_data_mount_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8cc111ec16f09c35f9826577a598ee9a6d7d77ec --- /dev/null +++ b/test/unittest/fs_manager/ota_rollback/ota_data_mount_unittest.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd. + * 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 "fs_manager/fs_manager.h" +#include +#include "init_utils.h" +#include +#include +#include +#include +#include + +using namespace std; +using namespace testing::ext; +namespace init_ut { +struct Item { + const char *mountPoint; + const char *fsType; +}; +class OtaDataRemountUnitTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + cout << "OTA Data Remount Unittest Begin!" << endl; + }; + static void TearDownTestCase(void) + { + cout << "OTA Data Remount Unittest End!" << endl; + }; + void SetUp(void) {}; + void TearDown(void) {}; +}; +HWTEST_F(OtaDataRemountUnitTest, Init_OtaDataRemount_001, TestSize.Level0) +{ + Item item = {"/data", "f2fs"}; + const char *options = "checkpoint=disable"; + int result = mount(item.mountPoint, item.mountPoint, item.fsType, MS_REMOUNT, options); + EXPECT_EQ(result, 0); + + Item item1 = {"/data", "ext4"}; + int result1 = mount(item1.mountPoint, item1.mountPoint, item1.fsType, MS_REMOUNT, options); + EXPECT_EQ(result1, 0); + + Item item2 = {"/data", "unknown_fs"}; + int result2 = mount(item2.mountPoint, item2.mountPoint, item2.fsType, MS_REMOUNT, options); + EXPECT_EQ(result2, 0); +} + +HWTEST_F(OtaDataRemountUnitTest, Init_OtaDataRemount_002, TestSize.Level0) +{ + Item item = {"/data", "f2fs"}; + const char *options = "checkpoint=enable"; + int result = mount(item.mountPoint, item.mountPoint, item.fsType, MS_REMOUNT, options); + EXPECT_EQ(result, 0); + + Item item1 = {"/data", "ext4"}; + int result1 = mount(item1.mountPoint, item1.mountPoint, item1.fsType, MS_REMOUNT, options); + EXPECT_EQ(result1, 0); + + Item item2 = {"/data", "unknown_fs"}; + int result2 = mount(item2.mountPoint, item2.mountPoint, item2.fsType, MS_REMOUNT, options); + EXPECT_EQ(result2, 0); +} + +}