aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2016-12-18 22:59:59 -0800
committerGarrett D'Amore <garrett@damore.org>2016-12-18 22:59:59 -0800
commitc6640e3bcfce9f3e3d4def60b0acb7ea782ab890 (patch)
tree5b3e0beac1fca6c8240ddcaba79d32290739f187 /tests
parentc2334e3e644c89595ae9fd20b1021cdc195e054e (diff)
downloadnng-c6640e3bcfce9f3e3d4def60b0acb7ea782ab890.tar.gz
nng-c6640e3bcfce9f3e3d4def60b0acb7ea782ab890.tar.bz2
nng-c6640e3bcfce9f3e3d4def60b0acb7ea782ab890.zip
Nicer convey API - more closely mirrors the Go one.
Diffstat (limited to 'tests')
-rw-r--r--tests/convey.h163
-rw-r--r--tests/list.c78
2 files changed, 202 insertions, 39 deletions
diff --git a/tests/convey.h b/tests/convey.h
new file mode 100644
index 00000000..d311acb2
--- /dev/null
+++ b/tests/convey.h
@@ -0,0 +1,163 @@
+
+/*
+ * Copyright 2016 Garrett D'Amore <garrett@damore.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef TESTS_CONVEY_H
+
+#define TESTS_CONVEY_H
+
+#include "test.h"
+
+/*
+ * This header file provides a friendlier API to the test-convey framework.
+ * It basically provides some "friendly" names for symbols to use instead of
+ * the test_xxx symbols. Basically we pollute your namespace, for your
+ * benefit. Don't like the pollution? Use test.h instead.
+ */
+
+
+
+/*
+ * This test framework allows one to write tests as a form of assertion,
+ * giving simpler and more readable test logic.
+ *
+ * The test framework provides a main() function.
+ *
+ * To use this call the test_main() macro, and embed test_convey() references.
+ * These can be nested, and after each convey the entire stack is popped so
+ * that execution can continue from the beginning, giving each test section
+ * the same environment.
+ *
+ * There are assertion macros too, which don't roll back the stack, but which
+ * do update the test state.
+ *
+ * Here's a sample file:
+ *
+ * TestMain("Integer Tests", {
+ * int x = 1; int y = 2;
+ * Convey("Addition works", func() {
+ * So(y == 2);
+ * So(y + x == 3);
+ * So(x + y == 3);
+ * Convey("Even big numbers", func() {
+ * y = 100;
+ * So(x + y == 101);
+ * });
+ * Convey("Notice y is still 2 in this context", func() {
+ * So(y == 2);
+ * });
+ * });
+ * })
+ *
+ * There are other macros, but this is a work in progress. The inspiration
+ * for this is from GoConvey -- github.com/smartystreets/goconvey - but this
+ * is a version for C programs.
+ *
+ * In addition to the names listed here, your test code should avoid using
+ * names beginning with "test_" or "T_" as we use those names internally
+ * in macros, which may collide or do other bad things with your names.
+ */
+
+/*
+ * TestMain is used to generate a main() function that runs your code,
+ * and is appropriate when your entire program consists of one test.
+ * This is equivalent to doing Main() with just a single Test(), but it
+ * may spare you a level of indentation.
+ */
+#define TestMain(name, code) test_main(name, code)
+
+/*
+ * Main() wraps zero or more Tests, which will then contain Convey
+ * scopes. This emits a main function, and can only be used once.
+ * It also cannot be used with TestMain.
+ */
+#define Main(code) test_main_group(name, code)
+
+/*
+ * Test creates a top-level test scope.
+ */
+#define Test(name, code) test_group(name, code)
+
+/*
+ * Convey starts a new test scope. These can be nested. The code is
+ * executed, including new scopes, but each time a new scope is encountered,
+ * the stack is unwound to give the code a fresh start to work with.
+ */
+#define Convey(name, code) test_convey(name, code)
+
+/*
+ * So is to be used like assert(), except that it always is checked,
+ * and records results in the current scope. If the assertion fails,
+ * then no further processing in the same scope (other than possible
+ * reset logic) is performed. Additional tests at higher scopes, or
+ * in sibling scopes, may be executed.
+ */
+#define So(condition) test_so(condition)
+
+/*
+ * Skip ceases further processing the current scope (Convey). The
+ * reason is a string that will be emitted to the log.
+ */
+#define Skip(reason) test_skip(reason)
+
+/*
+ * Fail records a test failure, and is much like So, except that
+ * no condition is recorded, and instead you may supply your own
+ * reason.
+ */
+#define Fail(reason) test_fail(reason)
+
+
+/*
+ * SkipSo is a way to skip a check. The fact that it was skipped
+ * will be noted.
+ */
+#define SkipSo(condition) test_skip_so(condition)
+
+/*
+ * SkipConvey is a way to skip an entire Convey scope. The fact
+ * will be noted.
+ */
+#define SkipConvey(name, code) test_skip_convey(name, code)
+
+
+/*
+ * Reset is establishes a block of code to be reset when exiting from
+ * Convey blocks, or even when finishing the current scope. It only
+ * affects the following code, and it is possible to override a prior
+ * Reset block with a new one in the same scope. Unlike with GoConvey,
+ * you must put this *before* other Convey blocks you wish to cover.
+ */
+#define Reset(code) test_reset(code)
+
+/*
+ * Printf is like printf, but it sends its output to the test debug
+ * log, which is emitted only after the test is finished. The system
+ * injects events in the debug log as well, which makes this useful for
+ * debugging flow of execution.
+ *
+ * NB: We avoid variadic macros since some systems don't support them.
+ */
+#define Printf test_debugf
+
+
+#endif /* TEST_CONVEY_H */
diff --git a/tests/list.c b/tests/list.c
index 8fb19fa9..79200931 100644
--- a/tests/list.c
+++ b/tests/list.c
@@ -21,7 +21,7 @@
*/
#include "core/list.c"
-#include "test.h"
+#include "convey.h"
typedef struct {
int pad[2];
@@ -29,76 +29,76 @@ typedef struct {
nni_list_node_t nodeb;
} mystruct;
-test_main("Linked Lists", {
- test_convey("Given a couple lists", {
+TestMain("Linked Lists", {
+ Convey("Given a couple lists", {
nni_list_t alist;
nni_list_t blist;
NNI_LIST_INIT(&alist, mystruct, nodea);
NNI_LIST_INIT(&blist, mystruct, nodeb);
- test_so(alist.ll_offset == 8);
- test_so(blist.ll_offset == (8 + sizeof (nni_list_node_t)));
+ So(alist.ll_offset == 8);
+ So(blist.ll_offset == (8 + sizeof (nni_list_node_t)));
- test_convey("The list starts empty", {
- test_so(nni_list_first(&alist) == NULL);
- test_so(nni_list_last(&blist) == NULL);
+ Convey("The list starts empty", {
+ So(nni_list_first(&alist) == NULL);
+ So(nni_list_last(&blist) == NULL);
});
- test_convey("And we can add an item", {
+ Convey("And we can add an item", {
mystruct item;
nni_list_append(&alist, &item);
- test_convey("It is the first item", {
- test_so(nni_list_first(&alist) == &item);
+ Convey("It is the first item", {
+ So(nni_list_first(&alist) == &item);
});
- test_convey("It is the last item", {
- test_so(nni_list_last(&alist) == &item);
+ Convey("It is the last item", {
+ So(nni_list_last(&alist) == &item);
});
- test_convey("It is the only item", {
- test_so(nni_list_next(&alist, &item) == NULL);
- test_so(nni_list_prev(&alist, &item) == NULL);
+ Convey("It is the only item", {
+ So(nni_list_next(&alist, &item) == NULL);
+ So(nni_list_prev(&alist, &item) == NULL);
});
- test_convey("It isn't on the other list", {
- test_so(nni_list_first(&blist) == NULL);
- test_so(nni_list_last(&blist) == NULL);
+ Convey("It isn't on the other list", {
+ So(nni_list_first(&blist) == NULL);
+ So(nni_list_last(&blist) == NULL);
});
- test_convey("We can remove it", {
+ Convey("We can remove it", {
nni_list_remove(&alist, &item);
- test_so(nni_list_first(&alist) == NULL);
- test_so(nni_list_last(&alist) == NULL);
+ So(nni_list_first(&alist) == NULL);
+ So(nni_list_last(&alist) == NULL);
});
});
- test_convey("We can add two items", {
+ Convey("We can add two items", {
mystruct item1;
mystruct item2;
nni_list_append(&alist, &item1);
nni_list_append(&alist, &item2);
- test_so(nni_list_first(&alist) == &item1);
- test_so(nni_list_last(&alist) == &item2);
- test_so(nni_list_next(&alist, &item1) == &item2);
- test_so(nni_list_prev(&alist, &item2) == &item1);
+ So(nni_list_first(&alist) == &item1);
+ So(nni_list_last(&alist) == &item2);
+ So(nni_list_next(&alist, &item1) == &item2);
+ So(nni_list_prev(&alist, &item2) == &item1);
- test_so(nni_list_next(&alist, &item2) == NULL);
- test_so(nni_list_prev(&alist, &item1) == NULL);
+ So(nni_list_next(&alist, &item2) == NULL);
+ So(nni_list_prev(&alist, &item1) == NULL);
- test_convey("Removing the first works", {
+ Convey("Removing the first works", {
nni_list_remove(&alist, &item1);
- test_so(nni_list_first(&alist) == &item2);
- test_so(nni_list_last(&alist) == &item2);
- test_so(nni_list_next(&alist, &item2) == NULL);
- test_so(nni_list_prev(&alist, &item2) == NULL);
+ So(nni_list_first(&alist) == &item2);
+ So(nni_list_last(&alist) == &item2);
+ So(nni_list_next(&alist, &item2) == NULL);
+ So(nni_list_prev(&alist, &item2) == NULL);
});
- test_convey("Removing the second works", {
+ Convey("Removing the second works", {
nni_list_remove(&alist, &item2);
- test_so(nni_list_first(&alist) == &item1);
- test_so(nni_list_last(&alist) == &item1);
- test_so(nni_list_next(&alist, &item1) == NULL);
- test_so(nni_list_prev(&alist, &item1) == NULL);
+ So(nni_list_first(&alist) == &item1);
+ So(nni_list_last(&alist) == &item1);
+ So(nni_list_next(&alist, &item1) == NULL);
+ So(nni_list_prev(&alist, &item1) == NULL);
});
});
});