aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/exess/test/test_variant.c
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/exess/test/test_variant.c')
-rw-r--r--subprojects/exess/test/test_variant.c301
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;
+}