summaryrefslogtreecommitdiff
path: root/libmisc/tests/test_vcall.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-15 15:12:08 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-15 21:40:37 -0700
commit5704de985cff1d40359ecd15211cece0fbe79067 (patch)
tree5c172a6ea91716f4f8023e58d580e4b08fbd7fc1 /libmisc/tests/test_vcall.c
parentf753128b22b61d4f85a74ba2694b8f9a576fc238 (diff)
Add tests to libmisc
Diffstat (limited to 'libmisc/tests/test_vcall.c')
-rw-r--r--libmisc/tests/test_vcall.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/libmisc/tests/test_vcall.c b/libmisc/tests/test_vcall.c
new file mode 100644
index 0000000..f36fc4b
--- /dev/null
+++ b/libmisc/tests/test_vcall.c
@@ -0,0 +1,74 @@
+/* libmisc/tests/test_vcall.c - Tests for <libmisc/vcall.h>
+ *
+ * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libmisc/assert.h>
+#include <libmisc/vcall.h>
+
+#include "test.h"
+
+/******************************************************************************/
+
+struct frobber_vtable;
+
+typedef struct {
+ struct frobber_vtable *vtable;
+} implements_frobber;
+
+struct frobber_vtable {
+ int (*frob)(implements_frobber *);
+ int (*frob1)(implements_frobber *, int);
+ void (*frob0)(implements_frobber *);
+};
+
+/******************************************************************************/
+
+struct myclass {
+ int a;
+ implements_frobber;
+};
+static_assert(offsetof(struct myclass, implements_frobber) != 0);
+
+static int myclass_frob(implements_frobber *_self) {
+ struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
+ test_assert(self);
+ test_assert((void*)self != (void*)_self);
+ return self->a;
+}
+
+static int myclass_frob1(implements_frobber *_self, int arg) {
+ struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
+ test_assert(self);
+ test_assert((void*)self != (void*)_self);
+ return arg;
+}
+
+static void myclass_frob0(implements_frobber *_self) {
+ struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
+ test_assert(self);
+ test_assert((void*)self != (void*)_self);
+}
+
+struct frobber_vtable myclass_vtable = {
+ .frob = myclass_frob,
+ .frob1 = myclass_frob1,
+ .frob0 = myclass_frob0,
+};
+
+/******************************************************************************/
+
+#define MAGIC1 909837
+#define MAGIC2 657441
+
+int main() {
+ struct myclass obj = {
+ .implements_frobber = { .vtable = &myclass_vtable },
+ .a = MAGIC1,
+ };
+ test_assert(VCALL(&obj, frob) == MAGIC1);
+ test_assert(VCALL(&obj, frob1, MAGIC2) == MAGIC2);
+ VCALL(&obj, frob0);
+ return 0;
+}