AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <math.h>5#include <stdio.h>6#include <stdlib.h>7 8/* Wrapper for the static function under test, provided by the module */9extern int test_parseYyyyMmDd(const char *zDate, DateTime *p);10 11static void dtZero(DateTime *p){12 memset(p, 0, sizeof(*p));13}14 15void setUp(void) {16 /* No global setup required */17}18 19void tearDown(void) {20 /* No global teardown required */21}22 23/* Basic date-only parsing */24void test_parseYyyyMmDd_date_only(void) {25 DateTime dt;26 dtZero(&dt);27 28 int rc = test_parseYyyyMmDd("2023-07-15", &dt);29 TEST_ASSERT_EQUAL_INT(0, rc);30 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);31 TEST_ASSERT_EQUAL_INT(0, dt.validHMS);32 TEST_ASSERT_EQUAL_INT(0, dt.validJD);33 TEST_ASSERT_EQUAL_INT(2023, dt.Y);34 TEST_ASSERT_EQUAL_INT(7, dt.M);35 TEST_ASSERT_EQUAL_INT(15, dt.D);36 TEST_ASSERT_EQUAL_INT(0, dt.nFloor); /* No overflow */37}38 39/* Date + time with space separator */40void test_parseYyyyMmDd_date_time_space(void) {41 DateTime dt;42 dtZero(&dt);43 44 int rc = test_parseYyyyMmDd("2023-07-15 12:34:56", &dt);45 TEST_ASSERT_EQUAL_INT(0, rc);46 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);47 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);48 TEST_ASSERT_EQUAL_INT(0, dt.validJD); /* No timezone => JD not computed */49 TEST_ASSERT_EQUAL_INT(2023, dt.Y);50 TEST_ASSERT_EQUAL_INT(7, dt.M);51 TEST_ASSERT_EQUAL_INT(15, dt.D);52 TEST_ASSERT_EQUAL_INT(12, dt.h);53 TEST_ASSERT_EQUAL_INT(34, dt.m);54 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 56.0, dt.s);55}56 57/* Date + time with 'T' separator */58void test_parseYyyyMmDd_date_time_T(void) {59 DateTime dt;60 dtZero(&dt);61 62 int rc = test_parseYyyyMmDd("2023-07-15T12:34", &dt);63 TEST_ASSERT_EQUAL_INT(0, rc);64 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);65 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);66 TEST_ASSERT_EQUAL_INT(0, dt.validJD);67 TEST_ASSERT_EQUAL_INT(12, dt.h);68 TEST_ASSERT_EQUAL_INT(34, dt.m);69 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 0.0, dt.s);70}71 72/* Fractional seconds, truncation behavior (>0.999 -> 0.999) */73void test_parseYyyyMmDd_fractional_seconds_truncate(void) {74 DateTime dt;75 dtZero(&dt);76 77 int rc = test_parseYyyyMmDd("2023-07-15 01:02:03.9999", &dt);78 TEST_ASSERT_EQUAL_INT(0, rc);79 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);80 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);81 TEST_ASSERT_EQUAL_INT(1, dt.h == 1);82 TEST_ASSERT_EQUAL_INT(1, dt.m == 2);83 /* Expect 3.999 exactly by truncation rule */84 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 3.999, dt.s);85}86 87/* Invalid: short month digits */88void test_parseYyyyMmDd_invalid_short_month(void) {89 DateTime dt;90 dtZero(&dt);91 92 int rc = test_parseYyyyMmDd("2023-7-15", &dt);93 TEST_ASSERT_EQUAL_INT(1, rc);94}95 96/* Invalid: trailing unexpected character without time */97void test_parseYyyyMmDd_invalid_trailing_char(void) {98 DateTime dt;99 dtZero(&dt);100 101 int rc = test_parseYyyyMmDd("2023-07-15X", &dt);102 TEST_ASSERT_EQUAL_INT(1, rc);103}104 105/* Leap day valid */106void test_parseYyyyMmDd_feb29_valid_leap_year(void) {107 DateTime dt;108 dtZero(&dt);109 110 int rc = test_parseYyyyMmDd("2020-02-29", &dt);111 TEST_ASSERT_EQUAL_INT(0, rc);112 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);113 TEST_ASSERT_EQUAL_INT(0, dt.validHMS);114 TEST_ASSERT_EQUAL_INT(0, dt.nFloor); /* Valid date */115}116 117/* Leap day invalid (non-leap year) — overflow detected by computeFloor */118void test_parseYyyyMmDd_feb29_invalid_non_leap_year(void) {119 DateTime dt;120 dtZero(&dt);121 122 int rc = test_parseYyyyMmDd("2019-02-29", &dt);123 TEST_ASSERT_EQUAL_INT(0, rc); /* Parsing succeeds */124 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);125 TEST_ASSERT_EQUAL_INT(0, dt.validHMS);126 TEST_ASSERT_EQUAL_INT(1, dt.nFloor); /* Indicates overflow */127}128 129/* April 31 — overflow of day-of-month */130void test_parseYyyyMmDd_april31_overflow(void) {131 DateTime dt;132 dtZero(&dt);133 134 int rc = test_parseYyyyMmDd("2023-04-31", &dt);135 TEST_ASSERT_EQUAL_INT(0, rc); /* Parsing succeeds */136 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);137 TEST_ASSERT_EQUAL_INT(1, dt.nFloor); /* 31 is overflow for April */138}139 140/* Month out of range */141void test_parseYyyyMmDd_month_out_of_range(void) {142 DateTime dt;143 dtZero(&dt);144 145 int rc = test_parseYyyyMmDd("2023-13-01", &dt);146 TEST_ASSERT_EQUAL_INT(1, rc);147}148 149/* Day zero invalid */150void test_parseYyyyMmDd_day_zero_invalid(void) {151 DateTime dt;152 dtZero(&dt);153 154 int rc = test_parseYyyyMmDd("2023-01-00", &dt);155 TEST_ASSERT_EQUAL_INT(1, rc);156}157 158/* Negative year parsing */159void test_parseYyyyMmDd_negative_year(void) {160 DateTime dt;161 dtZero(&dt);162 163 int rc = test_parseYyyyMmDd("-0010-01-02", &dt);164 TEST_ASSERT_EQUAL_INT(0, rc);165 TEST_ASSERT_EQUAL_INT(-10, dt.Y);166 TEST_ASSERT_EQUAL_INT(1, dt.M);167 TEST_ASSERT_EQUAL_INT(2, dt.D);168}169 170/* Timezone "+HH:MM" should trigger computeJD: validJD set, validYMD/HMS cleared, tz reset, isUtc set */171void test_parseYyyyMmDd_timezone_offset_triggers_jd(void) {172 DateTime dt;173 dtZero(&dt);174 175 int rc = test_parseYyyyMmDd("2023-07-15 12:34:56+02:30", &dt);176 TEST_ASSERT_EQUAL_INT(0, rc);177 TEST_ASSERT_EQUAL_INT(1, dt.validJD);178 TEST_ASSERT_EQUAL_INT(0, dt.validYMD);179 TEST_ASSERT_EQUAL_INT(0, dt.validHMS);180 TEST_ASSERT_EQUAL_INT(0, dt.tz); /* Reset by computeJD */181 TEST_ASSERT_EQUAL_INT(1, dt.isUtc);182 TEST_ASSERT_EQUAL_INT(0, dt.isLocal);183}184 185/* Timezone "Z" (UTC) should not trigger computeJD (tz==0), but isUtc should be set */186void test_parseYyyyMmDd_timezone_Z_sets_utc_no_jd(void) {187 DateTime dt;188 dtZero(&dt);189 190 int rc = test_parseYyyyMmDd("2023-07-15T12:34:56Z", &dt);191 TEST_ASSERT_EQUAL_INT(0, rc);192 TEST_ASSERT_EQUAL_INT(0, dt.validJD); /* tz==0 -> computeJD not called here */193 TEST_ASSERT_EQUAL_INT(1, dt.validYMD);194 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);195 TEST_ASSERT_EQUAL_INT(1, dt.isUtc);196}197 198/* Invalid trailing garbage after time should fail */199void test_parseYyyyMmDd_invalid_trailing_after_time(void) {200 DateTime dt;201 dtZero(&dt);202 203 int rc = test_parseYyyyMmDd("2023-01-01 00:00:00abc", &dt);204 TEST_ASSERT_EQUAL_INT(1, rc);205}206 207/* Multiple spaces between date and time are allowed */208void test_parseYyyyMmDd_multiple_spaces_separator(void) {209 DateTime dt;210 dtZero(&dt);211 212 int rc = test_parseYyyyMmDd("2023-08-09 05:06", &dt);213 TEST_ASSERT_EQUAL_INT(0, rc);214 TEST_ASSERT_EQUAL_INT(1, dt.validHMS);215 TEST_ASSERT_EQUAL_INT(5, dt.h);216 TEST_ASSERT_EQUAL_INT(6, dt.m);217 TEST_ASSERT_DOUBLE_WITHIN(1e-12, 0.0, dt.s);218}219 220int main(void) {221 UNITY_BEGIN();222 223 RUN_TEST(test_parseYyyyMmDd_date_only);224 RUN_TEST(test_parseYyyyMmDd_date_time_space);225 RUN_TEST(test_parseYyyyMmDd_date_time_T);226 RUN_TEST(test_parseYyyyMmDd_fractional_seconds_truncate);227 RUN_TEST(test_parseYyyyMmDd_invalid_short_month);228 RUN_TEST(test_parseYyyyMmDd_invalid_trailing_char);229 RUN_TEST(test_parseYyyyMmDd_feb29_valid_leap_year);230 RUN_TEST(test_parseYyyyMmDd_feb29_invalid_non_leap_year);231 RUN_TEST(test_parseYyyyMmDd_april31_overflow);232 RUN_TEST(test_parseYyyyMmDd_month_out_of_range);233 RUN_TEST(test_parseYyyyMmDd_day_zero_invalid);234 RUN_TEST(test_parseYyyyMmDd_negative_year);235 RUN_TEST(test_parseYyyyMmDd_timezone_offset_triggers_jd);236 RUN_TEST(test_parseYyyyMmDd_timezone_Z_sets_utc_no_jd);237 RUN_TEST(test_parseYyyyMmDd_invalid_trailing_after_time);238 RUN_TEST(test_parseYyyyMmDd_multiple_spaces_separator);239 240 return UNITY_END();241}