diff options
Diffstat (limited to 'subprojects/exess/test/test_variant.c')
-rw-r--r-- | subprojects/exess/test/test_variant.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/subprojects/exess/test/test_variant.c b/subprojects/exess/test/test_variant.c new file mode 100644 index 00000000..7ef7803d --- /dev/null +++ b/subprojects/exess/test/test_variant.c @@ -0,0 +1,301 @@ +/* + Copyright 2011-2021 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "exess/exess.h" + +#include <assert.h> +#include <stdbool.h> +#include <stddef.h> +#include <string.h> + +#define CHECK_POINTEE_EQUALS(p, v) assert((p) && (*(p) == (v))) + +static const ExessDuration duration = {14, + 3 * 24 * 60 * 60 + 4 * 60 * 60 + 5 * 60 + + 6, + 0}; + +static const ExessDateTime datetime = {2001, 2, 3, false, 4, 5, 6, 0}; +static const ExessTime time = {{0}, 1, 2, 3, 0}; +static const ExessDate date = {2001, 2, 3, {0}}; + +static void +check_read(ExessVariant* const variant, + const ExessDatatype datatype, + const char* const string, + const ExessStatus expected_status, + const size_t expected_count) +{ + const ExessResult r = exess_read_variant(variant, datatype, string); + + assert(r.status == expected_status); + assert(r.count == expected_count); + assert(variant->datatype == datatype); +} + +static void +test_read_variant(void) +{ + ExessVariant variant; + + check_read(&variant, EXESS_NOTHING, "42", EXESS_UNSUPPORTED, 0); + + check_read(&variant, EXESS_DECIMAL, "1.2", EXESS_SUCCESS, 3); + CHECK_POINTEE_EQUALS(exess_get_double(&variant), 1.2); + + check_read(&variant, EXESS_DOUBLE, "3.4", EXESS_SUCCESS, 3); + assert(variant.value.as_double == 3.4); + + check_read(&variant, EXESS_FLOAT, "5.6", EXESS_SUCCESS, 3); + assert(variant.value.as_float == 5.6f); + + check_read(&variant, EXESS_BOOLEAN, "true", EXESS_SUCCESS, 4); + assert(variant.value.as_bool); + + check_read(&variant, EXESS_INTEGER, "7", EXESS_SUCCESS, 1); + assert(variant.value.as_long == 7); + + check_read( + &variant, EXESS_NON_POSITIVE_INTEGER, "f", EXESS_EXPECTED_DIGIT, 0); + check_read(&variant, EXESS_NON_POSITIVE_INTEGER, "1", EXESS_OUT_OF_RANGE, 1); + check_read(&variant, EXESS_NON_POSITIVE_INTEGER, "-8", EXESS_SUCCESS, 2); + assert(variant.value.as_long == -8); + + check_read(&variant, EXESS_NEGATIVE_INTEGER, "f", EXESS_EXPECTED_DIGIT, 0); + check_read(&variant, EXESS_NEGATIVE_INTEGER, "1", EXESS_OUT_OF_RANGE, 1); + check_read(&variant, EXESS_NEGATIVE_INTEGER, "-9", EXESS_SUCCESS, 2); + assert(variant.value.as_long == -9); + + check_read(&variant, EXESS_LONG, "10", EXESS_SUCCESS, 2); + assert(variant.value.as_long == 10); + + check_read(&variant, EXESS_INT, "11", EXESS_SUCCESS, 2); + assert(variant.value.as_int == 11); + + check_read(&variant, EXESS_SHORT, "12", EXESS_SUCCESS, 2); + assert(variant.value.as_short == 12); + + check_read(&variant, EXESS_BYTE, "13", EXESS_SUCCESS, 2); + assert(variant.value.as_byte == 13); + + check_read(&variant, EXESS_ULONG, "14", EXESS_SUCCESS, 2); + assert(variant.value.as_long == 14); + + check_read(&variant, EXESS_UINT, "15", EXESS_SUCCESS, 2); + assert(variant.value.as_int == 15); + + check_read(&variant, EXESS_USHORT, "16", EXESS_SUCCESS, 2); + assert(variant.value.as_short == 16); + + check_read(&variant, EXESS_UBYTE, "17", EXESS_SUCCESS, 2); + assert(variant.value.as_byte == 17); + + check_read(&variant, EXESS_POSITIVE_INTEGER, "-1", EXESS_EXPECTED_DIGIT, 0); + check_read(&variant, EXESS_POSITIVE_INTEGER, "0", EXESS_OUT_OF_RANGE, 1); + check_read(&variant, EXESS_POSITIVE_INTEGER, "18", EXESS_SUCCESS, 2); + assert(variant.value.as_long == 18); + + check_read(&variant, EXESS_DATE, "2001-01-02", EXESS_SUCCESS, 10); + assert(variant.value.as_date.year == 2001); + assert(variant.value.as_date.month == 1); + assert(variant.value.as_date.day == 2); + + check_read(&variant, EXESS_TIME, "12:15:01.25", EXESS_SUCCESS, 11); + assert(variant.value.as_time.hour == 12); + assert(variant.value.as_time.minute == 15); + assert(variant.value.as_time.second == 1); + assert(variant.value.as_time.nanosecond == 250000000); + + char blob_data[] = {0, 0, 0}; + + variant.datatype = EXESS_HEX; + variant.value.as_blob.size = sizeof(blob_data); + variant.value.as_blob.data = blob_data; + check_read(&variant, EXESS_HEX, "666F6F", EXESS_SUCCESS, 6); + assert(!strncmp(blob_data, "foo", sizeof(blob_data))); + + variant.datatype = EXESS_BASE64; + variant.value.as_blob.size = sizeof(blob_data); + variant.value.as_blob.data = blob_data; + check_read(&variant, EXESS_BASE64, "Zm9v", EXESS_SUCCESS, 4); + assert(!strncmp(blob_data, "foo", sizeof(blob_data))); +} + +static void +test_variant_string_length(void) +{ + const ExessVariant variant = {EXESS_DECIMAL, {.as_double = 12.3456}}; + + assert(exess_write_variant(variant, 0, NULL).count == 7); +} + +static void +check_write(const ExessVariant value, + const ExessStatus expected_status, + const size_t buf_size, + const char* const expected_string) +{ + char buf[328] = {42}; + + assert(buf_size <= sizeof(buf)); + + const ExessResult r = exess_write_variant(value, buf_size, buf); + assert(r.status == expected_status); + if (buf_size > 0) { + assert(r.count == strlen(buf)); + assert(!strcmp(buf, expected_string)); + } +} + +static void +test_write_variant(void) +{ + char blob_data[] = {'f', 'o', 'o'}; + const ExessBlob blob = {sizeof(blob_data), blob_data}; + + const ExessVariant a_nothing = exess_make_nothing(EXESS_SUCCESS); + const ExessVariant a_bool = exess_make_boolean(true); + const ExessVariant a_decimal = exess_make_decimal(1.2); + const ExessVariant a_double = exess_make_double(3.4); + const ExessVariant a_float = exess_make_float(5.6f); + const ExessVariant a_long = exess_make_long(7); + const ExessVariant a_int = exess_make_int(8); + const ExessVariant a_short = exess_make_short(9); + const ExessVariant a_byte = exess_make_byte(10); + const ExessVariant a_ulong = exess_make_ulong(11); + const ExessVariant a_uint = exess_make_uint(12); + const ExessVariant a_ushort = exess_make_ushort(13); + const ExessVariant a_ubyte = exess_make_ubyte(14); + const ExessVariant a_duration = exess_make_duration(duration); + const ExessVariant a_datetime = exess_make_datetime(datetime); + const ExessVariant a_time = exess_make_time(time); + const ExessVariant a_date = exess_make_date(date); + const ExessVariant a_hex = exess_make_hex(blob); + const ExessVariant a_base64 = exess_make_base64(blob); + + check_write(a_nothing, EXESS_BAD_VALUE, 0, ""); + check_write(a_nothing, EXESS_BAD_VALUE, 1, ""); + check_write(a_decimal, EXESS_SUCCESS, 4, "1.2"); + check_write(a_double, EXESS_SUCCESS, 6, "3.4E0"); + check_write(a_float, EXESS_SUCCESS, 12, "5.5999999E0"); + check_write(a_bool, EXESS_SUCCESS, 5, "true"); + check_write(a_long, EXESS_SUCCESS, 2, "7"); + check_write(a_int, EXESS_SUCCESS, 2, "8"); + check_write(a_short, EXESS_SUCCESS, 2, "9"); + check_write(a_byte, EXESS_SUCCESS, 3, "10"); + check_write(a_ulong, EXESS_SUCCESS, 3, "11"); + check_write(a_uint, EXESS_SUCCESS, 3, "12"); + check_write(a_ushort, EXESS_SUCCESS, 3, "13"); + check_write(a_ubyte, EXESS_SUCCESS, 3, "14"); + check_write(a_duration, EXESS_SUCCESS, 15, "P1Y2M3DT4H5M6S"); + check_write(a_datetime, EXESS_SUCCESS, 40, "2001-02-03T04:05:06"); + check_write(a_time, EXESS_SUCCESS, 40, "01:02:03Z"); + check_write(a_date, EXESS_SUCCESS, 40, "2001-02-03Z"); + check_write(a_hex, EXESS_SUCCESS, 7, "666F6F"); + check_write(a_base64, EXESS_SUCCESS, 5, "Zm9v"); + + const ExessBlob null_blob = {0, NULL}; + + const ExessVariant null_hex = exess_make_hex(null_blob); + check_write(null_hex, EXESS_BAD_VALUE, 99, ""); + + const ExessVariant null_base64 = exess_make_base64(null_blob); + check_write(null_base64, EXESS_BAD_VALUE, 99, ""); +} + +static void +test_make_get(void) +{ + char blob_data[] = {'f', 'o', 'o'}; + const ExessBlob blob = {sizeof(blob_data), blob_data}; + + const ExessVariant a_nothing = exess_make_nothing(EXESS_NO_SPACE); + const ExessVariant a_bool = exess_make_boolean(true); + const ExessVariant a_decimal = exess_make_decimal(1.2); + const ExessVariant a_double = exess_make_double(3.4); + const ExessVariant a_float = exess_make_float(5.6f); + const ExessVariant a_long = exess_make_long(7); + const ExessVariant a_int = exess_make_int(8); + const ExessVariant a_short = exess_make_short(9); + const ExessVariant a_byte = exess_make_byte(10); + const ExessVariant a_ulong = exess_make_ulong(11); + const ExessVariant a_uint = exess_make_uint(12); + const ExessVariant a_ushort = exess_make_ushort(13); + const ExessVariant a_ubyte = exess_make_ubyte(14); + const ExessVariant a_duration = exess_make_duration(duration); + const ExessVariant a_datetime = exess_make_datetime(datetime); + const ExessVariant a_time = exess_make_time(time); + const ExessVariant a_date = exess_make_date(date); + const ExessVariant a_hex = exess_make_hex(blob); + const ExessVariant a_base64 = exess_make_base64(blob); + + // Different types as status + assert(exess_get_status(&a_nothing) == EXESS_NO_SPACE); + assert(exess_get_status(&a_bool) == EXESS_SUCCESS); + + // Basic successful get + CHECK_POINTEE_EQUALS(exess_get_boolean(&a_bool), true); + CHECK_POINTEE_EQUALS(exess_get_double(&a_decimal), 1.2); + CHECK_POINTEE_EQUALS(exess_get_double(&a_double), 3.4); + CHECK_POINTEE_EQUALS(exess_get_float(&a_float), 5.6f); + CHECK_POINTEE_EQUALS(exess_get_long(&a_long), 7); + CHECK_POINTEE_EQUALS(exess_get_int(&a_int), 8); + CHECK_POINTEE_EQUALS(exess_get_short(&a_short), 9); + CHECK_POINTEE_EQUALS(exess_get_byte(&a_byte), 10); + CHECK_POINTEE_EQUALS(exess_get_ulong(&a_ulong), 11u); + CHECK_POINTEE_EQUALS(exess_get_uint(&a_uint), 12u); + CHECK_POINTEE_EQUALS(exess_get_ushort(&a_ushort), 13u); + CHECK_POINTEE_EQUALS(exess_get_ubyte(&a_ubyte), 14u); + assert(!memcmp(exess_get_duration(&a_duration), &duration, sizeof(duration))); + assert(!memcmp(exess_get_datetime(&a_datetime), &datetime, sizeof(datetime))); + assert(!memcmp(exess_get_time(&a_time), &time, sizeof(time))); + assert(!memcmp(exess_get_date(&a_date), &date, sizeof(date))); + assert(exess_get_blob(&a_hex)->size == sizeof(blob_data)); + assert(exess_get_blob(&a_hex)->data == blob_data); + assert(exess_get_blob(&a_base64)->size == sizeof(blob_data)); + assert(exess_get_blob(&a_base64)->data == blob_data); + + // Unsuccessful get + assert(!exess_get_boolean(&a_int)); + assert(!exess_get_double(&a_int)); + assert(!exess_get_float(&a_int)); + assert(!exess_get_long(&a_bool)); + assert(!exess_get_int(&a_bool)); + assert(!exess_get_short(&a_int)); + assert(!exess_get_byte(&a_int)); + assert(!exess_get_ulong(&a_int)); + assert(!exess_get_uint(&a_int)); + assert(!exess_get_ushort(&a_int)); + assert(!exess_get_ubyte(&a_int)); + assert(!exess_get_duration(&a_int)); + assert(!exess_get_datetime(&a_int)); + assert(!exess_get_time(&a_int)); + assert(!exess_get_date(&a_int)); + assert(!exess_get_blob(&a_int)); +} + +int +main(void) +{ + test_read_variant(); + test_variant_string_length(); + test_write_variant(); + test_make_get(); + + return 0; +} |