#include "hsv.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int passed = 0;
static int failed = 0;
#define TEST(name, code) do { \
if (code) { \
printf("✓ %s\n", name); \
passed++; \
} else { \
printf("✗ %s\n", name); \
failed++; \
} \
} while(0)
int main(void) {
printf("==================================================\n");
printf("HSV Parser Tests (C)\n");
printf("==================================================\n");
{
char test[64];
snprintf(test, sizeof(test), "%cname%cAlice%cage%c30%c",
HSV_STX, HSV_US, HSV_RS, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->record_count == 1 &&
strcmp(hsv_get_string(doc->records[0], "name"), "Alice") == 0 &&
strcmp(hsv_get_string(doc->records[0], "age"), "30") == 0;
TEST("Basic parsing", ok);
hsv_free_document(doc);
}
{
char test[64];
snprintf(test, sizeof(test), "%cname%cAlice%cname%cBob%c",
HSV_STX, HSV_US, HSV_FS, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->record_count == 2;
TEST("Multiple records", ok);
hsv_free_document(doc);
}
{
char test[64];
snprintf(test, sizeof(test), "%ctags%ca%cb%cc%c",
HSV_STX, HSV_US, HSV_GS, HSV_GS, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
hsv_value_t *tags = hsv_get(doc->records[0], "tags");
int ok = doc && doc->record_count == 1 &&
tags && tags->type == HSV_TYPE_ARRAY &&
tags->data.array.count == 3;
TEST("Array values", ok);
hsv_free_document(doc);
}
{
char test[128];
snprintf(test, sizeof(test), "%chsv%c1.0%ctype%cusers%cname%cAlice%c",
HSV_SOH, HSV_US, HSV_RS, HSV_US, HSV_STX, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->header &&
strcmp(hsv_get_string(doc->header, "hsv"), "1.0") == 0 &&
strcmp(hsv_get_string(doc->header, "type"), "users") == 0 &&
doc->record_count == 1;
TEST("SOH header", ok);
hsv_free_document(doc);
}
{
char test[128];
snprintf(test, sizeof(test), "%cuser%c%cname%cAlice%cemail%ca@b.com%c%c",
HSV_STX, HSV_US, HSV_SO, HSV_US, HSV_RS, HSV_US, HSV_SI, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
hsv_value_t *user = hsv_get(doc->records[0], "user");
int ok = doc && doc->record_count == 1 &&
user && user->type == HSV_TYPE_OBJECT &&
strcmp(hsv_get_string(user, "name"), "Alice") == 0 &&
strcmp(hsv_get_string(user, "email"), "a@b.com") == 0;
TEST("SO/SI nesting", ok);
hsv_free_document(doc);
}
{
char test[128];
snprintf(test, sizeof(test), "%cdata%c%clevel1%c%clevel2%cdeep%c%c%c",
HSV_STX, HSV_US, HSV_SO, HSV_US, HSV_SO, HSV_US, HSV_SI, HSV_SI, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
hsv_value_t *data = hsv_get(doc->records[0], "data");
hsv_value_t *level1 = data ? hsv_get(data, "level1") : NULL;
int ok = doc && level1 &&
strcmp(hsv_get_string(level1, "level2"), "deep") == 0;
TEST("Deep nesting", ok);
hsv_free_document(doc);
}
{
char test[64];
snprintf(test, sizeof(test), "%ctext%cline1\nline2\nline3%c",
HSV_STX, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->record_count == 1 &&
strcmp(hsv_get_string(doc->records[0], "text"), "line1\nline2\nline3") == 0;
TEST("Newlines in values", ok);
hsv_free_document(doc);
}
{
char test[64];
snprintf(test, sizeof(test), "%cmsg%cHe said \"hello\"%c",
HSV_STX, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->record_count == 1 &&
strcmp(hsv_get_string(doc->records[0], "msg"), "He said \"hello\"") == 0;
TEST("Quotes (no escaping)", ok);
hsv_free_document(doc);
}
{
char test[64];
snprintf(test, sizeof(test), "ignored%cname%cAlice%calso ignored",
HSV_STX, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->record_count == 1 &&
strcmp(hsv_get_string(doc->records[0], "name"), "Alice") == 0;
TEST("Mixed content", ok);
hsv_free_document(doc);
}
{
char test[64];
snprintf(test, sizeof(test), "%ca%c1%cjunk%cb%c2%c",
HSV_STX, HSV_US, HSV_ETX, HSV_STX, HSV_US, HSV_ETX);
hsv_document_t *doc = hsv_parse(test);
int ok = doc && doc->record_count == 2;
TEST("Multiple blocks", ok);
hsv_free_document(doc);
}
printf("==================================================\n");
printf("%d passed, %d failed\n", passed, failed);
printf("==================================================\n");
return failed > 0 ? 1 : 0;
}