From cb3c6bdc0f6a89609b88f2c4d647e18d8bcdd843 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 9 Jun 2020 15:55:22 +0200 Subject: libtest: Add push/pop fixture support 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 -- cgit v1.2.3