lib/: Pure C machinery for handling `keyword arguments' to functions.
[sod] / test / kwtest.c
diff --git a/test/kwtest.c b/test/kwtest.c
new file mode 100644 (file)
index 0000000..b760ed4
--- /dev/null
@@ -0,0 +1,143 @@
+/* -*-c-*-
+ *
+ * Test program for the keyword-argument machinery
+ *
+ * (c) 2015 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the Sensible Object Design, an object system for C.
+ *
+ * SOD is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * SOD is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SOD; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "keyword.h"
+
+static void show_kwval(const char *what, int f, const char *fmt, ...)
+{
+  va_list ap;
+
+  printf("  %s = ", what);
+  if (!f)
+    puts("<unset>");
+  else {
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
+    putchar('\n');
+  }
+}
+
+#define SHOW(mem, fmt) show_kwval(#mem, kw.mem##_suppliedp, fmt, kw.mem)
+
+#define t1_KWSET(_)                                                    \
+  _(int, x, 0)                                                         \
+  _(double, y, 69.0)                                                   \
+  _(const char *, z, "default")
+KWSET_STRUCT(t1);
+static KWSET_PARSEFN(t1)
+static KWCALL void t1(const char *what, KWTAIL)
+{
+  KWPARSE(t1);
+
+  printf("t1: %s\n", what);
+  SHOW(x, "%d");
+  SHOW(y, "%g");
+  SHOW(z, "`%s'");
+}
+
+static KWCALL void t2(const char *what, ...)
+{
+  va_list ap;
+
+  printf("t2: %s\n", what);
+  va_start(ap, what);
+  t1("via t2", KWARGS(K_VALIST(ap)));
+  va_end(ap);
+}
+
+#define t3_KWSET(_)                                                    \
+  _(int, q, 0)                                                         \
+  t1_KWSET(_)
+KWSET_STRUCT(t3);
+static KWSET_PARSEFN(t3)
+static KWCALL void t3(const char *what, KWTAIL)
+{
+  struct kwval v[KW_COUNT(t1)];
+  size_t n = 0;
+  KWPARSE(t3);
+
+  printf("t3: %s\n", what);
+  SHOW(q, "%c");
+  SHOW(z, "`%s'");
+
+  KW_COPY(t3, t1, kw, v, n);
+  t1("via t3", KWARGS(K_TAB(v, n)
+                     K(x, kw.x_suppliedp ? kw.x + 1 : 42)));
+}
+
+/* The @KW_TEST@ machinery from the manpage... */
+#define KWARGS_TEST(k, val) KWARGS(K(k, val) K(kw.unknown, 0))
+
+static jmp_buf kw_test_jmp;
+
+static void kw_test_unknown(const char *set, const char *kw)
+{
+  if (strcmp(kw, "kw.unknown") == 0) longjmp(kw_test_jmp, 1);
+  else longjmp(kw_test_jmp, 2);
+}
+
+#define KW_TEST(flag, set, call) do {                                  \
+  kw_unkhookfn *oldunk = kw_unkhook;                                   \
+  kw_unkhook = kw_test_unknown;                                                \
+  switch (setjmp(kw_test_jmp)) {                                       \
+    case 0: call; abort();                                             \
+    case 1: flag = 1; break;                                           \
+    case 2: flag = 0; break;                                           \
+    default: abort();                                                  \
+  }                                                                    \
+  kw_unkhook = oldunk;                                                 \
+} while (0)
+/* END */
+
+int main(void)
+{
+  t1("no args", NO_KWARGS);
+  t1("some args", KWARGS(K(z, "set") K(x, 42)));
+
+  t2("indirection", KWARGS(K(y, 6.283)));
+
+  t3("no args", NO_KWARGS);
+  t3("x initially 19", KWARGS(K(q, 't') K(x, 19) K(z, "boing")));
+
+#define TEST_KWTEST(kw, val) do {                                      \
+  int f_;                                                              \
+  KW_TEST(f_, t3, t3(0, KWARGS_TEST(kw, val)));                                \
+  printf("t3 arg `%s' %s\n", #kw, f_ ? "present" : "absent");          \
+} while (0)
+  TEST_KWTEST(q, '!');
+  TEST_KWTEST(z, "splat");
+  TEST_KWTEST(nope, 0);
+
+  return (0);
+}
+
+/*----- That's all, folks -------------------------------------------------*/