#include "mgos.h" #include "test.h" #include "timespec.h" static void test_timespec_pass(void) { struct mgos_timespec *ts; static const char * tests[] = { "08-20", "8-20", "08:01-20:59", "8:00-20", "08:00:00-20:00:00", "8:00:00-20:00:00", "0-0:01", "0-23:59:59", "08-20:30", "20-08", "20:01:02-08:01:02", "00:00-00:00", NULL }; ts = timespec_create(); ASSERT(ts, "Created timespec"); for (int i = 0; tests[i]; i++) { ASSERT(timespec_add_spec(ts, tests[i]), tests[i]); } ASSERT(timespec_destroy(&ts), "Destroyed timespec"); } static void test_timespec_fail(void) { struct mgos_timespec *ts; static const char * tests[] = { "08", // No endtime given "08-", // No endtime given "-20", // No begintime given "08:00:00:00-20", // Malformed begintime "08:00-20:00:00:00", // Malformed endtime "24-01", // Hours >23 "08:60-20:00", // Minutes >59 "08:59:60-20:00", // Seconds >59 "08:59:59-24:00:00", // Hours >23 "08:59:59-23:60:00", // Minutes >59 "08:59:59-23:59:60", // Seconds >59 "abc", // Invalid chars "", // Empty spec "-", // No times specified NULL }; ts = timespec_create(); ASSERT(ts, "Created timespec"); for (int i = 0; tests[i]; i++) { ASSERT(!timespec_add_spec(ts, tests[i]), tests[i]); } ASSERT(timespec_destroy(&ts), "Destroyed timespec"); } static void test_timespec_flips_and_seconds(const struct mgos_timespec *ts, const uint32_t expected_flips, const uint32_t expected_seconds_on) { struct tm target; bool state = false; int state_flips = 0; int state_seconds_on = 0; int state_seconds_off = 0; for (int i = 0; i < 86400; i++) { target.tm_sec = i % 60; target.tm_min = (i / 60) % 60; target.tm_hour = (i / 3600) % 24; if (state != timespec_match(ts, &target)) { state = !state; state_flips++; LOG(LL_DEBUG, ("State flipped to %s at %02d:%02d:%02d", state ? "On" : "Off", target.tm_hour, target.tm_min, target.tm_sec)); } if (state) { state_seconds_on++; } else{ state_seconds_off++; } } LOG(LL_DEBUG, ("state_flips=%d state_seconds_on=%d", state_flips, state_seconds_on)); ASSERT(state_flips == expected_flips, "Want to see expected_flips number of state flips"); ASSERT(state_seconds_on == expected_seconds_on, "State seconds on should be expected_seconds_on"); ASSERT(state_seconds_on + state_seconds_off == 86400, "State seconds on + off should be 86400 seconds"); } static void test_timespec_state(void) { struct mgos_timespec *ts = timespec_create(); struct tm target; char buf[500]; ASSERT(ts, "Created timespec"); timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, ""), "timespec_get_spec() didn't match input spec(s)"); ASSERT(timespec_add_spec(ts, "08-10"), "Added timespec"); ASSERT(timespec_add_spec(ts, "12:00-13:00"), "Added timespec"); ASSERT(timespec_add_spec(ts, "14:11:05-14:59:52"), "Added timespec"); ASSERT(timespec_add_spec(ts, "23:01:02-01:02:03"), "Added timespec"); ASSERT(!timespec_add_spec(ts, "14:60-15:01"), "Illegal timespec"); target.tm_sec = 59; target.tm_min = 59; target.tm_hour = 7; ASSERT(!timespec_match(ts, &target), "No match at 07:59:59"); target.tm_sec = 0; target.tm_min = 0; target.tm_hour = 8; ASSERT(timespec_match(ts, &target), "Match at 08:00:00"); target.tm_sec = 59; target.tm_min = 59; target.tm_hour = 9; ASSERT(timespec_match(ts, &target), "Match at 09:59:59"); target.tm_sec = 0; target.tm_min = 0; target.tm_hour = 10; ASSERT(!timespec_match(ts, &target), "No Match at 10:00:00"); target.tm_sec = 59; target.tm_min = 59; target.tm_hour = 11; ASSERT(!timespec_match(ts, &target), "No match at 11:59:59"); target.tm_sec = 0; target.tm_min = 0; target.tm_hour = 12; ASSERT(timespec_match(ts, &target), "Match at 12:00:00"); target.tm_sec = 59; target.tm_min = 59; target.tm_hour = 12; ASSERT(timespec_match(ts, &target), "Match at 12:59:59"); target.tm_sec = 0; target.tm_min = 0; target.tm_hour = 13; ASSERT(!timespec_match(ts, &target), "No match at 13:00:00"); target.tm_sec = 4; target.tm_min = 11; target.tm_hour = 14; ASSERT(!timespec_match(ts, &target), "No match at 14:11:04"); target.tm_sec = 5; target.tm_min = 11; target.tm_hour = 14; ASSERT(timespec_match(ts, &target), "Match at 14:11:05"); target.tm_sec = 51; target.tm_min = 59; target.tm_hour = 14; ASSERT(timespec_match(ts, &target), "Match at 14:59:51"); target.tm_sec = 52; target.tm_min = 59; target.tm_hour = 14; ASSERT(!timespec_match(ts, &target), "No match at 14:59:52"); target.tm_sec = 1; target.tm_min = 1; target.tm_hour = 23; ASSERT(!timespec_match(ts, &target), "No match at 23:01:01"); target.tm_sec = 2; target.tm_min = 1; target.tm_hour = 23; ASSERT(timespec_match(ts, &target), "Match at 23:01:02"); target.tm_sec = 59; target.tm_min = 59; target.tm_hour = 23; ASSERT(timespec_match(ts, &target), "Match at 23:59:59"); target.tm_sec = 0; target.tm_min = 0; target.tm_hour = 0; ASSERT(timespec_match(ts, &target), "Match at 00:00:00"); target.tm_sec = 2; target.tm_min = 2; target.tm_hour = 1; ASSERT(timespec_match(ts, &target), "Match at 01:02:02"); target.tm_sec = 3; target.tm_min = 2; target.tm_hour = 1; ASSERT(!timespec_match(ts, &target), "No match at 01:02:03"); // Test timespec retrieval timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, "23:01:02-01:02:03,14:11:05-14:59:52,12:00:00-13:00:00,08:00:00-10:00:00"), "timespec_get_spec() didn't match input spec(s)"); LOG(LL_INFO, ("Spec: '%s'", buf)); ASSERT(timespec_destroy(&ts), "Destroyed timespec"); // Some time counting tests ts = timespec_create(); ASSERT(ts, "Created timespec"); ASSERT(timespec_add_spec(ts, "08-10"), "Added timespec"); test_timespec_flips_and_seconds(ts, 2, 7200); // Zero seconds long ASSERT(timespec_add_spec(ts, "00:00:00-00:00:00"), "Added timespec"); test_timespec_flips_and_seconds(ts, 2, 7200 + 0); // Add two hours wrapping midnight ASSERT(timespec_add_spec(ts, "23:00:00-01:00:00"), "Added timespec"); test_timespec_flips_and_seconds(ts, 5, 7200 + 0 + 7200); // Add single second ASSERT(timespec_add_spec(ts, "02:00:00-02:00:01"), "Added timespec"); test_timespec_flips_and_seconds(ts, 7, 7200 + 0 + 7200 + 1); // Add an hour, a minute and a second ASSERT(timespec_add_spec(ts, "03:02:03-04:03:04"), "Added timespec"); test_timespec_flips_and_seconds(ts, 9, 7200 + 0 + 7200 + 1 + 3661); // Test timespec retrieval timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, "03:02:03-04:03:04,02:00:00-02:00:01,23:00:00-01:00:00,00:00:00-00:00:00,08:00:00-10:00:00"), "timespec_get_spec() didn't match input spec(s)"); ASSERT(timespec_destroy(&ts), "Destroyed timespec"); // Some other time counting tests ts = timespec_create(); ASSERT(ts, "Created timespec"); ASSERT(timespec_add_spec(ts, "00-12"), "Added timespec"); test_timespec_flips_and_seconds(ts, 2, 12 * 60 * 60); ASSERT(timespec_add_spec(ts, "12-00"), "Added timespec"); test_timespec_flips_and_seconds(ts, 1, 24 * 60 * 60); // Test timespec retrieval timespec_get_spec(ts, buf, sizeof(buf)-1); ASSERT(0 == strcmp(buf, "12:00:00-00:00:00,00:00:00-12:00:00"), "timespec_get_spec() didn't match input spec(s)"); ASSERT(timespec_destroy(&ts), "Destroyed timespec"); } void test_timespec() { test_timespec_pass(); test_timespec_fail(); test_timespec_state(); }