Skip to content

Commit cea13e6

Browse files
committed
source: merge qcom-linux-testkit-sources into unified testkit
- Imported all C source files from qcom-linux-testkit-sources into src/ - Ensured reboot health check and related binaries are included in autotools build Signed-off-by: Srikanth Muppandam <[email protected]>
1 parent 47c5deb commit cea13e6

File tree

2 files changed

+259
-0
lines changed

2 files changed

+259
-0
lines changed

src/tests/reboot.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3+
* SPDX-License-Identifier: BSD-3-Clause-Clear
4+
*/
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <unistd.h>
8+
#include <sys/stat.h>
9+
#include <string.h>
10+
#include <time.h>
11+
#include <sys/reboot.h>
12+
13+
#define HEALTH_DIR "/var/reboot_health"
14+
#define LOG_FILE "/var/reboot_health/reboot_health.log"
15+
#define SERIAL_PORT "/dev/ttyS0"
16+
17+
// Function to get the current timestamp
18+
void get_timestamp(char *buffer, size_t size) {
19+
time_t now = time(NULL);
20+
struct tm *t = localtime(&now);
21+
strftime(buffer, size, "%Y-%m-%d %H:%M:%S", t);
22+
}
23+
24+
// Function to log messages with a specified level
25+
void log_message(const char *level, const char *message) {
26+
char timestamp[64];
27+
get_timestamp(timestamp, sizeof(timestamp));
28+
29+
// Log to file
30+
FILE *log = fopen(LOG_FILE, "a");
31+
if (log) {
32+
fprintf(log, "[%s] [%s] %s\n", timestamp, level, message);
33+
fclose(log);
34+
}
35+
36+
// Log to serial port (for visibility)
37+
FILE *serial = fopen(SERIAL_PORT, "w");
38+
if (serial) {
39+
fprintf(serial, "[%s] [%s] %s\n", timestamp, level, message);
40+
fclose(serial);
41+
}
42+
}
43+
44+
// Helper functions for logging
45+
void log_info(const char *message) { log_message("INFO", message); }
46+
void log_pass(const char *message) { log_message("PASS", message); }
47+
void log_fail(const char *message) { log_message("FAIL", message); }
48+
void log_error(const char *message) { log_message("ERROR", message); }
49+
50+
// Check if the system has recently rebooted by reading uptime
51+
void check_system_reboot() {
52+
FILE *fp;
53+
char buffer[128];
54+
unsigned long uptime = 0;
55+
56+
fp = fopen("/proc/uptime", "r");
57+
if (fp == NULL) {
58+
log_error("Failed to read /proc/uptime.");
59+
exit(1);
60+
}
61+
fscanf(fp, "%s", buffer);
62+
fclose(fp);
63+
64+
uptime = strtol(buffer, NULL, 10); // Uptime in seconds
65+
66+
if (uptime < 300) { // If uptime is less than 5 minutes, assume the system has rebooted recently
67+
log_info("System has rebooted recently (uptime < 300 seconds).");
68+
} else {
69+
log_info("System uptime is normal (no recent reboot detected).");
70+
}
71+
}
72+
73+
// Check if the system is running a valid shell (PID 1)
74+
void check_shell_alive() {
75+
FILE *fp = fopen("/proc/1/comm", "r");
76+
if (!fp) {
77+
log_fail("Cannot open /proc/1/comm. System critical error.");
78+
exit(1);
79+
}
80+
81+
char buf[64] = {0};
82+
if (!fgets(buf, sizeof(buf), fp)) {
83+
fclose(fp);
84+
log_fail("Failed to read PID 1 comm.");
85+
exit(1);
86+
}
87+
fclose(fp);
88+
89+
buf[strcspn(buf, "\n")] = 0; // Remove trailing newline
90+
91+
if (strstr(buf, "init") || strstr(buf, "systemd") || strstr(buf, "busybox")) {
92+
char msg[128];
93+
snprintf(msg, sizeof(msg), "Booted successfully with PID1 -> %s", buf);
94+
log_pass(msg); // Log PASS
95+
} else {
96+
char msg[128];
97+
snprintf(msg, sizeof(msg), "Boot failed. Unexpected PID1: %s", buf);
98+
log_fail(msg); // Log FAIL
99+
100+
log_info("Attempting reboot now...");
101+
sync();
102+
reboot(RB_AUTOBOOT);
103+
}
104+
}
105+
106+
// Create the directory if it doesn't exist
107+
int create_directory_if_not_exists(const char *dir_path) {
108+
struct stat st = {0};
109+
if (stat(dir_path, &st) == -1) {
110+
if (mkdir(dir_path, 0755) == -1) {
111+
log_error("Failed to create directory /var/reboot_health.");
112+
return -1;
113+
}
114+
log_info("Created directory /var/reboot_health.");
115+
}
116+
return 0;
117+
}
118+
119+
int main() {
120+
// Ensure the directory exists before proceeding
121+
if (create_directory_if_not_exists(HEALTH_DIR) != 0) {
122+
log_error("Exiting due to failure in creating directory.");
123+
return 1; // Directory creation failed
124+
}
125+
126+
check_system_reboot(); // Check if the system has recently rebooted
127+
check_shell_alive(); // Check if the system shell (PID 1) is alive and healthy
128+
129+
log_info("Reboot health check completed.");
130+
return 0;
131+
}

src/tests/reboot_health_check.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3+
* SPDX-License-Identifier: BSD-3-Clause-Clear
4+
*/
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <unistd.h>
8+
#include <time.h>
9+
#include <sys/stat.h>
10+
#include <string.h>
11+
12+
#define LOG_DIR "/var/reboot_health"
13+
#define LOG_FILE "/var/reboot_health/reboot_health.log"
14+
#define RESULT_FILE "/var/reboot_health/test_result.txt" // Separate result file for CI/CD
15+
16+
// Function to check if the system rebooted (log file exists)
17+
int check_system_rebooted() {
18+
FILE *file = fopen(LOG_FILE, "r");
19+
if (file == NULL) {
20+
return 0; // No log file means no reboot has occurred
21+
}
22+
fclose(file);
23+
return 1; // Log file exists, system has rebooted
24+
}
25+
26+
// Function to log the result of the health check
27+
void log_health_check(int status) {
28+
FILE *log_file = fopen(LOG_FILE, "a");
29+
if (log_file == NULL) {
30+
perror("Failed to open log file");
31+
exit(1);
32+
}
33+
34+
time_t now = time(NULL);
35+
char *time_str = ctime(&now);
36+
time_str[strlen(time_str) - 1] = '\0'; // Remove the newline character from ctime's output
37+
38+
if (status) {
39+
fprintf(log_file, "[%s] PASS: System rebooted successfully.\n", time_str);
40+
} else {
41+
fprintf(log_file, "[%s] FAIL: System did not reboot successfully.\n", time_str);
42+
}
43+
44+
fclose(log_file);
45+
}
46+
47+
// Function to write a result (PASS/FAIL) for CI/CD into a separate file
48+
void write_result_for_cicd(int status) {
49+
FILE *result_file = fopen(RESULT_FILE, "a");
50+
if (result_file == NULL) {
51+
perror("Failed to open result file");
52+
exit(1);
53+
}
54+
55+
time_t now = time(NULL);
56+
char *time_str = ctime(&now);
57+
time_str[strlen(time_str) - 1] = '\0'; // Remove the newline character
58+
59+
if (status) {
60+
fprintf(result_file, "[%s] PASS\n", time_str);
61+
} else {
62+
fprintf(result_file, "[%s] FAIL\n", time_str);
63+
}
64+
65+
fclose(result_file);
66+
}
67+
68+
// Function to ensure the log directory exists
69+
void create_log_directory() {
70+
if (access(LOG_DIR, F_OK) == -1) {
71+
if (mkdir(LOG_DIR, 0755) != 0) {
72+
perror("Failed to create log directory");
73+
exit(1);
74+
}
75+
}
76+
}
77+
78+
// Function to check if the log and result files exist, create them if not
79+
void ensure_files_exist() {
80+
// Create log file if not exists
81+
FILE *log_file = fopen(LOG_FILE, "a");
82+
if (log_file == NULL) {
83+
perror("Failed to open log file");
84+
exit(1);
85+
}
86+
fclose(log_file); // Close after checking/creating the file
87+
88+
// Create result file if not exists
89+
FILE *result_file = fopen(RESULT_FILE, "w");
90+
if (result_file == NULL) {
91+
perror("Failed to open result file");
92+
exit(1);
93+
}
94+
fclose(result_file); // Close after checking/creating the file
95+
}
96+
97+
// Watchdog timer simulation
98+
void watchdog_timer() {
99+
int counter = 0;
100+
while (1) {
101+
sleep(5); // Check every 5 seconds
102+
103+
counter++;
104+
105+
if (check_system_rebooted()) {
106+
log_health_check(1); // Log success if system rebooted
107+
write_result_for_cicd(1); // Write pass to CI/CD result file
108+
break; // Exit the loop after success
109+
}
110+
111+
if (counter >= 12) { // Timeout after 1 minute
112+
log_health_check(0); // Log failure if no reboot detected
113+
write_result_for_cicd(0); // Write fail to CI/CD result file
114+
break; // Exit the loop after failure
115+
}
116+
}
117+
}
118+
119+
int main() {
120+
// Ensure the necessary directories and files exist
121+
create_log_directory();
122+
ensure_files_exist();
123+
124+
// Start the watchdog timer
125+
watchdog_timer();
126+
127+
return 0;
128+
}

0 commit comments

Comments
 (0)