AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <math.h>5#include <stdint.h>6 7/* Helper: tolerance for comparing seconds */8static const double EPS = 1e-6;9 10/* Helper: Build an iJD that yields a desired time-of-day in milliseconds.11 computeHMS computes:12 day_ms = (iJD + 43200000) % 8640000013 So to get desired_ms (0..86399999), we can set:14 iJD = K*86400000 + R, where R = (desired_ms - 43200000) mod 8640000015 Equivalent:16 R = (desired_ms + 43200000) % 8640000017*/18static sqlite3_int64 make_iJD_for_time_ms(sqlite3_int64 desired_ms){19 const sqlite3_int64 DAY_MS = 86400000;20 const sqlite3_int64 NOON_MS = 43200000;21 sqlite3_int64 R = (desired_ms + NOON_MS) % DAY_MS;22 sqlite3_int64 K = 12345; /* arbitrary day offset */23 return K*DAY_MS + R;24}25 26void setUp(void) {27 /* Setup code here, or leave empty */28}29 30void tearDown(void) {31 /* Cleanup code here, or leave empty */32}33 34/* Test: When validHMS is already set, computeHMS should return immediately and not modify fields */35void test_computeHMS_early_return_when_validHMS_set(void) {36 DateTime dt;37 memset(&dt, 0, sizeof(dt));38 dt.validHMS = 1;39 dt.h = -1;40 dt.m = -2;41 dt.s = -3.25;42 dt.rawS = 1;43 dt.validJD = 0; /* ensure computeJD would be needed if it ran */44 45 /* Call wrapper */46 test_computeHMS(&dt);47 48 /* Ensure nothing changed */49 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);50 TEST_ASSERT_EQUAL_INT(-1, dt.h);51 TEST_ASSERT_EQUAL_INT(-2, dt.m);52 TEST_ASSERT_DOUBLE_IS_NOT_INF(dt.s);53 TEST_ASSERT_DOUBLE_IS_NOT_NAN(dt.s);54 TEST_ASSERT(fabs(dt.s - (-3.25)) < EPS);55 TEST_ASSERT_EQUAL_INT(1, dt.rawS);56 TEST_ASSERT_EQUAL_INT(0, dt.validJD);57}58 59/* Test: Default path (no validJD and no validYMD) uses 2000-01-01 and returns 00:00:00 */60void test_computeHMS_default_date_midnight(void) {61 DateTime dt;62 memset(&dt, 0, sizeof(dt));63 /* validYMD=0, validJD=0, rawS=0 by default */64 65 test_computeHMS(&dt);66 67 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);68 TEST_ASSERT_EQUAL_INT(1, dt.validJD); /* computeJD should have been called */69 TEST_ASSERT_EQUAL_INT(0, dt.h);70 TEST_ASSERT_EQUAL_INT(0, dt.m);71 TEST_ASSERT(fabs(dt.s - 0.0) <= EPS);72 TEST_ASSERT_EQUAL_INT(0, dt.rawS);73}74 75/* Test: When validJD is set and iJD encodes a known time, computeHMS extracts correct HMS */76void test_computeHMS_extracts_known_time_12_34_56_789(void) {77 const int H = 12, M = 34;78 const int sec = 56;79 const int ms = 789;80 const sqlite3_int64 desired_ms = (sqlite3_int64)H*3600000 + (sqlite3_int64)M*60000 + (sqlite3_int64)sec*1000 + ms;81 82 DateTime dt;83 memset(&dt, 0, sizeof(dt));84 dt.validJD = 1;85 dt.iJD = make_iJD_for_time_ms(desired_ms);86 87 test_computeHMS(&dt);88 89 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);90 TEST_ASSERT_EQUAL_INT(H, dt.h);91 TEST_ASSERT_EQUAL_INT(M, dt.m);92 TEST_ASSERT(fabs(dt.s - (sec + ms/1000.0)) <= EPS);93 TEST_ASSERT_EQUAL_INT(0, dt.rawS);94}95 96/* Test: Boundary at end of day 23:59:59.999 */97void test_computeHMS_end_of_day_23_59_59_999(void) {98 const int H = 23, M = 59;99 const int sec = 59;100 const int ms = 999;101 const sqlite3_int64 desired_ms = (sqlite3_int64)H*3600000 + (sqlite3_int64)M*60000 + (sqlite3_int64)sec*1000 + ms;102 103 DateTime dt;104 memset(&dt, 0, sizeof(dt));105 dt.validJD = 1;106 dt.iJD = make_iJD_for_time_ms(desired_ms);107 108 test_computeHMS(&dt);109 110 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);111 TEST_ASSERT_EQUAL_INT(H, dt.h);112 TEST_ASSERT_EQUAL_INT(M, dt.m);113 TEST_ASSERT(fabs(dt.s - (sec + ms/1000.0)) <= EPS);114 TEST_ASSERT_EQUAL_INT(0, dt.rawS);115}116 117/* Test: If iJD is a multiple of the day (mod 86400000 == 0), time should be 12:00:00 (noon) */118void test_computeHMS_mod_zero_returns_noon(void) {119 const sqlite3_int64 DAY_MS = 86400000;120 DateTime dt;121 memset(&dt, 0, sizeof(dt));122 dt.validJD = 1;123 dt.iJD = 54321 * DAY_MS; /* remainder 0 */124 125 test_computeHMS(&dt);126 127 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);128 TEST_ASSERT_EQUAL_INT(12, dt.h);129 TEST_ASSERT_EQUAL_INT(0, dt.m);130 TEST_ASSERT(fabs(dt.s - 0.0) <= EPS);131 TEST_ASSERT_EQUAL_INT(0, dt.rawS);132}133 134/* Test: Specific valid YMD provided should still yield midnight (00:00:00) */135void test_computeHMS_with_specific_YMD_midnight(void) {136 DateTime dt;137 memset(&dt, 0, sizeof(dt));138 dt.Y = 2023;139 dt.M = 10;140 dt.D = 5;141 dt.validYMD = 1;142 /* validJD=0 so computeJD will compute iJD for 2023-10-05 00:00:00 UT */143 144 test_computeHMS(&dt);145 146 TEST_ASSERT_EQUAL_INT(1, dt.validJD);147 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);148 TEST_ASSERT_EQUAL_INT(0, dt.h);149 TEST_ASSERT_EQUAL_INT(0, dt.m);150 TEST_ASSERT(fabs(dt.s - 0.0) <= EPS);151 TEST_ASSERT_EQUAL_INT(0, dt.rawS);152}153 154int main(void) {155 UNITY_BEGIN();156 RUN_TEST(test_computeHMS_early_return_when_validHMS_set);157 RUN_TEST(test_computeHMS_default_date_midnight);158 RUN_TEST(test_computeHMS_extracts_known_time_12_34_56_789);159 RUN_TEST(test_computeHMS_end_of_day_23_59_59_999);160 RUN_TEST(test_computeHMS_mod_zero_returns_noon);161 RUN_TEST(test_computeHMS_with_specific_YMD_midnight);162 return UNITY_END();163}