cmocka: Allow to pass initial data to test cases

Sometimes multiple test cases share the same test function, running it
on different data. To pass this data to test functions we must define
setup function for each data set. It's not very convienient when there
are many states to test.

This commit introduce more elegant way to pass data to tests. The
initial_state field of CMUnitTest structure can be defined by user.
It will be either passed to setup function, which makes any preparation
needed, or it will be passed directly to test function when setup func is
NULL.

Signed-off-by: Pawel Szewczyk <p.szewczyk@samsung.com>
diff --git a/include/cmocka.h b/include/cmocka.h
index 797fbe2..e4aa5b2 100644
--- a/include/cmocka.h
+++ b/include/cmocka.h
@@ -1489,19 +1489,35 @@
 
 
 /** Initializes a CMUnitTest structure. */
-#define cmocka_unit_test(f) { #f, f, NULL, NULL }
+#define cmocka_unit_test(f) { #f, f, NULL, NULL, NULL }
 
 /** Initializes a CMUnitTest structure with a setup function. */
-#define cmocka_unit_test_setup(f, setup) { #f, f, setup, NULL }
+#define cmocka_unit_test_setup(f, setup) { #f, f, setup, NULL, NULL }
 
 /** Initializes a CMUnitTest structure with a teardown function. */
-#define cmocka_unit_test_teardown(f, teardown) { #f, f, NULL, teardown }
+#define cmocka_unit_test_teardown(f, teardown) { #f, f, NULL, teardown, NULL }
 
 /**
  * Initialize an array of CMUnitTest structures with a setup function for a test
  * and a teardown function. Either setup or teardown can be NULL.
  */
-#define cmocka_unit_test_setup_teardown(f, setup, teardown) { #f, f, setup, teardown }
+#define cmocka_unit_test_setup_teardown(f, setup, teardown) { #f, f, setup, teardown, NULL }
+
+/**
+ * Initialize a CMUnitTest structure with given initial state. It will be passed to test
+ * function as an argument later. It can be used when test state does not need special initialization
+ * or was initialized already.
+ * If group state was initialized for this unit test, it won't be overrided by initial state defined here.
+ */
+#define cmocka_unit_test_prestate(f, state) { #f, f, NULL, NULL, state }
+
+/**
+ * Initialize a CMUnitTest structure with given initial state, setup and teardown function. Any of
+ * these values can be NULL. Initial state is passed later to setup function, or directly to test if
+ * none was given.
+ * If group state was initialized for this unit test, it won't be overrided by initial state defined here.
+ */
+#define cmocka_unit_test_prestate_setup_teardown(f, setup, teardown, state) { #f, f, setup, teardown, state }
 
 #define run_tests(tests) _run_tests(tests, sizeof(tests) / sizeof(tests)[0])
 #define run_group_tests(tests) _run_group_tests(tests, sizeof(tests) / sizeof(tests)[0])
@@ -1894,6 +1910,7 @@
     CMUnitTestFunction test_func;
     CMFixtureFunction setup_func;
     CMFixtureFunction teardown_func;
+    void *initial_state;
 };
 
 /* Location within some source code. */
diff --git a/src/cmocka.c b/src/cmocka.c
index 333a739..2fc46f3 100644
--- a/src/cmocka.c
+++ b/src/cmocka.c
@@ -2577,7 +2577,10 @@
 
             if (group_state != NULL) {
                 cm_tests[i].state = group_state;
+            } else if (cm_tests[i].test->initial_state != NULL) {
+                cm_tests[i].state = cm_tests[i].test->initial_state;
             }
+
             rc = cmocka_run_one_tests(cmtest);
             total_executed++;
             total_runtime += cmtest->runtime;
diff --git a/tests/test_fixtures.c b/tests/test_fixtures.c
index 4597626..6d39487 100644
--- a/tests/test_fixtures.c
+++ b/tests/test_fixtures.c
@@ -31,7 +31,42 @@
     assert_non_null(*state);
 }
 
+static int prestate_setup(void **state)
+{
+    int *val = (int *)*state, *a;
+
+    a = malloc(sizeof(int));
+    *a = *val + 1;
+    *state = a;
+
+    return 0;
+}
+
+static int prestate_teardown(void **state)
+{
+	free(*state);
+
+	return 0;
+}
+
+static void prestate_setup_test(void **state)
+{
+    int *a = (int *)*state;
+
+    assert_non_null(a);
+    assert_int_equal(*a, 43);
+}
+
+static void prestate_test(void **state)
+{
+    int *a = (int *)*state;
+
+    assert_non_null(a);
+    assert_int_equal(*a, 42);
+}
+
 int main(void) {
+    int prestate = 42;
     const struct CMUnitTest tests[] = {
         cmocka_unit_test_setup(malloc_setup_test, setup_only),
         cmocka_unit_test_setup(malloc_setup_test, setup_only),
@@ -39,6 +74,8 @@
         cmocka_unit_test_teardown(malloc_teardown_test, teardown_only),
         cmocka_unit_test_teardown(malloc_teardown_test, teardown_only),
         cmocka_unit_test_teardown(malloc_teardown_test, teardown_only),
+        cmocka_unit_test_prestate(prestate_test, &prestate),
+        cmocka_unit_test_prestate_setup_teardown(prestate_setup_test, prestate_setup, prestate_teardown, &prestate),
     };
 
     return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/test_group_fixtures.c b/tests/test_group_fixtures.c
index 09f39b1..64f0ab7 100644
--- a/tests/test_group_fixtures.c
+++ b/tests/test_group_fixtures.c
@@ -39,9 +39,11 @@
 }
 
 int main(void) {
+    int prestate = 1337;
     const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_value_equal),
         cmocka_unit_test(test_value_range),
+	cmocka_unit_test_prestate(test_value_equal, &prestate),
     };
 
     return cmocka_run_group_tests(tests, group_setup, group_teardown);