diff --git a/backup_logs/unittest/backup_engine_gtest.cpp b/backup_logs/unittest/backup_engine_gtest.cpp index d7acf25d3..a9d696b11 100644 --- a/backup_logs/unittest/backup_engine_gtest.cpp +++ b/backup_logs/unittest/backup_engine_gtest.cpp @@ -19,7 +19,7 @@ /** * @file backup_engine_gtest.cpp * @brief Comprehensive Google Test suite for backup_engine.c - * + * * This test suite validates the backup engine functionality with comprehensive * mock testing and edge case coverage. */ @@ -34,7 +34,7 @@ #include extern "C" { - #include "backup_engine.h" + #include "backup_engine.h" #include "backup_types.h" } @@ -49,51 +49,51 @@ using ::testing::StrictMock; static struct { // RDK_LOG mock control volatile bool rdk_log_enabled = false; - + // Directory operation mock controls volatile DIR* opendir_return = nullptr; volatile bool opendir_called = false; char opendir_last_path[PATH_MAX] = {0}; - + volatile struct dirent* readdir_return = nullptr; volatile bool readdir_called = false; volatile int readdir_call_count = 0; - + volatile int closedir_return = 0; volatile bool closedir_called = false; - + // File operation mock controls volatile int filePresentCheck_return = -1; // Default: file not present volatile bool filePresentCheck_called = false; char filePresentCheck_last_path[PATH_MAX] = {0}; - + volatile int createDir_return = 0; volatile bool createDir_called = false; char createDir_last_path[PATH_MAX] = {0}; - + volatile int copyFiles_return = 0; volatile bool copyFiles_called = false; char copyFiles_last_source[PATH_MAX] = {0}; char copyFiles_last_dest[PATH_MAX] = {0}; - + volatile int remove_return = 0; volatile bool remove_called = false; char remove_last_path[PATH_MAX] = {0}; - + volatile FILE *fopen_return = nullptr; volatile bool fopen_called = false; char fopen_last_filename[PATH_MAX] = {0}; char fopen_last_mode[16] = {0}; - + volatile int fclose_return = 0; volatile bool fclose_called = false; - + // System operation mock controls volatile int stat_return = 0; volatile bool stat_called = false; char stat_last_path[PATH_MAX] = {0}; volatile mode_t stat_mode = S_IFREG; // Default: regular file - + // open/fstat/close mock controls (used by backup_and_recover_logs) volatile int open_return = 3; // Default: valid fd volatile bool open_called = false; @@ -101,18 +101,18 @@ static struct { volatile bool fstat_called = false; volatile int close_return = 0; volatile bool close_called = false; - + // Time operation mock controls volatile time_t time_return = 1234567890; // Fixed timestamp volatile bool time_called = false; - + volatile struct tm* localtime_return = nullptr; volatile bool localtime_called = false; - + volatile size_t strftime_return = 0; volatile bool strftime_called = false; char strftime_last_format[64] = {0}; - + // Special files operation mock controls volatile bool special_files_init_called = false; volatile int special_files_load_config_return = BACKUP_SUCCESS; @@ -120,14 +120,14 @@ static struct { volatile int special_files_execute_all_return = BACKUP_SUCCESS; volatile bool special_files_execute_all_called = false; volatile bool special_files_cleanup_called = false; - + // System integration mock controls volatile bool sys_send_systemd_notification_called = false; char sys_send_systemd_notification_last_message[256] = {0}; - + // Control flag for safe path copying volatile bool safe_to_copy_paths = false; - + // Mock directory entries for readdir simulation struct dirent mock_entries[10]; volatile int mock_entry_count = 0; @@ -145,7 +145,7 @@ extern "C" { (void)level; (void)module; (void)format; mock_control.rdk_log_enabled = true; } - + // Directory operation mocks DIR* __wrap_opendir(const char *name) { mock_control.opendir_called = true; @@ -157,24 +157,24 @@ extern "C" { } return mock_control.opendir_return; } - + struct dirent* __wrap_readdir(DIR *dirp) { (void)dirp; mock_control.readdir_called = true; mock_control.readdir_call_count++; - + if (mock_control.mock_entry_index < mock_control.mock_entry_count) { return &mock_control.mock_entries[mock_control.mock_entry_index++]; } return nullptr; // End of directory } - + int __wrap_closedir(DIR *dirp) { (void)dirp; mock_control.closedir_called = true; return mock_control.closedir_return; } - + // File operation mocks int __wrap_filePresentCheck(char *path) { mock_control.filePresentCheck_called = true; @@ -186,7 +186,7 @@ extern "C" { } return mock_control.filePresentCheck_return; } - + int __wrap_createDir(char *path) { mock_control.createDir_called = true; if (mock_control.safe_to_copy_paths && path != nullptr) { @@ -197,7 +197,7 @@ extern "C" { } return mock_control.createDir_return; } - + int __wrap_copyFiles(const char *source, const char *dest) { mock_control.copyFiles_called = true; if (mock_control.safe_to_copy_paths && source != nullptr && dest != nullptr) { @@ -211,7 +211,7 @@ extern "C" { } return mock_control.copyFiles_return; } - + int __wrap_remove(const char *pathname) { mock_control.remove_called = true; if (mock_control.safe_to_copy_paths && pathname != nullptr) { @@ -222,7 +222,7 @@ extern "C" { } return mock_control.remove_return; } - + FILE* __wrap_fopen(const char *filename, const char *mode) { mock_control.fopen_called = true; if (filename) { @@ -239,13 +239,13 @@ extern "C" { } return mock_control.fopen_return; } - + int __wrap_fclose(FILE *fp) { (void)fp; mock_control.fclose_called = true; return mock_control.fclose_return; } - + // System operation mocks int __wrap_stat(const char *pathname, struct stat *statbuf) { mock_control.stat_called = true; @@ -255,19 +255,19 @@ extern "C" { } else { strcpy(mock_control.stat_last_path, ""); } - + if (mock_control.stat_return == 0 && statbuf) { memset(statbuf, 0, sizeof(struct stat)); statbuf->st_mode = mock_control.stat_mode; } return mock_control.stat_return; } - + // Real function declarations for forwarding non-test calls extern int __real_open(const char *pathname, int flags, ...); extern int __real_fstat(int fd, struct stat *statbuf); extern int __real_close(int fd); - + // open/fstat/close mocks (used by backup_and_recover_logs for file type check) // These forward to real implementations except when open_return is set (non-zero). int __wrap_open(const char *pathname, int flags, ...) { @@ -282,7 +282,7 @@ extern "C" { } return __real_open(pathname, flags); } - + int __wrap_fstat(int fd, struct stat *statbuf) { if (fd == mock_control.open_return && mock_control.open_return > 0) { mock_control.fstat_called = true; @@ -294,7 +294,7 @@ extern "C" { } return __real_fstat(fd, statbuf); } - + int __wrap_close(int fd) { if (fd == mock_control.open_return && mock_control.open_return > 0) { mock_control.close_called = true; @@ -302,7 +302,7 @@ extern "C" { } return __real_close(fd); } - + // Time operation mocks time_t __wrap_time(time_t *tloc) { mock_control.time_called = true; @@ -311,33 +311,33 @@ extern "C" { } return mock_control.time_return; } - + struct tm* __wrap_localtime(const time_t *timep) { (void)timep; mock_control.localtime_called = true; return mock_control.localtime_return; } - + size_t __wrap_strftime(char *s, size_t max, const char *format, const struct tm *tm) { mock_control.strftime_called = true; if (format) { strncpy(mock_control.strftime_last_format, format, sizeof(mock_control.strftime_last_format) - 1); mock_control.strftime_last_format[sizeof(mock_control.strftime_last_format) - 1] = '\0'; } - + if (s && mock_control.strftime_return > 0 && mock_control.strftime_return < max) { strcpy(s, "01-01-24-12-00-00AM"); // Mock timestamp } (void)tm; return mock_control.strftime_return; } - + // Special files operation mocks int __wrap_special_files_init(void) { mock_control.special_files_init_called = true; return BACKUP_SUCCESS; } - + int __wrap_special_files_load_config(special_files_config_t *config, const char *config_file) { (void)config_file; mock_control.special_files_load_config_called = true; @@ -346,25 +346,28 @@ extern "C" { } return mock_control.special_files_load_config_return; } - + int __wrap_special_files_execute_all(const special_files_config_t *config, const backup_config_t *backup_config) { (void)config; (void)backup_config; mock_control.special_files_execute_all_called = true; return mock_control.special_files_execute_all_return; } - + void __wrap_special_files_cleanup(void) { mock_control.special_files_cleanup_called = true; } - + // System integration mocks int __wrap_sys_send_systemd_notification(const char *message) { mock_control.sys_send_systemd_notification_called = true; if (message) { - strncpy(mock_control.sys_send_systemd_notification_last_message, message, + strncpy(mock_control.sys_send_systemd_notification_last_message, message, sizeof(mock_control.sys_send_systemd_notification_last_message) - 1); mock_control.sys_send_systemd_notification_last_message[sizeof(mock_control.sys_send_systemd_notification_last_message) - 1] = '\0'; + } else { + mock_control.sys_send_systemd_notification_last_message[0] = '\0'; } + return 0; // Return success } } @@ -373,12 +376,25 @@ extern "C" { // ================================================================================================ void setup_mock_directory_entries(const char* names[], int count) { - mock_control.mock_entry_count = count; + // Reset directory entry state + mock_control.mock_entry_count = 0; mock_control.mock_entry_index = 0; + memset(mock_control.mock_entries, 0, sizeof(mock_control.mock_entries)); - for (int i = 0; i < count && i < 10; i++) { - memset(&mock_control.mock_entries[i], 0, sizeof(struct dirent)); - strncpy(mock_control.mock_entries[i].d_name, names[i], sizeof(mock_control.mock_entries[i].d_name) - 1); + if (names == nullptr || count < 0) { + return; + } + + // Safely copy entries with bounds checking + int safe_count = (count > 10) ? 10 : count; + mock_control.mock_entry_count = safe_count; + + for (int i = 0; i < safe_count; i++) { + if (names[i] != nullptr) { + strncpy(mock_control.mock_entries[i].d_name, names[i], + sizeof(mock_control.mock_entries[i].d_name) - 1); + mock_control.mock_entries[i].d_name[sizeof(mock_control.mock_entries[i].d_name) - 1] = '\0'; + } } } @@ -394,7 +410,7 @@ void setup_default_time_mocks() { .tm_yday = 0, .tm_isdst = 0 }; - + mock_control.localtime_return = &test_tm; mock_control.strftime_return = 18; // Length of "01-01-24-12-00-00AM" } @@ -413,7 +429,7 @@ class BackupEngineTest : public ::testing::Test { mock_control.open_return = 100; // Mock fd for open/fstat/close interception mock_control.fopen_return = (FILE*)0x12345678; // Valid fake pointer setup_default_time_mocks(); - + // Initialize test config memset(&test_config, 0, sizeof(test_config)); strcpy(test_config.log_path, "/opt/logs"); @@ -424,7 +440,11 @@ class BackupEngineTest : public ::testing::Test { } void TearDown() override { - // Clean up any test state + // Reset mock control to prevent memory corruption between tests + memset(&mock_control, 0, sizeof(mock_control)); + mock_control.filePresentCheck_return = -1; // Reset defaults + mock_control.stat_mode = S_IFREG; + mock_control.open_return = 100; } backup_config_t test_config; @@ -437,15 +457,15 @@ class BackupEngineTest : public ::testing::Test { TEST_F(BackupEngineTest, MoveLogFilesByPattern_Success) { const char* mock_files[] = {"messages.txt", "system.log", "bootlog", "config.conf", "data.bin"}; setup_mock_directory_entries(mock_files, 5); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.filePresentCheck_return = 0; // Files exist mock_control.copyFiles_return = 0; // Copy succeeds mock_control.remove_return = 0; // Remove succeeds mock_control.safe_to_copy_paths = true; - + int result = move_log_files_by_pattern("/opt/logs", "/opt/logs/PreviousLogs"); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.opendir_called); EXPECT_TRUE(mock_control.copyFiles_called); @@ -455,9 +475,9 @@ TEST_F(BackupEngineTest, MoveLogFilesByPattern_Success) { TEST_F(BackupEngineTest, MoveLogFilesByPattern_OpenDirFails) { mock_control.opendir_return = nullptr; // opendir fails - + int result = move_log_files_by_pattern("/opt/logs", "/opt/logs/PreviousLogs"); - + EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); EXPECT_TRUE(mock_control.opendir_called); EXPECT_FALSE(mock_control.copyFiles_called); @@ -466,12 +486,12 @@ TEST_F(BackupEngineTest, MoveLogFilesByPattern_OpenDirFails) { TEST_F(BackupEngineTest, MoveLogFilesByPattern_NoMatchingFiles) { const char* mock_files[] = {"config.conf", "data.bin"}; setup_mock_directory_entries(mock_files, 2); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.filePresentCheck_return = 0; - + int result = move_log_files_by_pattern("/opt/logs", "/opt/logs/PreviousLogs"); - + EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); // No files moved EXPECT_TRUE(mock_control.opendir_called); EXPECT_FALSE(mock_control.copyFiles_called); @@ -480,13 +500,13 @@ TEST_F(BackupEngineTest, MoveLogFilesByPattern_NoMatchingFiles) { TEST_F(BackupEngineTest, MoveLogFilesByPattern_CopyFails) { const char* mock_files[] = {"messages.txt"}; setup_mock_directory_entries(mock_files, 1); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.filePresentCheck_return = 0; mock_control.copyFiles_return = -1; // Copy fails - + int result = move_log_files_by_pattern("/opt/logs", "/opt/logs/PreviousLogs"); - + EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); EXPECT_TRUE(mock_control.copyFiles_called); EXPECT_FALSE(mock_control.remove_called); // Remove not called if copy fails @@ -501,9 +521,9 @@ TEST_F(BackupEngineTest, HDDEnabledStrategy_FirstTime) { mock_control.opendir_return = (DIR*)0x12345678; mock_control.fopen_return = (FILE*)0x12345678; mock_control.safe_to_copy_paths = true; - + int result = backup_execute_hdd_enabled_strategy(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.filePresentCheck_called); EXPECT_TRUE(mock_control.fopen_called); // Creates last_reboot file @@ -516,13 +536,13 @@ TEST_F(BackupEngineTest, HDDEnabledStrategy_SubsequentBackup) { mock_control.createDir_return = 0; mock_control.fopen_return = (FILE*)0x12345678; mock_control.safe_to_copy_paths = true; - + // Setup directory entries with last_reboot file const char* mock_files[] = {"last_reboot", "messages.txt"}; setup_mock_directory_entries(mock_files, 2); - + int result = backup_execute_hdd_enabled_strategy(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.createDir_called); // Creates timestamped directory EXPECT_TRUE(mock_control.time_called); @@ -535,9 +555,9 @@ TEST_F(BackupEngineTest, HDDEnabledStrategy_PathTooLong) { backup_config_t long_config = test_config; memset(long_config.prev_log_path, 'A', PATH_MAX - 5); long_config.prev_log_path[PATH_MAX - 5] = '\0'; - + int result = backup_execute_hdd_enabled_strategy(&long_config); - + EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); } @@ -550,9 +570,9 @@ TEST_F(BackupEngineTest, HDDDisabledStrategy_FirstTime) { mock_control.opendir_return = (DIR*)0x12345678; mock_control.fopen_return = (FILE*)0x12345678; mock_control.safe_to_copy_paths = true; - + int result = backup_execute_hdd_disabled_strategy(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.filePresentCheck_called); EXPECT_TRUE(mock_control.fopen_called); // Creates last_reboot @@ -561,16 +581,16 @@ TEST_F(BackupEngineTest, HDDDisabledStrategy_FirstTime) { TEST_F(BackupEngineTest, HDDDisabledStrategy_SecondTime) { // First call: messages.txt exists, bak1 doesn't mock_control.filePresentCheck_return = 0; // messages.txt exists - + // Need to simulate multiple filePresentCheck calls with different return values // This is a simplified test - in reality we'd need more sophisticated mock behavior - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.fopen_return = (FILE*)0x12345678; mock_control.safe_to_copy_paths = true; - + int result = backup_execute_hdd_disabled_strategy(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -578,9 +598,9 @@ TEST_F(BackupEngineTest, HDDDisabledStrategy_PathTooLong) { backup_config_t long_config = test_config; memset(long_config.prev_log_path, 'A', PATH_MAX - 5); long_config.prev_log_path[PATH_MAX - 5] = '\0'; - + int result = backup_execute_hdd_disabled_strategy(&long_config); - + EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); } @@ -591,17 +611,17 @@ TEST_F(BackupEngineTest, HDDDisabledStrategy_PathTooLong) { TEST_F(BackupEngineTest, BackupAndRecoverLogs_MoveOperation) { const char* mock_files[] = {"messages.txt", "system.log"}; setup_mock_directory_entries(mock_files, 2); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.stat_return = 0; // stat succeeds mock_control.stat_mode = S_IFREG; // Regular file mock_control.copyFiles_return = 0; // Copy succeeds mock_control.remove_return = 0; // Remove succeeds mock_control.safe_to_copy_paths = true; - - int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", + + int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", BACKUP_OP_MOVE, "", ""); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.opendir_called); EXPECT_TRUE(mock_control.stat_called); @@ -612,16 +632,16 @@ TEST_F(BackupEngineTest, BackupAndRecoverLogs_MoveOperation) { TEST_F(BackupEngineTest, BackupAndRecoverLogs_CopyOperation) { const char* mock_files[] = {"messages.txt"}; setup_mock_directory_entries(mock_files, 1); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.stat_return = 0; mock_control.stat_mode = S_IFREG; mock_control.copyFiles_return = 0; mock_control.safe_to_copy_paths = true; - - int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", + + int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", BACKUP_OP_COPY, "", ""); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.copyFiles_called); EXPECT_FALSE(mock_control.remove_called); // No remove for copy operation @@ -630,16 +650,16 @@ TEST_F(BackupEngineTest, BackupAndRecoverLogs_CopyOperation) { TEST_F(BackupEngineTest, BackupAndRecoverLogs_WithPrefixes) { const char* mock_files[] = {"bak1_messages.txt", "bak1_system.log", "other.txt"}; setup_mock_directory_entries(mock_files, 3); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.stat_return = 0; mock_control.stat_mode = S_IFREG; mock_control.copyFiles_return = 0; mock_control.safe_to_copy_paths = true; - - int result = backup_and_recover_logs("/opt/logs/PreviousLogs/", "/opt/logs/PreviousLogs/", + + int result = backup_and_recover_logs("/opt/logs/PreviousLogs/", "/opt/logs/PreviousLogs/", BACKUP_OP_MOVE, "bak1_", "bak2_"); - + EXPECT_EQ(result, BACKUP_SUCCESS); // Should process only files starting with "bak1_" } @@ -647,70 +667,74 @@ TEST_F(BackupEngineTest, BackupAndRecoverLogs_WithPrefixes) { TEST_F(BackupEngineTest, BackupAndRecoverLogs_SkipDirectories) { const char* mock_files[] = {"messages.txt", "subdir"}; setup_mock_directory_entries(mock_files, 2); - + mock_control.opendir_return = (DIR*)0x12345678; - + // First stat call returns regular file, second returns directory static int stat_call_count = 0; stat_call_count = 0; mock_control.stat_return = 0; // Need to set up different modes for different files - this is simplified mock_control.stat_mode = S_IFREG; // Will be regular file for first call - + mock_control.copyFiles_return = 0; mock_control.safe_to_copy_paths = true; - - int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", + + int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", BACKUP_OP_COPY, "", ""); - + EXPECT_EQ(result, BACKUP_SUCCESS); } TEST_F(BackupEngineTest, BackupAndRecoverLogs_OpenDirFails) { mock_control.opendir_return = nullptr; // opendir fails - - int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", + + int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", BACKUP_OP_MOVE, "", ""); - + EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); EXPECT_TRUE(mock_control.opendir_called); } TEST_F(BackupEngineTest, BackupAndRecoverLogs_NoFiles) { setup_mock_directory_entries(nullptr, 0); // No files - + mock_control.opendir_return = (DIR*)0x12345678; - - int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", + + int result = backup_and_recover_logs("/opt/logs/", "/opt/logs/PreviousLogs/", BACKUP_OP_MOVE, "", ""); - + EXPECT_EQ(result, BACKUP_SUCCESS); // Success if no files found } // ================================================================================================ -// backup_execute_common_operations() Tests +// backup_execute_common_operations() Tests // ================================================================================================ TEST_F(BackupEngineTest, CommonOperations_Success) { mock_control.special_files_load_config_return = BACKUP_SUCCESS; mock_control.special_files_execute_all_return = BACKUP_SUCCESS; - + int result = backup_execute_common_operations(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(mock_control.special_files_init_called); EXPECT_TRUE(mock_control.special_files_load_config_called); EXPECT_TRUE(mock_control.special_files_execute_all_called); EXPECT_TRUE(mock_control.sys_send_systemd_notification_called); EXPECT_TRUE(mock_control.special_files_cleanup_called); + + // Ensure string is properly null-terminated before comparison + mock_control.sys_send_systemd_notification_last_message[ + sizeof(mock_control.sys_send_systemd_notification_last_message) - 1] = '\0'; EXPECT_STREQ(mock_control.sys_send_systemd_notification_last_message, "Logs Backup Done..!"); } TEST_F(BackupEngineTest, CommonOperations_ConfigLoadFails) { mock_control.special_files_load_config_return = BACKUP_ERROR_CONFIG; - + int result = backup_execute_common_operations(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); // Still succeeds even if special files config fails EXPECT_TRUE(mock_control.special_files_init_called); EXPECT_TRUE(mock_control.special_files_load_config_called); @@ -722,9 +746,9 @@ TEST_F(BackupEngineTest, CommonOperations_ConfigLoadFails) { TEST_F(BackupEngineTest, CommonOperations_ExecuteAllFails) { mock_control.special_files_load_config_return = BACKUP_SUCCESS; mock_control.special_files_execute_all_return = BACKUP_ERROR_FILESYSTEM; - + int result = backup_execute_common_operations(&test_config); - + EXPECT_EQ(result, BACKUP_SUCCESS); // Still succeeds even if execute fails EXPECT_TRUE(mock_control.special_files_execute_all_called); } @@ -737,10 +761,10 @@ TEST_F(BackupEngineTest, TimeOperations_FailureHandling) { mock_control.localtime_return = nullptr; // localtime fails mock_control.filePresentCheck_return = 0; // Trigger subsequent backup path mock_control.opendir_return = (DIR*)0x12345678; - + // Should handle gracefully even if time operations fail int result = backup_execute_hdd_enabled_strategy(&test_config); - + EXPECT_TRUE(mock_control.time_called); EXPECT_TRUE(mock_control.localtime_called); // Function should still attempt to continue @@ -749,14 +773,14 @@ TEST_F(BackupEngineTest, TimeOperations_FailureHandling) { TEST_F(BackupEngineTest, FileOperations_EdgeCases) { const char* mock_files[] = {".txt", "file.txt.backup", "file.log.old"}; setup_mock_directory_entries(mock_files, 3); - + mock_control.opendir_return = (DIR*)0x12345678; mock_control.filePresentCheck_return = 0; mock_control.copyFiles_return = 0; mock_control.safe_to_copy_paths = true; - + int result = move_log_files_by_pattern("/opt/logs", "/opt/logs/PreviousLogs"); - + EXPECT_EQ(result, BACKUP_SUCCESS); // All files contain .txt or .log so should be processed } diff --git a/backup_logs/unittest/special_files_gtest.cpp b/backup_logs/unittest/special_files_gtest.cpp index bff2dc5ec..d030b2e5d 100644 --- a/backup_logs/unittest/special_files_gtest.cpp +++ b/backup_logs/unittest/special_files_gtest.cpp @@ -1,8 +1,5 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2026 RDK Management +/** + * Copyright 2024 Comcast Cable Communications Management, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +12,10 @@ * 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. + * + * SPDX-License-Identifier: Apache-2.0 */ - #include #include #include @@ -89,16 +87,16 @@ extern "C" { if (mock_fgets_return_null || mock_fgets_call_count == 0) { return nullptr; } - + mock_fgets_call_count--; strncpy(s, mock_fgets_buffer, size - 1); s[size - 1] = '\0'; - + // Return NULL next time to simulate EOF if (mock_fgets_call_count == 0) { mock_fgets_return_null = true; } - + return s; } @@ -119,7 +117,7 @@ class SpecialFilesTest : public ::testing::Test { mock_fgets_call_count = 0; mock_fgets_return_null = false; memset(mock_fgets_buffer, 0, sizeof(mock_fgets_buffer)); - + // Initialize test structures memset(&test_config, 0, sizeof(test_config)); memset(&test_entry, 0, sizeof(test_entry)); @@ -181,7 +179,7 @@ TEST_F(SpecialFilesTest, LoadConfig_NullParameters) { // Test special_files_load_config with missing config file TEST_F(SpecialFilesTest, LoadConfig_MissingFile) { mock_fopen_return = nullptr; // Simulate fopen failure - + int result = special_files_load_config(&test_config, "nonexistent_file.txt"); EXPECT_EQ(result, BACKUP_ERROR_CONFIG); EXPECT_FALSE(test_config.config_loaded); @@ -193,13 +191,13 @@ TEST_F(SpecialFilesTest, LoadConfig_ValidFile) { // Set up mock to simulate successful file operations FILE dummy_file; mock_fopen_return = &dummy_file; - + // Set up mock fgets to return test data strcpy(mock_fgets_buffer, "/tmp/test_file.log\n"); mock_fgets_call_count = 1; // One data line, then EOF - + int result = special_files_load_config(&test_config, "test_config.txt"); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(test_config.config_loaded); EXPECT_EQ(test_config.count, 1); @@ -212,7 +210,7 @@ TEST_F(SpecialFilesTest, LoadConfig_ValidFile) { TEST_F(SpecialFilesTest, LoadConfig_SkipCommentsAndEmptyLines) { FILE dummy_file; mock_fopen_return = &dummy_file; - + // Mock multiple fgets calls const vector lines = { "# This is a comment\n", @@ -221,13 +219,13 @@ TEST_F(SpecialFilesTest, LoadConfig_SkipCommentsAndEmptyLines) { " \n", // Empty line with spaces "# Another comment\n" }; - + // For simplicity, we'll test with one valid line strcpy(mock_fgets_buffer, "/tmp/valid_file.log\n"); mock_fgets_call_count = 1; // One valid line, then EOF - + int result = special_files_load_config(&test_config, "test_config.txt"); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(test_config.config_loaded); EXPECT_EQ(test_config.count, 1); @@ -239,13 +237,13 @@ TEST_F(SpecialFilesTest, LoadConfig_SkipCommentsAndEmptyLines) { TEST_F(SpecialFilesTest, LoadConfig_PathParsing) { FILE dummy_file; mock_fopen_return = &dummy_file; - + // Test file with full path strcpy(mock_fgets_buffer, "/opt/logs/system/app.log\n"); mock_fgets_call_count = 1; // One data line, then EOF - + int result = special_files_load_config(&test_config, "test_config.txt"); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_STREQ(test_config.entries[0].source_path, "/opt/logs/system/app.log"); EXPECT_STREQ(test_config.entries[0].destination_path, "app.log"); @@ -282,7 +280,7 @@ TEST_F(SpecialFilesTest, ValidateEntry_EmptyPaths) { TEST_F(SpecialFilesTest, ValidateEntry_ValidEntry) { strcpy(test_entry.source_path, "/tmp/source.log"); strcpy(test_entry.destination_path, "dest.log"); - + int result = special_files_validate_entry(&test_entry); EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -298,7 +296,7 @@ TEST_F(SpecialFilesTest, ExecuteEntry_InvalidEntry) { // Empty source path test_entry.source_path[0] = '\0'; strcpy(test_entry.destination_path, "dest.log"); - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_ERROR_CONFIG); } @@ -307,9 +305,9 @@ TEST_F(SpecialFilesTest, ExecuteEntry_InvalidEntry) { TEST_F(SpecialFilesTest, ExecuteEntry_MissingSourceFile) { strcpy(test_entry.source_path, "/tmp/missing.log"); strcpy(test_entry.destination_path, "dest.log"); - + mock_filePresentCheck_return = -1; // File doesn't exist - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS); // Missing file is not an error } @@ -319,10 +317,10 @@ TEST_F(SpecialFilesTest, ExecuteEntry_CopyOperation) { strcpy(test_entry.source_path, "/tmp/version.txt"); strcpy(test_entry.destination_path, "version.txt"); strcpy(test_backup_config.log_path, "/opt/logs"); - + mock_filePresentCheck_return = 0; // File exists mock_copyFiles_return = 0; // Copy succeeds - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -332,11 +330,11 @@ TEST_F(SpecialFilesTest, ExecuteEntry_MoveOperation) { strcpy(test_entry.source_path, "/tmp/disk_cleanup.log"); strcpy(test_entry.destination_path, "disk_cleanup.log"); strcpy(test_backup_config.log_path, "/opt/logs"); - + mock_filePresentCheck_return = 0; // File exists mock_copyFiles_return = 0; // Copy succeeds mock_remove_return = 0; // Remove succeeds - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -346,10 +344,10 @@ TEST_F(SpecialFilesTest, ExecuteEntry_CopyFailure) { strcpy(test_entry.source_path, "/tmp/test.log"); strcpy(test_entry.destination_path, "test.log"); strcpy(test_backup_config.log_path, "/opt/logs"); - + mock_filePresentCheck_return = 0; // File exists mock_copyFiles_return = -1; // Copy fails - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); } @@ -359,11 +357,11 @@ TEST_F(SpecialFilesTest, ExecuteEntry_MoveOperationRemoveFailure) { strcpy(test_entry.source_path, "/tmp/mount_log.txt"); strcpy(test_entry.destination_path, "mount_log.txt"); strcpy(test_backup_config.log_path, "/opt/logs"); - + mock_filePresentCheck_return = 0; // File exists mock_copyFiles_return = 0; // Copy succeeds mock_remove_return = -1; // Remove fails - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_ERROR_FILESYSTEM); } @@ -372,10 +370,10 @@ TEST_F(SpecialFilesTest, ExecuteEntry_MoveOperationRemoveFailure) { TEST_F(SpecialFilesTest, ExecuteEntry_NoBackupConfig) { strcpy(test_entry.source_path, "/tmp/test.log"); strcpy(test_entry.destination_path, "test.log"); - + mock_filePresentCheck_return = 0; // File exists mock_copyFiles_return = 0; // Copy succeeds - + int result = special_files_execute_entry(&test_entry, nullptr); EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -390,7 +388,7 @@ TEST_F(SpecialFilesTest, ExecuteAll_NullParameter) { TEST_F(SpecialFilesTest, ExecuteAll_EmptyConfig) { test_config.count = 0; test_config.config_loaded = true; - + int result = special_files_execute_all(&test_config, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -400,18 +398,18 @@ TEST_F(SpecialFilesTest, ExecuteAll_MultipleEntries) { // Set up config with multiple entries test_config.count = 2; test_config.config_loaded = true; - + strcpy(test_config.entries[0].source_path, "/tmp/test1.log"); strcpy(test_config.entries[0].destination_path, "test1.log"); - + strcpy(test_config.entries[1].source_path, "/tmp/test2.log"); strcpy(test_config.entries[1].destination_path, "test2.log"); - + strcpy(test_backup_config.log_path, "/opt/logs"); - + mock_filePresentCheck_return = 0; // Files exist mock_copyFiles_return = 0; // Copy succeeds - + int result = special_files_execute_all(&test_config, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS); } @@ -420,18 +418,18 @@ TEST_F(SpecialFilesTest, ExecuteAll_MultipleEntries) { TEST_F(SpecialFilesTest, ExecuteAll_PartialFailures) { test_config.count = 2; test_config.config_loaded = true; - + strcpy(test_config.entries[0].source_path, "/tmp/test1.log"); strcpy(test_config.entries[0].destination_path, "test1.log"); - + strcpy(test_config.entries[1].source_path, "/tmp/test2.log"); strcpy(test_config.entries[1].destination_path, "test2.log"); - + strcpy(test_backup_config.log_path, "/opt/logs"); - + // First file exists, second doesn't mock_filePresentCheck_return = -1; // Files don't exist - + int result = special_files_execute_all(&test_config, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS); // Should succeed even if individual files fail } @@ -441,12 +439,12 @@ TEST_F(SpecialFilesTest, ExecuteEntry_PathTruncation) { // Create a very long path that would cause truncation string long_log_path(PATH_MAX - 10, 'a'); // Very long path strcpy(test_backup_config.log_path, long_log_path.c_str()); - + strcpy(test_entry.source_path, "/tmp/test.log"); strcpy(test_entry.destination_path, "very_long_destination_filename_that_might_cause_truncation.log"); - + mock_filePresentCheck_return = 0; // File exists - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_ERROR_CONFIG); // Should fail due to path truncation } @@ -455,13 +453,13 @@ TEST_F(SpecialFilesTest, ExecuteEntry_PathTruncation) { TEST_F(SpecialFilesTest, LoadConfig_MaxFiles) { FILE dummy_file; mock_fopen_return = &dummy_file; - + // Set up to return many files (more than MAX_SPECIAL_FILES) strcpy(mock_fgets_buffer, "/tmp/test.log\n"); mock_fgets_call_count = MAX_SPECIAL_FILES; // Exactly max files - + int result = special_files_load_config(&test_config, "test_config.txt"); - + EXPECT_EQ(result, BACKUP_SUCCESS); EXPECT_TRUE(test_config.config_loaded); EXPECT_EQ(test_config.count, MAX_SPECIAL_FILES); // Should cap at max @@ -471,24 +469,289 @@ TEST_F(SpecialFilesTest, LoadConfig_MaxFiles) { TEST_F(SpecialFilesTest, ExecuteEntry_SpecificMoveFiles) { const char* move_files[] = { "/tmp/disk_cleanup.log", - "/tmp/mount_log.txt", + "/tmp/mount_log.txt", "/tmp/mount-ta_log.txt" }; - + for (int i = 0; i < 3; i++) { strcpy(test_entry.source_path, move_files[i]); strcpy(test_entry.destination_path, "dest.log"); strcpy(test_backup_config.log_path, "/opt/logs"); - + mock_filePresentCheck_return = 0; // File exists mock_copyFiles_return = 0; // Copy succeeds mock_remove_return = 0; // Remove succeeds - + int result = special_files_execute_entry(&test_entry, &test_backup_config); EXPECT_EQ(result, BACKUP_SUCCESS) << "Failed for file: " << move_files[i]; } } +// Test load_config with lines containing only whitespace +TEST_F(SpecialFilesTest, LoadConfig_WhitespaceOnlyLines) { + FILE dummy_file; + mock_fopen_return = &dummy_file; + + // Test line with only tabs and spaces + strcpy(mock_fgets_buffer, " \t \n"); + mock_fgets_call_count = 1; + + int result = special_files_load_config(&test_config, "test_config.txt"); + + EXPECT_EQ(result, BACKUP_SUCCESS); + EXPECT_TRUE(test_config.config_loaded); + EXPECT_EQ(test_config.count, 0); // Should skip whitespace-only lines +} + +// Test load_config with filename only (no path separators) +TEST_F(SpecialFilesTest, LoadConfig_FilenameOnly) { + FILE dummy_file; + mock_fopen_return = &dummy_file; + + strcpy(mock_fgets_buffer, "simple_file.log\n"); + mock_fgets_call_count = 1; + + int result = special_files_load_config(&test_config, "test_config.txt"); + + EXPECT_EQ(result, BACKUP_SUCCESS); + EXPECT_EQ(test_config.count, 1); + EXPECT_STREQ(test_config.entries[0].source_path, "simple_file.log"); + EXPECT_STREQ(test_config.entries[0].destination_path, "simple_file.log"); +} + +// Test load_config with path ending in slash +TEST_F(SpecialFilesTest, LoadConfig_PathEndingInSlash) { + FILE dummy_file; + mock_fopen_return = &dummy_file; + + strcpy(mock_fgets_buffer, "/tmp/logs/\n"); + mock_fgets_call_count = 1; + + int result = special_files_load_config(&test_config, "test_config.txt"); + + EXPECT_EQ(result, BACKUP_SUCCESS); + EXPECT_EQ(test_config.count, 1); + EXPECT_STREQ(test_config.entries[0].source_path, "/tmp/logs/"); + EXPECT_STREQ(test_config.entries[0].destination_path, ""); // Empty destination after trailing slash +} + +// Test load_config with mixed valid and invalid entries +TEST_F(SpecialFilesTest, LoadConfig_MixedValidInvalidEntries) { + FILE dummy_file; + mock_fopen_return = &dummy_file; + + // For simplicity, test with one valid entry (mocking multiple calls is complex) + strcpy(mock_fgets_buffer, "/tmp/valid.log\n"); + mock_fgets_call_count = 1; + + int result = special_files_load_config(&test_config, "test_config.txt"); + + EXPECT_EQ(result, BACKUP_SUCCESS); + EXPECT_EQ(test_config.count, 1); + EXPECT_STREQ(test_config.entries[0].source_path, "/tmp/valid.log"); +} + +// Test validate_entry with paths containing special characters +TEST_F(SpecialFilesTest, ValidateEntry_SpecialCharactersInPath) { + strcpy(test_entry.source_path, "/tmp/file with spaces & symbols.log"); + strcpy(test_entry.destination_path, "file with spaces & symbols.log"); + + int result = special_files_validate_entry(&test_entry); + EXPECT_EQ(result, BACKUP_SUCCESS); +} + +// Test validate_entry with maximum length paths +TEST_F(SpecialFilesTest, ValidateEntry_MaxLengthPaths) { + // Create paths that are exactly PATH_MAX-1 characters + string long_source(PATH_MAX - 1, 'a'); + string long_dest(PATH_MAX - 1, 'b'); + + strncpy(test_entry.source_path, long_source.c_str(), sizeof(test_entry.source_path) - 1); + test_entry.source_path[sizeof(test_entry.source_path) - 1] = '\0'; + + strncpy(test_entry.destination_path, long_dest.c_str(), sizeof(test_entry.destination_path) - 1); + test_entry.destination_path[sizeof(test_entry.destination_path) - 1] = '\0'; + + int result = special_files_validate_entry(&test_entry); + EXPECT_EQ(result, BACKUP_SUCCESS); +} + +// Test execute_entry with edge case file names similar to move files +TEST_F(SpecialFilesTest, ExecuteEntry_SimilarToMoveFiles) { + const char* similar_files[] = { + "/tmp/disk_cleanup_other.log", // Similar but not exact match + "/tmp/mount_log_backup.txt", // Similar but not exact match + "/etc/mount_log.txt" // Different path, same filename + }; + + for (int i = 0; i < 3; i++) { + strcpy(test_entry.source_path, similar_files[i]); + strcpy(test_entry.destination_path, "dest.log"); + strcpy(test_backup_config.log_path, "/opt/logs"); + + mock_filePresentCheck_return = 0; // File exists + mock_copyFiles_return = 0; // Copy succeeds + + int result = special_files_execute_entry(&test_entry, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS) << "Failed for file: " << similar_files[i]; + + // These should be copy operations, not move (no remove call expected) + } +} + +// Test execute_entry with exactly PATH_MAX destination path +TEST_F(SpecialFilesTest, ExecuteEntry_ExactPathMaxDestination) { + strcpy(test_entry.source_path, "/tmp/test.log"); + strcpy(test_entry.destination_path, "test.log"); + + // Create log_path that when combined with destination will equal PATH_MAX + string long_path(PATH_MAX - strlen("test.log") - 2, 'a'); // -2 for '/' and '\0' + strcpy(test_backup_config.log_path, long_path.c_str()); + + mock_filePresentCheck_return = 0; // File exists + mock_copyFiles_return = 0; // Copy succeeds + + int result = special_files_execute_entry(&test_entry, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS); +} + +// Test execute_entry with NULL backup_config parameter +TEST_F(SpecialFilesTest, ExecuteEntry_NullBackupConfig) { + strcpy(test_entry.source_path, "/tmp/test.log"); + strcpy(test_entry.destination_path, "test.log"); + + mock_filePresentCheck_return = 0; // File exists + mock_copyFiles_return = 0; // Copy succeeds + + int result = special_files_execute_entry(&test_entry, nullptr); + EXPECT_EQ(result, BACKUP_SUCCESS); +} + +// Test execute_entry with empty log_path in backup_config +TEST_F(SpecialFilesTest, ExecuteEntry_EmptyLogPath) { + strcpy(test_entry.source_path, "/tmp/test.log"); + strcpy(test_entry.destination_path, "test.log"); + test_backup_config.log_path[0] = '\0'; // Empty log path + + mock_filePresentCheck_return = 0; // File exists + mock_copyFiles_return = 0; // Copy succeeds + + int result = special_files_execute_entry(&test_entry, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS); +} + +// Test execute_all with config not loaded +TEST_F(SpecialFilesTest, ExecuteAll_ConfigNotLoaded) { + test_config.count = 1; + test_config.config_loaded = false; // Mark as not loaded + + strcpy(test_config.entries[0].source_path, "/tmp/test.log"); + strcpy(test_config.entries[0].destination_path, "test.log"); + + mock_filePresentCheck_return = 0; + mock_copyFiles_return = 0; + + int result = special_files_execute_all(&test_config, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS); // Should still process entries +} + +// Test execute_all with all entries failing +TEST_F(SpecialFilesTest, ExecuteAll_AllEntriesFailing) { + test_config.count = 2; + test_config.config_loaded = true; + + strcpy(test_config.entries[0].source_path, "/tmp/test1.log"); + strcpy(test_config.entries[0].destination_path, "test1.log"); + + strcpy(test_config.entries[1].source_path, "/tmp/test2.log"); + strcpy(test_config.entries[1].destination_path, "test2.log"); + + mock_filePresentCheck_return = 0; // Files exist + mock_copyFiles_return = -1; // Copy fails + + int result = special_files_execute_all(&test_config, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS); // execute_all should succeed even if individual entries fail +} + +// Test load_config with exceeding MAX_SPECIAL_FILES limit +TEST_F(SpecialFilesTest, LoadConfig_ExceedMaxFiles) { + FILE dummy_file; + mock_fopen_return = &dummy_file; + + // Set up to return more files than MAX_SPECIAL_FILES + strcpy(mock_fgets_buffer, "/tmp/test.log\n"); + mock_fgets_call_count = MAX_SPECIAL_FILES + 5; // More than max + + int result = special_files_load_config(&test_config, "test_config.txt"); + + EXPECT_EQ(result, BACKUP_SUCCESS); + EXPECT_TRUE(test_config.config_loaded); + EXPECT_LE(test_config.count, MAX_SPECIAL_FILES); // Should not exceed max +} + +// Test execute_entry operation determination logic +TEST_F(SpecialFilesTest, ExecuteEntry_OperationDetermination) { + struct test_case { + const char* source_path; + bool should_move; + }; + + test_case test_cases[] = { + {"/tmp/disk_cleanup.log", true}, + {"/tmp/mount_log.txt", true}, + {"/tmp/mount-ta_log.txt", true}, + {"/tmp/version.txt", false}, + {"/tmp/other.log", false}, + {"/tmp/disk_cleanup.log.bak", false}, // Similar but not exact + {"/opt/disk_cleanup.log", false} // Different path + }; + + for (auto& tc : test_cases) { + strcpy(test_entry.source_path, tc.source_path); + strcpy(test_entry.destination_path, "dest.log"); + strcpy(test_backup_config.log_path, "/opt/logs"); + + mock_filePresentCheck_return = 0; // File exists + mock_copyFiles_return = 0; // Copy succeeds + mock_remove_return = 0; // Remove succeeds (for move operations) + + int result = special_files_execute_entry(&test_entry, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS) << "Failed for: " << tc.source_path; + } +} + +// Test edge case with very short destination filename +TEST_F(SpecialFilesTest, ExecuteEntry_ShortDestinationFilename) { + strcpy(test_entry.source_path, "/a/b/c/d/e/f/g/h/i/j/x"); // Short filename 'x' + strcpy(test_entry.destination_path, "x"); + strcpy(test_backup_config.log_path, "/opt/logs"); + + mock_filePresentCheck_return = 0; + mock_copyFiles_return = 0; + + int result = special_files_execute_entry(&test_entry, &test_backup_config); + EXPECT_EQ(result, BACKUP_SUCCESS); +} + +// Test cleanup function multiple times +TEST_F(SpecialFilesTest, Cleanup_MultipleCalls) { + EXPECT_NO_THROW(special_files_cleanup()); + EXPECT_NO_THROW(special_files_cleanup()); + EXPECT_NO_THROW(special_files_cleanup()); +} + +// Test init function multiple times +TEST_F(SpecialFilesTest, Init_MultipleCalls) { + int result1 = special_files_init(); + EXPECT_EQ(result1, BACKUP_SUCCESS); + + int result2 = special_files_init(); + EXPECT_EQ(result2, BACKUP_SUCCESS); + + int result3 = special_files_init(); + EXPECT_EQ(result3, BACKUP_SUCCESS); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/run_uploadstblogs_l2.sh b/test/run_uploadstblogs_l2.sh index 30db17ab0..f447bc7a9 100644 --- a/test/run_uploadstblogs_l2.sh +++ b/test/run_uploadstblogs_l2.sh @@ -1,6 +1,6 @@ #!/bin/sh #################################################################################### -# If not stated otherwise in this file or this component's LICENSE file the +# If not stated otherwise in this file or this component's Licenses.txt file the # following copyright and licenses apply: # # Copyright 2024 RDK Management @@ -126,6 +126,28 @@ echo "8. Running Upload Strategy Tests..." pytest -v --json-report --json-report-summary \ --json-report-file $RESULT_DIR/upload_strategies.json test/functional-tests/tests/test_uploadstblogs_upload_strategies.py + +echo "" +echo "9. Running backup Engine Tests..." +pytest -v --json-report --json-report-summary \ + --json-report-file $RESULT_DIR/backup_engine.json test/functional-tests/tests/test_backup_engine.py + +echo "" +echo "10. Running backup configuration manager Tests..." +pytest -v --json-report --json-report-summary \ + --json-report-file $RESULT_DIR/backuplog_config_manager.json test/functional-tests/tests/test_backuplog_config_manager.py + +echo "" +echo "11. Running backup systemintegration Tests..." +pytest -v --json-report --json-report-summary \ + --json-report-file $RESULT_DIR/backuplogs_system_integration.json test/functional-tests/tests/test_backuplogs_system_integration.py + + +echo "" +echo "12. Running backup special file Tests..." +pytest -v --json-report --json-report-summary \ + --json-report-file $RESULT_DIR/test_backuplogs_special_files.json test/functional-tests/tests/test_backuplogs_special_files.py + echo "" echo "=====================================" echo "Test Execution Complete" diff --git a/unit_test.sh b/unit_test.sh old mode 100755 new mode 100644 index e88bf470c..e20754d41 --- a/unit_test.sh +++ b/unit_test.sh @@ -18,7 +18,7 @@ ## SPDX-License-Identifier: Apache-2.0 # -ENABLE_COV=false +ENABLE_COV=true if [ "x$1" = "x--enable-cov" ]; then echo "Enabling coverage options" @@ -68,6 +68,17 @@ autoreconf --install make clean make + +cd ../../backup_logs/unittest +automake --add-missing +autoreconf --install + +./configure + +make clean +make + + echo "RDK_PROFILE=TV" >> /etc/device.properties fail=0 cd $TOP_DIR/unittest/ @@ -98,8 +109,12 @@ for test in \ ./../usbLogUpload/unittest/usb_log_file_manager_gtest \ ./../usbLogUpload/unittest/usb_log_validation_gtest \ ./../usbLogUpload/unittest/usb_log_utils_gtest \ - ./../usbLogUpload/unittest/usb_log_archive_gtest - + ./../usbLogUpload/unittest/usb_log_archive_gtest \ + ./../backup_logs/unittest/backup_engine_gtest \ + ./../backup_logs/unittest/backup_logs_gtest \ + ./../backup_logs/unittest/config_manager_gtest \ + ./../backup_logs/unittest/special_files_gtest \ + ./../backup_logs/unittest/sys_integration_gtest do $test status=$? @@ -125,4 +140,10 @@ if [ "$ENABLE_COV" = true ]; then lcov --remove coverage.info '/usr/*' --output-file coverage.info lcov --remove coverage.info "${PWD}/*" --output-file coverage.info lcov --list coverage.info + lcov --capture --directory ./../backup_logs/ --output-file coverage_backup.info + lcov --remove coverage_backup.info '/usr/*' --output-file coverage_backup.info + lcov --remove coverage_backup.info '/usr/*' '*/backup_logs/unittest/*' -o coverage_backup.info + #lcov --remove coverage_backup.info './../backup_logs/unittest/*' --output-file coverage_backup.info + lcov --list coverage_backup.info + fi diff --git a/unittest/dcm_cronparse_gtest.cpp b/unittest/dcm_cronparse_gtest.cpp index 79583a189..95511fc90 100644 --- a/unittest/dcm_cronparse_gtest.cpp +++ b/unittest/dcm_cronparse_gtest.cpp @@ -16,6 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 */ + #include #include #include