[sheepdog] [PATCH v3 2/4] tests/unit: introduce mock
Kai Zhang
kyle at zelin.io
Fri Jul 12 08:41:36 CEST 2013
Mock is useful when we do unit test.
This patch introduce some useful macro to simply testing.
The two most useful macro are MOCK_METHOD and MOCK_VOID_METHOD.
MOCK_VOID_METHOD is used to mock method how has no return value.
For example:
void foo(int a, long b)
{
return;
}
We define the mock method as:
MOCK_VOID_METHOD(foo, int a, long b)
MOCK_METHOD is used to mock method how has return value.
User have to specified the return value's type and the default return value.
For example:
bool foo(int a, long b)
{
return true;
}
We define the mock method as:
MOCK_METHCO(foo, bool, true, int a, long b)
Use macro to define mock method has many benifits:
- we can record each call of the method and its arguments
- we can control the return value, based on input arguments
However, current implementation is quite initial.
We just record how many times the method is called.
Another useful macro is method_nr_call(method) which returns how many times the
method is called.
Signed-off-by: Kai Zhang <kyle at zelin.io>
---
configure.ac | 1 +
tests/unit/Makefile.am | 2 +-
tests/unit/mock/Makefile.am | 7 +++++
tests/unit/mock/mock.c | 51 ++++++++++++++++++++++++++++++++++++
tests/unit/mock/mock.h | 60 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 120 insertions(+), 1 deletion(-)
create mode 100644 tests/unit/mock/Makefile.am
create mode 100644 tests/unit/mock/mock.c
create mode 100644 tests/unit/mock/mock.h
diff --git a/configure.ac b/configure.ac
index b609fac..84ce448 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,6 +136,7 @@ AC_CONFIG_FILES([Makefile
man/Makefile
shepherd/Makefile
tests/unit/Makefile
+ tests/unit/mock/Makefile
tests/unit/collie/Makefile
tests/unit/sheep/Makefile
tools/Makefile])
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index eb0a50e..3e6255a 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -1,3 +1,3 @@
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = collie sheep
+SUBDIRS = mock collie sheep
diff --git a/tests/unit/mock/Makefile.am b/tests/unit/mock/Makefile.am
new file mode 100644
index 0000000..b7c0c32
--- /dev/null
+++ b/tests/unit/mock/Makefile.am
@@ -0,0 +1,7 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
+
+noinst_LIBRARIES = libmock.a
+
+libmock_a_SOURCES = mock.c
diff --git a/tests/unit/mock/mock.c b/tests/unit/mock/mock.c
new file mode 100644
index 0000000..cd321c2
--- /dev/null
+++ b/tests/unit/mock/mock.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013 Zelin.io
+ *
+ * Kai Zhang <kyle at zelin.io>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "list.h"
+#include "mock.h"
+
+LIST_HEAD(mock_methods);
+
+static struct mock_method *find_method(const char *name)
+{
+ struct mock_method *method;
+ int len;
+ list_for_each_entry(method, &mock_methods, list) {
+ len = strlen(method->name);
+ if (strncmp(method->name, name, len) == 0)
+ return method;
+ }
+ return NULL;
+}
+
+int __method_nr_call(const char *name)
+{
+ struct mock_method *method = find_method(name);
+ if (method)
+ return method->nr_call;
+ else {
+ fprintf(stderr, "%s is not a mock method", name);
+ exit(1);
+ }
+}
+
+void __method_reset_all(void)
+{
+ struct mock_method *method;
+ list_for_each_entry(method, &mock_methods, list)
+ method->nr_call = 0;
+}
diff --git a/tests/unit/mock/mock.h b/tests/unit/mock/mock.h
new file mode 100644
index 0000000..0bb1bee
--- /dev/null
+++ b/tests/unit/mock/mock.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 Zelin.io
+ *
+ * Kai Zhang <kyle at zelin.io>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MOCK_H__
+#define __MOCK_H__
+
+#include "list.h"
+
+struct mock_method {
+ const char *name;
+ int nr_call;
+ struct list_head list;
+};
+
+extern struct list_head mock_methods;
+#define method_register(m) \
+ static void __attribute__((constructor)) regist_##m(void) \
+ { \
+ list_add(&m.list, &mock_methods); \
+ }
+
+#define MOCK_VOID_METHOD(m, ...) \
+ static struct mock_method _##m = { \
+ .name = #m, \
+ }; \
+ void m(__VA_ARGS__) \
+ { \
+ _##m.nr_call++; \
+ return; \
+ } \
+ method_register(_##m)
+
+#define MOCK_METHOD(m, rt, rv, ...) \
+ static struct mock_method _##m = { \
+ .name = #m, \
+ }; \
+ rt m(__VA_ARGS__) \
+ { \
+ _##m.nr_call++; \
+ return rv; \
+ } \
+ method_register(_##m)
+
+int __method_nr_call(const char *name);
+void __method_reset_all(void);
+
+#define method_nr_call(m) __method_nr_call(#m)
+#define method_reset_all() __method_reset_all()
+
+#endif
--
1.7.9.5
More information about the sheepdog
mailing list