]> git.llucax.com Git - software/mutest.git/commitdiff
Initial import
authorLeandro Lucarella <llucax@gmail.com>
Sat, 6 Dec 2008 16:45:14 +0000 (14:45 -0200)
committerLeandro Lucarella <llucarella@integratech.com.ar>
Fri, 12 Dec 2008 12:54:09 +0000 (10:54 -0200)
12 files changed:
LICENSE [new file with mode: 0644]
mkmutest [new file with mode: 0755]
mutest.h [new file with mode: 0644]
sample/.gitignore [new file with mode: 0644]
sample/Makefile [new file with mode: 0644]
sample/README [new file with mode: 0644]
sample/factorial.c [new file with mode: 0644]
sample/factorial.h [new file with mode: 0644]
sample/factorial_test.c [new file with mode: 0644]
sample/sum.c [new file with mode: 0644]
sample/sum.h [new file with mode: 0644]
sample/sum_test.c [new file with mode: 0644]

diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..c802e1e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+I don't like licenses, because I don't like having to worry about all this
+legal stuff just for a simple piece of software I don't really mind anyone
+using. But I also believe that it's important that people share and give back;
+so I'm placing this work under the following license.
+
+
+BOLA - Buena Onda License Agreement (v1.0)
+------------------------------------------
+
+This work is provided 'as-is', without any express or implied warranty. In no
+event will the authors be held liable for any damages arising from the use of
+this work.
+
+To all effects and purposes, this work is to be considered Public Domain.
+
+
+However, if you want to be "Buena onda", you should:
+
+1. Not take credit for it, and give proper recognition to the authors.
+2. Share your modifications, so everybody benefits from them.
+4. Do something nice for the authors.
+5. Help someone who needs it: sign up for some volunteer work or help your
+   neighbour paint the house.
+6. Don't waste. Anything, but specially energy that comes from natural
+   non-renewable resources. Extra points if you discover or invent something
+   to replace them.
+7. Be tolerant. Everything that's good in nature comes from cooperation.
+
+The order is important, and the further you go the more "Buena onda" you are.
+Make the world a better place: be "Buena onda".
diff --git a/mkmutest b/mkmutest
new file mode 100755 (executable)
index 0000000..82d71d1
--- /dev/null
+++ b/mkmutest
@@ -0,0 +1,120 @@
+#!/bin/sh
+
+# This file is part of mutest, a micro testing framework for C.
+#
+# mutest is under the BOLA license, please see the LICENSE file or visit
+# http://blitiri.com.ar/p/bola/
+#
+# This is a simple script to generate a C file that runs all the test cases
+# present in .o files passed as arguments.
+#
+# Please, read the README file for more details.
+
+TESTER='
+#include <stdio.h> /* printf(), fprintf() */
+
+/* macro for running a single test case */
+#define run_case(name) \
+       do { \
+               if (mutest_verbose > 2) \
+                       printf("\\t- executing test case \"" #name "\"\\n"); \
+               void name(); \
+               mutest_case_name = #name; \
+               name(); \
+               if (mutest_case_failed) { \
+                       ++mutest_failed_cases; \
+                       mutest_suite_failed = 1; \
+               } else ++mutest_passed_cases; \
+               mutest_case_failed = 0; \
+       } while (0)
+
+/* globals for managing test suites */
+static const char* mutest_suite_name;
+static int mutest_failed_suites;
+static int mutest_passed_suites;
+static int mutest_suite_failed;
+
+/* globals for managing test cases */
+static const char* mutest_case_name;
+static int mutest_failed_cases;
+static int mutest_passed_cases;
+int mutest_case_failed;
+
+/* globals for managing checks */
+int mutest_failed_checks;
+int mutest_passed_checks;
+
+/*
+ * verbosity level (each level shows all the previous levels too):
+ *   0 shows only errors
+ *   1 shows a summary
+ *   2 shows test suites progress
+ *   3 shows test cases progress
+ */
+int mutest_verbose;
+
+static void run_suites();
+
+int main(int argc, char* argv[]) {
+
+       /*
+        * arguments checking, both -v -v and -vv are accepted for setting
+        * verbosity to 2.
+        */
+       while (*++argv)
+               if (strncmp(*argv, "-v", 2) == 0) {
+                       ++mutest_verbose;
+                       char* c = (*argv) + 1;
+                       while (*++c)
+                               if (*c == '"'v'"')
+                                       ++mutest_verbose;
+                               else
+                                       break;
+               }
+
+       run_suites();
+
+       if (mutest_verbose) {
+               printf("\\n");
+               printf("Tests done:\\n");
+               printf("\\t%d test suite(s) passed, %d failed.\\n",
+                               mutest_passed_suites,
+                               mutest_failed_suites);
+               printf("\\t%d test case(s) passed, %d failed.\\n",
+                               mutest_passed_cases,
+                               mutest_failed_cases);
+               printf("\\t%d check(s) passed, %d failed.\\n",
+                               mutest_passed_checks, mutest_failed_checks);
+       }
+
+       return mutest_failed_checks ? 1 : 0;
+}
+
+'
+
+# the trick here is getting all the test cases present in an object file using
+# nm. All the tests must take and return void, start with "mutest_" and, of
+# course, should not be static, which leads to a small limitation: all test
+# cases must have unique names, even across test suites.
+echo "$TESTER"
+echo "static void run_suites() {"
+echo
+for file in "$@"
+do
+       suite="`basename $file .o`"
+       echo "\tmutest_suite_name = \"$suite\";"
+       echo "\tif (mutest_verbose > 1)"
+       echo "\t\tprintf(\"\\\\nRunning suite \\\"$suite\\\"\\\\n\");"
+       for symbol in `nm -p "$file" \
+                       | egrep '^[[:xdigit:]]{8} T mu_test_\w+$' \
+                       | cut -c12-`
+       do
+               echo "\trun_case($symbol);"
+       done
+       echo "\tif (mutest_suite_failed) ++mutest_failed_suites;"
+       echo "\telse                     ++mutest_passed_suites;"
+       echo "\tmutest_suite_failed = 0;"
+       echo
+done
+echo "}"
+
diff --git a/mutest.h b/mutest.h
new file mode 100644 (file)
index 0000000..e0467e8
--- /dev/null
+++ b/mutest.h
@@ -0,0 +1,40 @@
+
+#include <stdio.h> // fprintf
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int mutest_failed_checks;
+extern int mutest_passed_checks;
+extern int mutest_case_failed;
+
+#define mu_check(exp) \
+       do { \
+               if (exp) ++mutest_passed_checks; \
+               else { \
+                       ++mutest_failed_checks; \
+                       mutest_case_failed = 1; \
+                       fprintf(stderr, "%s:%d: mu_check(%s) failed, " \
+                                       "resuming test case\n", __FILE__, \
+                                       __LINE__, #exp); \
+               } \
+       } while (0)
+
+#define mu_ensure(exp) \
+       do { \
+               if (exp) ++mutest_passed_checks; \
+               else { \
+                       ++mutest_failed_checks; \
+                       mutest_case_failed = 1; \
+                       fprintf(stderr, "%s:%d: mu_ensure(%s) failed, " \
+                                       "aborting test case\n", __FILE__, \
+                                       __LINE__, #exp); \
+                       return; \
+               } \
+       } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/sample/.gitignore b/sample/.gitignore
new file mode 100644 (file)
index 0000000..9d1f6d3
--- /dev/null
@@ -0,0 +1,2 @@
+*.o
+tester
diff --git a/sample/Makefile b/sample/Makefile
new file mode 100644 (file)
index 0000000..df8b16c
--- /dev/null
@@ -0,0 +1,26 @@
+
+# Show the tests summary
+V=-v
+
+TARGET=tester
+
+OBJS = factorial.o sum.o
+TESTS = factorial_test.o sum_test.o
+TESTER = tester.o
+ALL = $(TESTER) $(OBJS) $(TESTS)
+
+all: $(TARGET)
+
+$(TARGET): $(ALL)
+
+$(TESTER): $(OBJS) $(TESTS)
+       ../mkmutest $(TESTS) | gcc -xc -o $(TESTER) -c -
+
+test: $(TARGET)
+       ./$(TARGET) $(V)
+
+clean:
+       $(RM) $(TARGET) $(ALL)
+
+.PHONY: all test clean
+
diff --git a/sample/README b/sample/README
new file mode 100644 (file)
index 0000000..2d5c710
--- /dev/null
@@ -0,0 +1,8 @@
+
+Just take a look to all the files and find out. To try it out, you can type:
+make test
+
+If you want extra verbosity, try:
+make test V=-vvv
+
+
diff --git a/sample/factorial.c b/sample/factorial.c
new file mode 100644 (file)
index 0000000..c178fa0
--- /dev/null
@@ -0,0 +1,7 @@
+
+unsigned factorial(unsigned x) {
+       if (x <= 1)
+               return 1;
+       return x * factorial(x-1);
+}
+
diff --git a/sample/factorial.h b/sample/factorial.h
new file mode 100644 (file)
index 0000000..a2d71d2
--- /dev/null
@@ -0,0 +1,3 @@
+
+int factorial(int);
+
diff --git a/sample/factorial_test.c b/sample/factorial_test.c
new file mode 100644 (file)
index 0000000..10209e0
--- /dev/null
@@ -0,0 +1,35 @@
+
+#include "../mutest.h"
+#include "factorial.h"
+
+void mu_test_factorial_zero() {
+       unsigned x = factorial(0);
+       mu_check(x == 1);
+}
+
+void mu_test_factorial_one() {
+       unsigned x = factorial(1);
+       /* this test is wrong on purpose, to see how it fails */
+       mu_check(x == 2);
+}
+
+void mu_test_factorial_positive() {
+       unsigned x = factorial(2);
+       /* this test is wrong on purpose, to see how it fails */
+       mu_check(x == 3);
+
+       x = factorial(3);
+       /* we don't want to continue if this fails, because the next result
+        * depends on this one. This one will succeed. */
+       mu_ensure(x == 6);
+
+       x = factorial(x);
+       mu_check(x == 720);
+
+       x = factorial(4);
+       mu_ensure(x == 6); /* same as before, but this one will fail. */
+
+       x = factorial(x-15); /* and this will never be executed */
+       mu_check(x == 362881); /* but if excecuted, will fail */
+}
+
diff --git a/sample/sum.c b/sample/sum.c
new file mode 100644 (file)
index 0000000..4d45974
--- /dev/null
@@ -0,0 +1,5 @@
+
+int sum(int x, int y) {
+       return x + y;
+}
+
diff --git a/sample/sum.h b/sample/sum.h
new file mode 100644 (file)
index 0000000..4f90d44
--- /dev/null
@@ -0,0 +1,3 @@
+
+int sum(int, int);
+
diff --git a/sample/sum_test.c b/sample/sum_test.c
new file mode 100644 (file)
index 0000000..7fea630
--- /dev/null
@@ -0,0 +1,14 @@
+
+/* see factorial_test.c for more complete examples, this file is mostly to show
+ * how to have multiple test suites, and a test suite that succeed. */
+
+#include "../mutest.h"
+#include "sum.h"
+
+void mu_test_sum() {
+       mu_check(sum(4, 5) == 9);
+       mu_check(sum(-4, -5) == -9);
+       mu_check(sum(0, 0) == 0);
+       mu_check(sum(1, -1) == 0);
+}
+