Add unit test foundations for blktap and cbtutil

From: Mark Syms <mark.syms@citrix.com>

Signed-off-by: Mark Syms <mark.syms@citrix.com>
Reviewed-by: Chandrika Srinivasan <chandrika.srinivasan@citrix.com>

diff --git a/Makefile.am b/Makefile.am
index 3ad331f..ea40691 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,7 @@ SUBDIRS += drivers
 SUBDIRS += include
 SUBDIRS += tapback
 SUBDIRS += cbt
+SUBDIRS += mockatests
 
 if ENABLE_PART
 MAYBE_part = part
diff --git a/cbt/Makefile.am b/cbt/Makefile.am
index 8434046..bbc4d50 100644
--- a/cbt/Makefile.am
+++ b/cbt/Makefile.am
@@ -7,7 +7,7 @@ sbin_PROGRAMS = cbt-util
 
 noinst_LTLIBRARIES = libcbtutil.la
 
-libcbtutil_la_SOURCES = cbt-util.c cbt-utl-priv.h
+libcbtutil_la_SOURCES = cbt-util.c
 
 cbt_util_SOURCES  = main.c
 cbt_util_LDADD  = -lrt -luuid libcbtutil.la
diff --git a/cbt/cbt-util.c b/cbt/cbt-util.c
index f480165..003e6ae 100644
--- a/cbt/cbt-util.c
+++ b/cbt/cbt-util.c
@@ -120,7 +120,7 @@ cbt_util_get(int argc, char **argv)
 		err = -errno;
 		goto error;
 	}
-	
+
 	ret = fread(log_meta, sizeof(struct cbt_log_metadata), 1, f);
 
 	if (!ret) {
diff --git a/configure.ac b/configure.ac
index b98ad7c..5b6fe30 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,5 +82,7 @@ control/Makefile
 drivers/Makefile
 include/Makefile
 tapback/Makefile
+mockatests/Makefile
+mockatests/cbt/Makefile
 ])
 AC_OUTPUT
diff --git a/mockatests/Makefile.am b/mockatests/Makefile.am
new file mode 100644
index 0000000..b5c941c
--- /dev/null
+++ b/mockatests/Makefile.am
@@ -0,0 +1,3 @@
+# ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS  = cbt
diff --git a/mockatests/cbt/Makefile.am b/mockatests/cbt/Makefile.am
new file mode 100644
index 0000000..60cff40
--- /dev/null
+++ b/mockatests/cbt/Makefile.am
@@ -0,0 +1,14 @@
+AM_CFLAGS  = -Wall
+AM_CFLAGS += -Werror
+# Arc coverage and wrap don't seem to be compatible
+#AM_CFLAGS += -fprofile-arcs
+#AM_CFLAGS += -ftest-coverage
+
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/cbt
+
+check_PROGRAMS = test-cbt-util
+TESTS = test-cbt-util
+
+test_cbt_util_SOURCES = test-cbt-util.c
+test_cbt_util_LDFLAGS = $(top_srcdir)/cbt/libcbtutil.la -lcmocka -luuid
+test_cbt_util_LDFLAGS += -Wl,--wrap=fopen,--wrap=fclose,--wrap=printf
diff --git a/mockatests/cbt/test-cbt-util.c b/mockatests/cbt/test-cbt-util.c
new file mode 100644
index 0000000..87debca
--- /dev/null
+++ b/mockatests/cbt/test-cbt-util.c
@@ -0,0 +1,134 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <uuid/uuid.h>
+
+#include <cbt-util-priv.h>
+
+extern int cbt_util_create(int , char **);
+extern int cbt_util_set(int , char **);
+extern int cbt_util_get(int , char **);
+
+struct cbt_log_metadata {
+	uuid_t parent;
+	uuid_t child;
+	int    consistent;
+};
+
+FILE *
+__wrap_fopen(void)
+{
+	return (FILE*) mock();
+}
+
+void __real_fclose(FILE *fp);
+
+void
+__wrap_fclose(FILE *fp)
+{
+	check_expected_ptr(fp);
+	__real_fclose(fp);
+}
+
+int
+__wrap_printf(const char *format, ...)
+{
+	va_list ap;
+	int bufsize = mock();
+	char* buf = mock();
+
+	va_start(ap, format);
+
+	int len = vsnprintf(buf, bufsize, format, ap);
+
+	assert_in_range(len, 0, bufsize);
+
+	return len;
+}
+
+
+void
+test_get_command_create(void **state)
+{
+	struct command *cmd;
+
+	char* requested_command = { "create" };
+
+	cmd = get_command(requested_command);
+
+	assert_string_equal(cmd->name, "create");
+	assert_ptr_equal(cmd->func, cbt_util_create);
+}
+
+void
+test_get_command_set(void **state)
+{
+	struct command *cmd;
+
+	char* requested_command = { "set" };
+
+	cmd = get_command(requested_command);
+
+	assert_string_equal(cmd->name, "set");
+	assert_ptr_equal(cmd->func, cbt_util_set);
+}
+
+void
+test_get_command_get(void **state)
+{
+	struct command *cmd;
+
+	char* requested_command = { "get" };
+
+	cmd = get_command(requested_command);
+
+	assert_string_equal(cmd->name, "get");
+	assert_ptr_equal(cmd->func, cbt_util_get);
+}
+
+
+void test_cbt_util_get_flag(void **state)
+{
+	int result;
+	char* args[] = { "cbt-util", "-n", "test_disk.log", "-f" };
+	void *log_meta;
+	char output[1024];
+
+	log_meta = malloc(sizeof(struct cbt_log_metadata));
+
+	((struct cbt_log_metadata*)log_meta)->consistent = 1;
+	FILE *test_log = fmemopen((void*)log_meta, sizeof(struct cbt_log_metadata), "r");
+
+	will_return(__wrap_fopen, test_log);
+	expect_value(__wrap_fclose, fp, test_log);
+
+	will_return(__wrap_printf, 1024);
+	will_return(__wrap_printf, output);
+
+	result = cbt_util_get(4, args);
+
+	assert_int_equal(result, 0);
+	assert_string_equal(output, "1\n");
+}
+
+const struct CMUnitTest cbt_command_tests[] = {
+	cmocka_unit_test(test_get_command_create),
+	cmocka_unit_test(test_get_command_set),
+	cmocka_unit_test(test_get_command_get)
+};
+
+const struct CMUnitTest cbt_get_tests[] = {
+	cmocka_unit_test(test_cbt_util_get_flag)
+};
+
+int main(void)
+{
+	return
+		cmocka_run_group_tests_name("Command tests", cbt_command_tests, NULL, NULL) +
+		cmocka_run_group_tests_name("Get tests", cbt_get_tests, NULL, NULL);
+}
