Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_date_parseModifier.c216 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <string.h>5#include <stdio.h>6#include <math.h>7 8/* Convenience: milliseconds per day */9#define MS_PER_DAY 86400000LL10 11/* Helper to compare 64-bit integers with a message */12static void assertI64Equal(sqlite3_int64 actual, sqlite3_int64 expected, const char *msg){13  if( actual!=expected ){14    char buf[256];15    sqlite3_snprintf(sizeof(buf), buf, "%s: expected %lld got %lld",16                     msg, (long long)expected, (long long)actual);17    TEST_FAIL_MESSAGE(buf);18  }19}20 21/* Initialize a DateTime to the given Y-M-D h:m:s and force iJD via "+0 days" */22static void initYMDHMS(DateTime *p, int Y, int M, int D, int h, int m, double s){23  memset(p, 0, sizeof(*p));24  p->Y = Y; p->M = M; p->D = D; p->validYMD = 1;25  if( h>=0 ){26    p->h = h; p->m = m; p->s = s; p->validHMS = 1;27  }28  /* Force compute of iJD using a no-op relative modifier */29  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "0 days", (int)strlen("0 days"), p, 1));30}31 32void setUp(void) {33  /* no-op */34}35void tearDown(void) {36  /* no-op */37}38 39/* auto: idx constraint and conversion */40void test_parseModifier_auto_idx_and_conversion(void){41  DateTime p; memset(&p, 0, sizeof(p));42  /* Ambiguous raw number: seconds since 1970 (0) */43  p.rawS = 1; p.s = 0.0;44  int rc = test_parseModifier(NULL, "auto", (int)strlen("auto"), &p, 1);45  TEST_ASSERT_EQUAL_INT(0, rc);46  TEST_ASSERT_TRUE(p.validJD!=0);47  TEST_ASSERT_EQUAL_INT(0, p.rawS);48  /* iJD == 210866760000000 for 1970-01-01 00:00:00 */49  assertI64Equal(p.iJD, (sqlite3_int64)210866760000000LL, "auto(0) iJD");50 51  /* idx > 1 must fail with no change */52  DateTime q; memset(&q, 0, sizeof(q));53  q.rawS = 1; q.s = 0.0;54  rc = test_parseModifier(NULL, "auto", (int)strlen("auto"), &q, 2);55  TEST_ASSERT_EQUAL_INT(1, rc);56  TEST_ASSERT_EQUAL_INT(1, q.rawS);57  TEST_ASSERT_EQUAL_INT(0, q.validJD);58}59 60/* unixepoch conversion and idx constraint */61void test_parseModifier_unixepoch_conversion(void){62  DateTime p; memset(&p, 0, sizeof(p));63  p.rawS = 1; p.s = 1620000000.0; /* 2021-05-03 00:00:00 UTC */64  int rc = test_parseModifier(NULL, "unixepoch", (int)strlen("unixepoch"), &p, 1);65  TEST_ASSERT_EQUAL_INT(0, rc);66  TEST_ASSERT_TRUE(p.validJD!=0);67  TEST_ASSERT_EQUAL_INT(0, p.rawS);68  sqlite3_int64 expect = (sqlite3_int64)(p.s*1000.0 + 210866760000000.0);69  assertI64Equal(p.iJD, expect, "unixepoch iJD");70 71  /* idx > 1 => error (no conversion) */72  DateTime q; memset(&q, 0, sizeof(q));73  q.rawS = 1; q.s = 1.0;74  rc = test_parseModifier(NULL, "unixepoch", (int)strlen("unixepoch"), &q, 2);75  TEST_ASSERT_EQUAL_INT(1, rc);76  TEST_ASSERT_EQUAL_INT(1, q.rawS);77  TEST_ASSERT_EQUAL_INT(0, q.validJD);78}79 80/* julianday clears rawS only when validJD && rawS and idx==1 */81void test_parseModifier_julianday_behavior(void){82  DateTime p; memset(&p, 0, sizeof(p));83  p.validJD = 1; p.iJD = 123456789LL; p.rawS = 1;84  int rc = test_parseModifier(NULL, "julianday", (int)strlen("julianday"), &p, 1);85  TEST_ASSERT_EQUAL_INT(0, rc);86  TEST_ASSERT_EQUAL_INT(0, p.rawS);87  assertI64Equal(p.iJD, 123456789LL, "julianday preserves iJD");88 89  DateTime q; memset(&q, 0, sizeof(q));90  q.rawS = 1; /* no validJD */91  rc = test_parseModifier(NULL, "julianday", (int)strlen("julianday"), &q, 1);92  TEST_ASSERT_EQUAL_INT(1, rc);93  TEST_ASSERT_EQUAL_INT(1, q.rawS);94 95  DateTime r; memset(&r, 0, sizeof(r));96  r.validJD = 1; /* rawS is 0 */97  rc = test_parseModifier(NULL, "julianday", (int)strlen("julianday"), &r, 1);98  TEST_ASSERT_EQUAL_INT(1, rc);99 100  DateTime s; memset(&s, 0, sizeof(s)); s.validJD=1; s.rawS=1;101  rc = test_parseModifier(NULL, "julianday", (int)strlen("julianday"), &s, 2);102  TEST_ASSERT_EQUAL_INT(1, rc);103  TEST_ASSERT_EQUAL_INT(1, s.rawS);104}105 106/* weekday N: no-op when already on N, and forward otherwise */107void test_parseModifier_weekday_noop_and_forward(void){108  DateTime base; initYMDHMS(&base, 2021, 3, 17, 0, 0, 0.0); /* Wednesday => N=3 */109  sqlite3_int64 jd0 = base.iJD;110 111  DateTime p1 = base;112  int rc = test_parseModifier(NULL, "weekday 3", (int)strlen("weekday 3"), &p1, 1);113  TEST_ASSERT_EQUAL_INT(0, rc);114  assertI64Equal(p1.iJD, jd0, "weekday same day");115 116  DateTime p2 = base;117  rc = test_parseModifier(NULL, "weekday 5", (int)strlen("weekday 5"), &p2, 1);118  TEST_ASSERT_EQUAL_INT(0, rc);119  assertI64Equal(p2.iJD - jd0, 2*MS_PER_DAY, "weekday advance to Friday");120}121 122/* "+HH:MM:SS.FFF" equals adding equivalent seconds */123void test_parseModifier_add_time_hhmmss_equivalent_to_seconds(void){124  DateTime base; initYMDHMS(&base, 2000, 1, 1, 0, 0, 0.0);125  DateTime p1 = base;126  DateTime p2 = base;127  int rc1 = test_parseModifier(NULL, "+01:02:03.250", (int)strlen("+01:02:03.250"), &p1, 1);128  int rc2 = test_parseModifier(NULL, "3723.25 seconds", (int)strlen("3723.25 seconds"), &p2, 1);129  TEST_ASSERT_EQUAL_INT(0, rc1);130  TEST_ASSERT_EQUAL_INT(0, rc2);131  assertI64Equal(p1.iJD, p2.iJD, "time add equivalence");132}133 134/* Adding 1 month from 2021-01-15 equals adding 31 days (to 2021-02-15) */135void test_parseModifier_add_months_no_overflow_equals_days(void){136  DateTime d1; initYMDHMS(&d1, 2021, 1, 15, 0, 0, 0.0);137  DateTime d2 = d1;138  DateTime d3 = d1;139  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "1 month", (int)strlen("1 month"), &d2, 1));140  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "31 days", (int)strlen("31 days"), &d3, 1));141  assertI64Equal(d2.iJD, d3.iJD, "1 month == 31 days (Jan15->Feb15 2021)");142}143 144/* Month overflow: Jan 31 + 1 month; floor should roll back to Feb 28 (2021) */145void test_parseModifier_month_overflow_floor_vs_default(void){146  DateTime a; memset(&a, 0, sizeof(a)); a.Y=2021; a.M=1; a.D=31; a.validYMD=1;147  DateTime b = a;148  /* default (ceiling) behavior */149  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "1 month", (int)strlen("1 month"), &a, 1));150  sqlite3_int64 jd_ceiling = a.iJD;151  /* floor behavior */152  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "1 month", (int)strlen("1 month"), &b, 1));153  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "floor", (int)strlen("floor"), &b, 2));154  sqlite3_int64 jd_floor = b.iJD;155  assertI64Equal(jd_ceiling - jd_floor, 3*MS_PER_DAY, "Jan31 +1 month: ceiling vs floor diff");156}157 158/* start of day should zero-out the time component */159void test_parseModifier_start_of_day_zeros_time(void){160  DateTime p; initYMDHMS(&p, 2020, 6, 7, 13, 24, 56.5);161  DateTime expectedStart; initYMDHMS(&expectedStart, 2020, 6, 7, 0, 0, 0.0);162 163  /* Apply start of day then force iJD calculation with a no-op */164  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "start of day", (int)strlen("start of day"), &p, 1));165  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "0 days", (int)strlen("0 days"), &p, 2));166 167  assertI64Equal(p.iJD, expectedStart.iJD, "start of day iJD");168}169 170/* subsec and subsecond set useSubsec flag */171void test_parseModifier_subsec_flags(void){172  DateTime p; memset(&p, 0, sizeof(p));173  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "subsec", (int)strlen("subsec"), &p, 1));174  TEST_ASSERT_EQUAL_INT(1, p.useSubsec);175  p.useSubsec = 0;176  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "subsecond", (int)strlen("subsecond"), &p, 1));177  TEST_ASSERT_EQUAL_INT(1, p.useSubsec);178}179 180/* +YYYY-MM-DD with time part: compare with +HH:MM equivalence */181void test_parseModifier_compound_year_day_and_time(void){182  DateTime base; initYMDHMS(&base, 2019, 12, 31, 22, 30, 0.0);183  DateTime p1 = base;184  DateTime p2 = base;185  /* Add +0000-00-00 01:30 => +01:30:00 */186  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "+0000-00-00 01:30", (int)strlen("+0000-00-00 01:30"), &p1, 1));187  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "+01:30:00", (int)strlen("+01:30:00"), &p2, 1));188  assertI64Equal(p1.iJD, p2.iJD, "compound date+time vs hh:mm:ss");189}190 191/* +1 year from leap day, floor vs default (ceiling): expect 1-day difference */192void test_parseModifier_year_addition_floor_vs_ceiling_on_leapday(void){193  DateTime a; memset(&a, 0, sizeof(a)); a.Y=2020; a.M=2; a.D=29; a.validYMD=1;194  DateTime b = a;195  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "+0001-00-00", (int)strlen("+0001-00-00"), &a, 1));196  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "+0001-00-00", (int)strlen("+0001-00-00"), &b, 1));197  TEST_ASSERT_EQUAL_INT(0, test_parseModifier(NULL, "floor", (int)strlen("floor"), &b, 2));198  sqlite3_int64 diff = a.iJD - b.iJD;199  assertI64Equal(diff, 1*MS_PER_DAY, "Leapday +1 year ceiling vs floor");200}201 202int main(void){203  UNITY_BEGIN();204  RUN_TEST(test_parseModifier_auto_idx_and_conversion);205  RUN_TEST(test_parseModifier_unixepoch_conversion);206  RUN_TEST(test_parseModifier_julianday_behavior);207  RUN_TEST(test_parseModifier_weekday_noop_and_forward);208  RUN_TEST(test_parseModifier_add_time_hhmmss_equivalent_to_seconds);209  RUN_TEST(test_parseModifier_add_months_no_overflow_equals_days);210  RUN_TEST(test_parseModifier_month_overflow_floor_vs_default);211  RUN_TEST(test_parseModifier_start_of_day_zeros_time);212  RUN_TEST(test_parseModifier_subsec_flags);213  RUN_TEST(test_parseModifier_compound_year_day_and_time);214  RUN_TEST(test_parseModifier_year_addition_floor_vs_ceiling_on_leapday);215  return UNITY_END();216}