AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7/* Prototype of the auto-generated wrapper for the static function under test */8void test_datetimeFunc(sqlite3_context *context, int argc, sqlite3_value **argv);9 10static sqlite3 *gDb = NULL;11 12static sqlite3_value *make_text_value(const char *z){13 sqlite3_value *v = sqlite3ValueNew(gDb);14 TEST_ASSERT_NOT_NULL(v);15 /* Use SQLITE_STATIC: z is a constant string literal in tests */16 sqlite3ValueSetStr(v, -1, z, SQLITE_UTF8, SQLITE_STATIC);17 return v;18}19 20static sqlite3_value *make_double_value(double d){21 sqlite3_value *v = sqlite3ValueNew(gDb);22 TEST_ASSERT_NOT_NULL(v);23 sqlite3VdbeMemSetDouble((Mem*)v, d);24 return v;25}26 27static void call_datetime_and_check(sqlite3_value **argv, int argc, const char *expected){28 sqlite3_context ctx;29 Mem out;30 memset(&ctx, 0, sizeof(ctx));31 sqlite3VdbeMemInit(&out, gDb, 0);32 ctx.pOut = &out;33 34 test_datetimeFunc(&ctx, argc, argv);35 36 const unsigned char *zRes = sqlite3_value_text((sqlite3_value*)&out);37 TEST_ASSERT_NOT_NULL(zRes);38 TEST_ASSERT_EQUAL_STRING(expected, (const char*)zRes);39 40 sqlite3VdbeMemRelease(&out);41}42 43void setUp(void) {44 int rc = sqlite3_open(":memory:", &gDb);45 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);46}47 48void tearDown(void) {49 if( gDb ){50 sqlite3_close(gDb);51 gDb = NULL;52 }53}54 55/* Basic datetime without subseconds */56void test_datetimeFunc_basic_datetime_no_subsec(void){57 sqlite3_value *argv[1];58 argv[0] = make_text_value("2023-06-01 12:34:56");59 call_datetime_and_check(argv, 1, "2023-06-01 12:34:56");60 sqlite3ValueFree(argv[0]);61}62 63/* Datetime with subseconds: verify rounding to nearest millisecond and formatting "SS.sss" */64void test_datetimeFunc_with_subseconds_rounding(void){65 sqlite3_value *argv[1];66 argv[0] = make_text_value("2023-01-01 00:00:01.2345"); /* rounds to 01.235 */67 call_datetime_and_check(argv, 1, "2023-01-01 00:00:01.235");68 sqlite3ValueFree(argv[0]);69}70 71/* Julian day number as a floating-point input */72void test_datetimeFunc_julian_number_float(void){73 sqlite3_value *argv[1];74 argv[0] = make_double_value(2451544.5); /* 2000-01-01 00:00:00 */75 call_datetime_and_check(argv, 1, "2000-01-01 00:00:00");76 sqlite3ValueFree(argv[0]);77}78 79/* Negative year formatting: ensure leading '-' and zero-padded absolute year */80void test_datetimeFunc_negative_year_format(void){81 sqlite3_value *argv[1];82 argv[0] = make_text_value("-0001-02-03 04:05:06");83 call_datetime_and_check(argv, 1, "-0001-02-03 04:05:06");84 sqlite3ValueFree(argv[0]);85}86 87/* Normalization of invalid YMD-only date: 2023-02-31 -> 2023-03-03 */88void test_datetimeFunc_normalizes_invalid_date_ymd_only(void){89 sqlite3_value *argv[1];90 argv[0] = make_text_value("2023-02-31");91 call_datetime_and_check(argv, 1, "2023-03-03 00:00:00");92 sqlite3ValueFree(argv[0]);93}94 95/* Date-only input should default to midnight */96void test_datetimeFunc_date_only_defaults_to_midnight(void){97 sqlite3_value *argv[1];98 argv[0] = make_text_value("2023-12-31");99 call_datetime_and_check(argv, 1, "2023-12-31 00:00:00");100 sqlite3ValueFree(argv[0]);101}102 103/* Subsecond boundary: verify printing when rounding hits 60.000 ms boundary */104void test_datetimeFunc_subsecond_boundary_60_seconds_print(void){105 sqlite3_value *argv[1];106 argv[0] = make_text_value("2023-01-01 00:00:59.9996"); /* rounds to 60.000 */107 /* As implemented, datetimeFunc will print "60.000" for seconds when rounding crosses 60.000 */108 call_datetime_and_check(argv, 1, "2023-01-01 00:00:60.000");109 sqlite3ValueFree(argv[0]);110}111 112int main(void) {113 UNITY_BEGIN();114 RUN_TEST(test_datetimeFunc_basic_datetime_no_subsec);115 RUN_TEST(test_datetimeFunc_with_subseconds_rounding);116 RUN_TEST(test_datetimeFunc_julian_number_float);117 RUN_TEST(test_datetimeFunc_negative_year_format);118 RUN_TEST(test_datetimeFunc_normalizes_invalid_date_ymd_only);119 RUN_TEST(test_datetimeFunc_date_only_defaults_to_midnight);120 RUN_TEST(test_datetimeFunc_subsecond_boundary_60_seconds_print);121 return UNITY_END();122}