]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
tests: Add uriparser tests
authorTomas Bzatek <tbzatek@redhat.com>
Wed, 17 Apr 2024 16:06:23 +0000 (18:06 +0200)
committerDaniel Wagner <wagi@monom.org>
Wed, 15 May 2024 17:55:21 +0000 (19:55 +0200)
Simple testcase both for valid and malformed URI strings.

Signed-off-by: Tomas Bzatek <tbzatek@redhat.com>
test/meson.build
test/uriparser.c [new file with mode: 0644]

index 93e69991d6d74b872e5da32274d02fa3cbd0f80d..55992df718cf5fe6a7de78ee2fb8bd71aa8e5963 100644 (file)
@@ -66,6 +66,15 @@ uuid = executable(
 
 test('uuid', uuid)
 
+uriparser = executable(
+    'test-uriparser',
+    ['uriparser.c'],
+    dependencies: libnvme_dep,
+    include_directories: [incdir, internal_incdir]
+)
+
+test('uriparser', uriparser)
+
 if conf.get('HAVE_NETDB')
     mock_ifaddrs = library(
         'mock-ifaddrs',
diff --git a/test/uriparser.c b/test/uriparser.c
new file mode 100644 (file)
index 0000000..cf26bfd
--- /dev/null
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/**
+ * This file is part of libnvme.
+ * Copyright (c) 2024 Tomas Bzatek <tbzatek@redhat.com>
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <ccan/array_size/array_size.h>
+
+#include <libnvme.h>
+#include <nvme/private.h>
+
+struct test_data {
+       const char *uri;
+       /* parsed data */
+       const char *scheme;
+       const char *host;
+       const char *user;
+       const char *proto;
+       int port;
+       const char *path[7];
+       const char *query;
+       const char *frag;
+};
+
+static struct test_data test_data[] = {
+       { "nvme://192.168.1.1",  "nvme", "192.168.1.1" },
+       { "nvme://192.168.1.1/", "nvme", "192.168.1.1" },
+       { "nvme://192.168.1.1:1234",  "nvme", "192.168.1.1", .port = 1234 },
+       { "nvme://192.168.1.1:1234/", "nvme", "192.168.1.1", .port = 1234 },
+       { "nvme+tcp://192.168.1.1",   "nvme", "192.168.1.1", .proto = "tcp" },
+       { "nvme+rdma://192.168.1.1/", "nvme", "192.168.1.1", .proto = "rdma" },
+       { "nvme+tcp://192.168.1.1:1234",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 1234 },
+       { "nvme+tcp://192.168.1.1:1234/",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 1234 },
+       { "nvme+tcp://192.168.1.1:4420/path",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+         .path = { "path", NULL }},
+       { "nvme+tcp://192.168.1.1/path/",
+         "nvme", "192.168.1.1", .proto = "tcp", .path = { "path", NULL }},
+       { "nvme+tcp://192.168.1.1:4420/p1/p2/p3",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+         .path = { "p1", "p2", "p3", NULL }},
+       { "nvme+tcp://192.168.1.1:4420/p1/p2/p3/",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+         .path = { "p1", "p2", "p3", NULL }},
+       { "nvme+tcp://192.168.1.1:4420//p1//p2/////p3",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+         .path = { "p1", "p2", "p3", NULL }},
+       { "nvme+tcp://192.168.1.1:4420//p1//p2/////p3/",
+         "nvme", "192.168.1.1", .proto = "tcp", .port = 4420,
+         .path = { "p1", "p2", "p3", NULL }},
+       { "nvme://[fe80::1010]",  "nvme", "fe80::1010" },
+       { "nvme://[fe80::1010]/", "nvme", "fe80::1010" },
+       { "nvme://[fe80::1010]:1234",  "nvme", "fe80::1010", .port = 1234 },
+       { "nvme://[fe80::1010]:1234/", "nvme", "fe80::1010", .port = 1234 },
+       { "nvme+tcp://[fe80::1010]",   "nvme", "fe80::1010", .proto = "tcp" },
+       { "nvme+rdma://[fe80::1010]/", "nvme", "fe80::1010", .proto = "rdma" },
+       { "nvme+tcp://[fe80::1010]:1234",
+         "nvme", "fe80::1010", .proto = "tcp", .port = 1234 },
+       { "nvme+tcp://[fe80::1010]:1234/",
+         "nvme", "fe80::1010", .proto = "tcp", .port = 1234 },
+       { "nvme+tcp://[fe80::1010]:4420/path",
+         "nvme", "fe80::1010", .proto = "tcp", .port = 4420,
+         .path = { "path", NULL }},
+       { "nvme+tcp://[fe80::1010]/path/",
+         "nvme", "fe80::1010", .proto = "tcp", .path = { "path", NULL }},
+       { "nvme+tcp://[fe80::1010]:4420/p1/p2/p3",
+         "nvme", "fe80::1010", .proto = "tcp", .port = 4420,
+         .path = { "p1", "p2", "p3", NULL }},
+       { "nvme+tcp://[fe80::fc7d:8cff:fe5b:962e]:666/p1/p2/p3/",
+         "nvme", "fe80::fc7d:8cff:fe5b:962e", .proto = "tcp", .port = 666,
+         .path = { "p1", "p2", "p3", NULL }},
+       { "nvme://h?query",  "nvme", "h", .query = "query" },
+       { "nvme://h/?query", "nvme", "h", .query = "query" },
+       { "nvme://h/x?query",
+         "nvme", "h", .path = { "x" }, .query = "query" },
+       { "nvme://h/p1/?query",
+         "nvme", "h", .path = { "p1" }, .query = "query" },
+       { "nvme://h/p1/x?query",
+         "nvme", "h", .path = { "p1", "x" }, .query = "query" },
+       { "nvme://h#fragment",  "nvme", "h", .frag = "fragment" },
+       { "nvme://h/#fragment", "nvme", "h", .frag = "fragment" },
+       { "nvme://h/x#fragment",
+         "nvme", "h", .path = { "x" }, .frag = "fragment" },
+       { "nvme://h/p1/#fragment",
+         "nvme", "h", .path = { "p1" }, .frag = "fragment" },
+       { "nvme://h/p1/x#fragment",
+         "nvme", "h", .path = { "p1", "x" }, .frag = "fragment" },
+       { "nvme://h/?query#fragment",
+         "nvme", "h", .query = "query", .frag = "fragment" },
+       { "nvme://h/x?query#fragment",
+         "nvme", "h", .path = { "x" }, .query = "query", .frag = "fragment" },
+       { "nvme://h/p1/?query#fragment",
+         "nvme", "h", .path = { "p1" }, .query = "query", .frag = "fragment" },
+       { "nvme://h/p1/x?query#fragment",
+         "nvme", "h", .path = { "p1", "x" }, .query = "query",
+          .frag = "fragment" },
+       { "nvme://h/#fragment?query",
+         "nvme", "h", .frag = "fragment?query" },
+       { "nvme://h/x#fragment?query",
+         "nvme", "h", .path = { "x" }, .frag = "fragment?query" },
+       { "nvme://h/p1/#fragment?query",
+         "nvme", "h", .path = { "p1" }, .frag = "fragment?query" },
+       { "nvme://h/p1/x#fragment?query",
+         "nvme", "h", .path = { "p1", "x" }, .frag = "fragment?query" },
+       { "nvme://user@h",  "nvme", "h", .user = "user" },
+       { "nvme://user@h/", "nvme", "h", .user = "user" },
+       { "nvme://user:pass@h/", "nvme", "h", .user = "user:pass" },
+       { "nvme://[fe80::1010]@h/", "nvme", "h", .user = "[fe80::1010]" },
+       { "nvme://u[fe80::1010]@h/", "nvme", "h", .user = "u[fe80::1010]" },
+       { "nvme://u[aa:bb::cc]@h/", "nvme", "h", .user = "u[aa:bb::cc]" },
+       { "nvme+rdma://u[aa:bb::cc]@[aa:bb::cc]:12345/p1/x?q=val#fr",
+         "nvme", "aa:bb::cc", .proto = "rdma", .port = 12345,
+         .user = "u[aa:bb::cc]", .path = { "p1", "x" },
+         .query = "q=val", .frag = "fr" },
+};
+
+const char *test_data_bad[] = {
+       "",
+       " ",
+       "nonsense",
+       "vnme:",
+       "vnme:/",
+       "vnme://",
+       "vnme:///",
+       "vnme+foo://",
+       "nvme:hostname/",
+       "nvme:/hostname/",
+       "nvme:///hostname/",
+       "nvme+foo:///hostname/",
+};
+
+static void test_uriparser(void)
+{
+       printf("Testing URI parser:\n");
+       for (int i = 0; i < ARRAY_SIZE(test_data); i++) {
+               const struct test_data *d = &test_data[i];
+               struct nvme_fabrics_uri *parsed_data;
+               char **s;
+               int i;
+
+               printf(" '%s'...", d->uri);
+               parsed_data = nvme_parse_uri(d->uri);
+               assert(parsed_data);
+
+               assert(strcmp(d->scheme, parsed_data->scheme) == 0);
+               if (d->proto) {
+                       assert(parsed_data->protocol != NULL);
+                       assert(strcmp(d->proto, parsed_data->protocol) == 0);
+               } else
+                       assert(d->proto == parsed_data->protocol);
+               assert(strcmp(d->host, parsed_data->host) == 0);
+               assert(d->port == parsed_data->port);
+
+               if (!parsed_data->path_segments)
+                       assert(d->path[0] == NULL);
+               else {
+                       for (i = 0, s = parsed_data->path_segments;
+                            s && *s; s++, i++) {
+                               assert(d->path[i] != NULL);
+                               assert(strcmp(d->path[i], *s) == 0);
+                       }
+                       /* trailing NULL element */
+                       assert(d->path[i] == parsed_data->path_segments[i]);
+               }
+               if (d->query) {
+                       assert(parsed_data->query != NULL);
+                       assert(strcmp(d->query, parsed_data->query) == 0);
+               } else
+                       assert(d->query == parsed_data->query);
+               if (d->frag) {
+                       assert(parsed_data->fragment != NULL);
+                       assert(strcmp(d->frag, parsed_data->fragment) == 0);
+               } else
+                       assert(d->frag == parsed_data->fragment);
+               nvme_free_uri(parsed_data);
+               printf("  OK\n");
+       }
+}
+
+static void test_uriparser_bad(void)
+{
+       printf("Testing malformed URI strings:\n");
+       for (int i = 0; i < ARRAY_SIZE(test_data_bad); i++) {
+               struct nvme_fabrics_uri *parsed_data;
+
+               printf(" '%s'...", test_data_bad[i]);
+               parsed_data = nvme_parse_uri(test_data_bad[i]);
+               assert(parsed_data == NULL);
+               printf("   OK\n");
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       test_uriparser();
+       test_uriparser_bad();
+
+       fflush(stdout);
+
+       return 0;
+}