[PATCH 07/33] libtest: Add push/pop fixture support

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Jul 21 15:04:24 UTC 2020


Update #3199.
---
 cpukit/include/rtems/test.h                |  11 +++
 cpukit/libtest/t-test.c                    | 110 +++++++++++++++++----
 testsuites/libtests/ttest01/init.c         |   4 +-
 testsuites/libtests/ttest01/test-fixture.c | 105 ++++++++++++++++++--
 4 files changed, 200 insertions(+), 30 deletions(-)

diff --git a/cpukit/include/rtems/test.h b/cpukit/include/rtems/test.h
index 2362e5b804..04f92dd1f4 100644
--- a/cpukit/include/rtems/test.h
+++ b/cpukit/include/rtems/test.h
@@ -66,6 +66,13 @@ typedef struct T_fixture {
 	void *initial_context;
 } T_fixture;
 
+typedef struct T_fixture_node {
+	struct T_fixture_node *next;
+	struct T_fixture_node *previous;
+	const T_fixture *fixture;
+	void *context;
+} T_fixture_node;
+
 #define T_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
 
 /*
@@ -2232,6 +2239,10 @@ void *T_fixture_context(void);
 
 void T_set_fixture_context(void *);
 
+void *T_push_fixture(T_fixture_node *, const T_fixture *);
+
+void T_pop_fixture(void);
+
 #ifdef __rtems__
 #define T_TEST_CASE_FIXTURE(name, fixture)			\
 void T_case_body_##name(void);					\
diff --git a/cpukit/libtest/t-test.c b/cpukit/libtest/t-test.c
index aa04f09139..bf9b68cdf2 100644
--- a/cpukit/libtest/t-test.c
+++ b/cpukit/libtest/t-test.c
@@ -1,7 +1,7 @@
 /*
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright (C) 2018, 2019 embedded brains GmbH
+ * Copyright (C) 2018, 2020 embedded brains GmbH
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,7 +62,8 @@ typedef struct {
 	T_verbosity verbosity;
 	const T_case_context *registered_cases;
 	const T_case_context *current_case;
-	void *fixture_context;
+	T_fixture_node *fixtures;
+	T_fixture_node case_fixture;
 	LIST_HEAD(, T_destructor) destructors;
 	T_time case_begin_time;
 	atomic_uint planned_steps;
@@ -288,7 +289,7 @@ static const char *
 T_scope(T_context *ctx, char *buf)
 {
 	const char *r;
-	const T_case_context *tc;
+	T_fixture_node *node;
 
 #if defined(__rtems__)
 	ISR_Level level;
@@ -327,19 +328,23 @@ T_scope(T_context *ctx, char *buf)
 	r = buf;
 #endif
 
-	tc = ctx->current_case;
-	if (tc != NULL) {
+	node = &ctx->case_fixture;
+
+	do {
 		const T_fixture *fixture;
 
-		fixture = tc->fixture;
+		fixture = node->fixture;
+
 		if (fixture != NULL && fixture->scope != NULL) {
 			size_t n;
 
 			n = strlen(r);
-			(*fixture->scope)(ctx->fixture_context, buf + n,
+			(*fixture->scope)(node->context, buf + n,
 			    T_SCOPE_SIZE - n);
 		}
-	}
+
+		node = node->previous;
+	} while (node != NULL);
 
 	return r;
 }
@@ -421,18 +426,20 @@ T_add_failure(T_context *ctx)
 static void
 T_stop(T_context *ctx)
 {
-	const T_case_context *tc;
+	T_fixture_node *node;
 
-	tc = ctx->current_case;
+	node = ctx->fixtures;
 
-	if (tc != NULL) {
+	while (node != NULL) {
 		const T_fixture *fixture;
 
-		fixture = tc->fixture;
+		fixture = node->fixture;
 
 		if (fixture != NULL && fixture->stop != NULL) {
-			(*fixture->stop)(ctx->fixture_context);
+			(*fixture->stop)(node->context);
 		}
+
+		node = node->next;
 	}
 
 	longjmp(ctx->case_begin_context, 1);
@@ -478,13 +485,13 @@ T_set_verbosity(T_verbosity verbosity)
 void *
 T_fixture_context(void)
 {
-	return T_instance.fixture_context;
+	return T_instance.fixtures->context;
 }
 
 void
 T_set_fixture_context(void *context)
 {
-	T_instance.fixture_context = context;
+	T_instance.fixtures->context = context;
 }
 
 const char *
@@ -730,6 +737,7 @@ T_do_run_initialize(const T_config *config)
 		ctx->buf_mask = 0;
 	}
 
+	ctx->fixtures = &ctx->case_fixture;
 	atomic_store_explicit(&ctx->buf_head, 0, memory_order_relaxed);
 	ctx->buf_tail = 0;
 	ctx->putchar = config->putchar;
@@ -761,6 +769,7 @@ T_do_case_begin(T_context *ctx, const T_case_context *tc)
 	fixture = tc->fixture;
 	ctx->verbosity = config->verbosity;
 	ctx->current_case = tc;
+	ctx->fixtures = &ctx->case_fixture;
 	LIST_INIT(&ctx->destructors);
 	atomic_store_explicit(&ctx->planned_steps, UINT_MAX,
 	    memory_order_relaxed);
@@ -773,10 +782,11 @@ T_do_case_begin(T_context *ctx, const T_case_context *tc)
 	T_actions_forward(config, T_EVENT_CASE_BEGIN, tc->name);
 
 	if (fixture != NULL) {
-		ctx->fixture_context = fixture->initial_context;
+		ctx->case_fixture.fixture = fixture;
+		ctx->case_fixture.context = fixture->initial_context;
 
 		if (fixture->setup != NULL) {
-			(*fixture->setup)(ctx->fixture_context);
+			(*fixture->setup)(ctx->case_fixture.context);
 		}
 	}
 }
@@ -785,7 +795,7 @@ static void
 T_do_case_end(T_context *ctx, const T_case_context *tc)
 {
 	const T_config *config;
-	const T_fixture *fixture;
+	T_fixture_node *node;
 	unsigned int planned_steps;
 	unsigned int steps;
 	unsigned int failures;
@@ -793,10 +803,22 @@ T_do_case_end(T_context *ctx, const T_case_context *tc)
 	T_time_string ts;
 
 	config = ctx->config;
-	fixture = tc->fixture;
+	node = ctx->fixtures;
+	ctx->fixtures = NULL;
 
-	if (fixture != NULL && fixture->teardown != NULL) {
-		(*fixture->teardown)(ctx->fixture_context);
+	while (node != NULL) {
+		const T_fixture *fixture;
+		T_fixture_node *dead;
+
+		fixture = node->fixture;
+
+		if (fixture != NULL && fixture->teardown != NULL) {
+			(*fixture->teardown)(node->context);
+		}
+
+		dead = node;
+		node = node->next;
+		memset(dead, 0, sizeof(*dead));
 	}
 
 	T_call_destructors(ctx);
@@ -1027,3 +1049,49 @@ T_now(void)
 	config = ctx->config;
 	return (*config->now)();
 }
+
+void *
+T_push_fixture(T_fixture_node *node, const T_fixture *fixture)
+{
+	T_context *ctx;
+	T_fixture_node *old;
+	void *context;
+
+	ctx = &T_instance;
+	old = ctx->fixtures;
+	old->previous = node;
+	node->next = old;
+	node->previous = NULL;
+	node->fixture = fixture;
+	context = fixture->initial_context;
+	node->context = context;
+	ctx->fixtures = node;
+
+	if (fixture != NULL && fixture->setup != NULL) {
+		(*fixture->setup)(context);
+	}
+
+	return context;
+}
+
+void
+T_pop_fixture(void)
+{
+	T_context *ctx;
+	T_fixture_node *node;
+	const T_fixture *fixture;
+	T_fixture_node *next;
+
+	ctx = &T_instance;
+	node = ctx->fixtures;
+	next = node->next;
+	next->previous = NULL;
+	ctx->fixtures = next;
+	fixture = node->fixture;
+
+	if (fixture != NULL && fixture->teardown != NULL) {
+		(*fixture->teardown)(node->context);
+	}
+
+	memset(node, 0, sizeof(*node));
+}
diff --git a/testsuites/libtests/ttest01/init.c b/testsuites/libtests/ttest01/init.c
index 1763a21616..a5df3932f7 100644
--- a/testsuites/libtests/ttest01/init.c
+++ b/testsuites/libtests/ttest01/init.c
@@ -182,8 +182,8 @@ run_initialize(void)
 	T_set_putchar(censor_putchar, ctx, &ctx->putchar, &ctx->putchar_arg);
 }
 
-static const char expected_final[] = "Z:ttest01:C:342:N:1316:F:791:D:0.687999\n"
-"Y:ReportHash:SHA256:efd7b69ac3ec0cac31fa147008bba87a077e6d53c0cfb8a836a4de2ae90ecc27\n";
+static const char expected_final[] = "Z:ttest01:C:342:N:1329:F:791:D:0.687999\n"
+"Y:ReportHash:SHA256:e5c3847558c805663117be13ef27fd89579f595148b8515c42a38bd1b9dd79c2\n";
 
 static void
 run_finalize(void)
diff --git a/testsuites/libtests/ttest01/test-fixture.c b/testsuites/libtests/ttest01/test-fixture.c
index c3515c320a..545fbf19dc 100644
--- a/testsuites/libtests/ttest01/test-fixture.c
+++ b/testsuites/libtests/ttest01/test-fixture.c
@@ -58,9 +58,77 @@ static const T_fixture fixture = {
 	.initial_context = &initial_value
 };
 
+static int initial_value_2 = 7;
+
+static int counter_2;
+
+static void
+setup_2(void *ctx)
+{
+	int *c;
+
+	T_log(T_QUIET, "setup 2 begin");
+	T_eq_ptr(ctx, &initial_value_2);
+	T_eq_ptr(ctx, T_fixture_context());
+	c = ctx;
+	counter_2 = *c;
+	T_set_fixture_context(&counter_2);
+	T_eq_ptr(&counter_2, T_fixture_context());
+	T_log(T_QUIET, "setup 2 end");
+}
+
+static void
+stop_2(void *ctx)
+{
+	int *c;
+
+	T_log(T_QUIET, "stop 2 begin");
+	T_eq_ptr(ctx, &counter_2);
+	c = ctx;
+	++(*c);
+	T_log(T_QUIET, "stop 2 end");
+}
+
+static void
+teardown_2(void *ctx)
+{
+	int *c;
+
+	T_log(T_QUIET, "teardown 2 begin");
+	T_eq_ptr(ctx, &counter_2);
+	c = ctx;
+	T_eq_int(*c, 8);
+	T_log(T_QUIET, "teardown 2 end");
+}
+
+static void
+scope_2(void *ctx, char *buf, size_t n)
+{
+
+	strlcpy(buf, "/AndMore", n);
+}
+
+static const T_fixture fixture_2 = {
+	.setup = setup_2,
+	.stop = stop_2,
+	.teardown = teardown_2,
+	.scope = scope_2,
+	.initial_context = &initial_value_2
+};
+
+static T_fixture_node node;
+
 T_TEST_CASE_FIXTURE(fixture, &fixture)
 {
+	void *ctx;
+
 	T_assert_true(true, "all right");
+	ctx = T_push_fixture(&node, &fixture_2);
+	T_eq_ptr(ctx, &initial_value_2);
+	++counter_2;
+	T_pop_fixture();
+	ctx = T_push_fixture(&node, &fixture_2);
+	T_eq_ptr(ctx, &initial_value_2);
 	T_assert_true(false, "test fails and we stop the test case");
 	T_log(T_QUIET, "not reached");
 }
@@ -74,16 +142,39 @@ T_TEST_OUTPUT(fixture,
 "P:1:0:UI1/More:test-fixture.c:14\n"
 "P:2:0:UI1/More:test-fixture.c:18\n"
 "L:setup end\n"
-"P:3:0:UI1/More:test-fixture.c:63\n"
-"F:4:0:UI1/More:test-fixture.c:64:test fails and we stop the test case\n"
+"P:3:0:UI1/More:test-fixture.c:125\n"
+"L:setup 2 begin\n"
+"P:4:0:UI1/More/AndMore:test-fixture.c:71\n"
+"P:5:0:UI1/More/AndMore:test-fixture.c:72\n"
+"P:6:0:UI1/More/AndMore:test-fixture.c:76\n"
+"L:setup 2 end\n"
+"P:7:0:UI1/More/AndMore:test-fixture.c:127\n"
+"L:teardown 2 begin\n"
+"P:8:0:UI1/More:test-fixture.c:98\n"
+"P:9:0:UI1/More:test-fixture.c:100\n"
+"L:teardown 2 end\n"
+"L:setup 2 begin\n"
+"P:10:0:UI1/More/AndMore:test-fixture.c:71\n"
+"P:11:0:UI1/More/AndMore:test-fixture.c:72\n"
+"P:12:0:UI1/More/AndMore:test-fixture.c:76\n"
+"L:setup 2 end\n"
+"P:13:0:UI1/More/AndMore:test-fixture.c:131\n"
+"F:14:0:UI1/More/AndMore:test-fixture.c:132:test fails and we stop the test case\n"
+"L:stop 2 begin\n"
+"P:15:0:UI1/More/AndMore:test-fixture.c:86\n"
+"L:stop 2 end\n"
 "L:stop begin\n"
-"P:5:0:UI1/More:test-fixture.c:28\n"
+"P:16:0:UI1/More/AndMore:test-fixture.c:28\n"
 "L:stop end\n"
+"L:teardown 2 begin\n"
+"P:17:0:UI1/More/AndMore:test-fixture.c:98\n"
+"P:18:0:UI1/More/AndMore:test-fixture.c:100\n"
+"L:teardown 2 end\n"
 "L:teardown begin\n"
-"P:6:0:UI1/More:test-fixture.c:40\n"
-"P:7:0:UI1/More:test-fixture.c:42\n"
+"P:19:0:UI1/More:test-fixture.c:40\n"
+"P:20:0:UI1/More:test-fixture.c:42\n"
 "L:teardown end\n"
-"E:fixture:N:8:F:1:D:0.001000\n");
+"E:fixture:N:21:F:1:D:0.001000\n");
 
 /*
  * The license is at the end of the file to be able to use the test code and
@@ -94,7 +185,7 @@ T_TEST_OUTPUT(fixture,
 /*
  * SPDX-License-Identifier: BSD-2-Clause OR CC-BY-SA-4.0
  *
- * Copyright (C) 2018, 2019 embedded brains GmbH
+ * Copyright (C) 2018, 2020 embedded brains GmbH
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
-- 
2.26.2



More information about the devel mailing list