diff --git a/c-programming/clock-malfunction-imitation.c b/c-programming/clock-malfunction-imitation.c new file mode 100644 index 0000000..ee6ec50 --- /dev/null +++ b/c-programming/clock-malfunction-imitation.c @@ -0,0 +1,188 @@ +/* + * clock-malfunction-imitation.c + * + * Author: Intel A80486DX2-66 + * License: Creative Commons Zero 1.0 Universal + */ + +#include +#include +#include +#include +#include +#include + +#define EXIT_IN 2U +#define SECOND_PRECISION 1L +#define TIME_BEFORE_ACCIDENT 2UL + +#define TEST_LABEL(s) { \ + printf("Test: %s\n", s); \ + fflush(stdout); \ +} + +#define CLOCK_FUN_BEGIN \ + static unsigned ticks_before_accident = TIME_BEFORE_ACCIDENT; \ + time_t y; + +#define CLOCK_FUN_END \ + if (x != NULL) { \ + *x = y; \ + } \ + return y; + +time_t clock_change_time(time_t* x); +time_t clock_exponential_growth(time_t* x); +time_t clock_hang(time_t* x); +time_t clock_overflow(time_t* x); +time_t clock_reverse(time_t* x); +void time_flow_test(time_t (*time_function)(time_t*)); + +time_t clock_change_time(time_t* x) { + CLOCK_FUN_BEGIN + + time(&y); + + if (ticks_before_accident == 0) { + y = 0; + + size_t max = sizeof(time(NULL)) / sizeof(int); + printf("max of clock_change_time = %zu\n", max); + size_t intmax_plus_1 = (size_t) INT_MAX + 1; + + for (size_t i = 0; i < max; i++) + y |= (rand() & INT_MAX) * intmax_plus_1; + } else + ticks_before_accident--; + + CLOCK_FUN_END +} + +time_t clock_exponential_growth(time_t* x) { + CLOCK_FUN_BEGIN + + static time_t counter = 1; + + time(&y); + + if (ticks_before_accident == 0) { + y += counter++; + counter *= counter; + } else { + ticks_before_accident--; + } + + CLOCK_FUN_END +} + +time_t clock_hang(time_t* x) { + CLOCK_FUN_BEGIN + + static time_t last_time; + + if (ticks_before_accident == 0) + y = last_time; + else { + time(&y); + last_time = y; + ticks_before_accident--; + } + + CLOCK_FUN_END +} + +time_t clock_overflow(time_t* x) { + CLOCK_FUN_BEGIN + + time(&y); + + if (ticks_before_accident == 0) + y = LONG_MAX - y; + else + ticks_before_accident--; + + CLOCK_FUN_END +} + +time_t clock_reverse(time_t* x) { + CLOCK_FUN_BEGIN + + static time_t counter = 1, old_time; + + if (ticks_before_accident == 0) { + y = old_time - counter++; + } else { + time(&y); + old_time = y; + ticks_before_accident--; + } + + CLOCK_FUN_END +} + +void time_flow_test(time_t (*time_function)(time_t*)) { + time_t current_time, previous_time; + double time_diff; + + // Get the current time + time(¤t_time); + previous_time = current_time; + bool first_time_passed = false; + unsigned i = 0; + + for (;;) { + // Get the current time + time_function(¤t_time); + + // Calculate the time difference in seconds + time_diff = difftime(current_time, previous_time); + if (!first_time_passed) { + time_diff = (double) SECOND_PRECISION; + first_time_passed = true; + } + printf("time difference: %f", time_diff); + fflush(stdout); + + // Check if the time difference exceeds a threshold (e.g., 1 second) + if (time_diff != (double) SECOND_PRECISION) { + printf(" -> Abnormal time flow detected!"); + fflush(stdout); + if (++i >= EXIT_IN) { + printf("\nAborting\n"); + fflush(stdout); + break; + } + } + printf("\n"); + fflush(stdout); + + // Update the previous time + previous_time = current_time; + + usleep(SECOND_PRECISION * 1000000L); + + first_time_passed = true; + } + + printf("\n"); + fflush(stdout); +} + +int main(void) { + TEST_LABEL("clock_change_time") + time_flow_test(&clock_change_time); + + TEST_LABEL("clock_exponential_growth") + time_flow_test(&clock_exponential_growth); + + TEST_LABEL("clock_hang") + time_flow_test(&clock_hang); + + TEST_LABEL("clock_overflow") + time_flow_test(&clock_overflow); + + TEST_LABEL("clock_reverse") + time_flow_test(&clock_reverse); + + return 0; +}