From ef00063ba350f64bab4fd113d5a226e5308f59df Mon Sep 17 00:00:00 2001 From: jlamothe Date: Wed, 15 Nov 2023 23:46:25 +0000 Subject: [PATCH] built and started to test test_context() --- 9unit.c | 74 ++++++++++++++++++++++ 9unit.h | 7 +++ test/mkfile | 17 ++++- test/test-context.c | 150 ++++++++++++++++++++++++++++++++++++++++++++ test/test-context.h | 24 +++++++ test/tests.c | 2 + 6 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 test/test-context.c create mode 100644 test/test-context.h diff --git a/9unit.c b/9unit.c index d9b2da6..a260c82 100644 --- a/9unit.c +++ b/9unit.c @@ -25,6 +25,19 @@ #include "9unit.h" +// Internal Types + +// data required by the context management functions +typedef struct ContextData ContextData; + +struct ContextData +{ + const char *old_c; // previous context + const char *old_fc; // previous full context + const char *new_c; // new context + char *new_fc; // new full context +}; + // Internal Prototypes static void init_TestState(TestState *); @@ -32,6 +45,9 @@ static void print_log(TestState *); static void clear_log(TestState *); static void reindex(TestState *); static void report(const char *); +static void build_new_context(TestState *, ContextData *); +static void display_context(TestState *); +static void restore_context(TestState *, ContextData *); // Public Functions @@ -111,6 +127,26 @@ append_test_log(TestState *s, const char *msg) s->last_log = entry; } +void +test_context( + TestState *s, + const char *label, + void (*test)(TestState *) +) +{ + if (!(s && test)) return; + if (label) + { + ContextData cd; + cd.new_c = label; + build_new_context(s, &cd); + display_context(s); + (*test)(s); + restore_context(s, &cd); + } + else (*test)(s); +} + // Internal Functions static void @@ -169,4 +205,42 @@ report(const char *str) print("%s", str); } +static void +build_new_context(TestState *s, ContextData *cd) +{ + cd->old_c = s->context; + cd->old_fc = s->full_context; + if (s->full_context) + { + cd->new_fc = malloc(strlen(cd->old_fc) + strlen(cd->new_c) + 3); + sprintf(cd->new_fc, "%s: %s", cd->old_fc, cd->new_c); + } + else + { + cd->new_fc = malloc(strlen(cd->new_c) + 1); + strcpy(cd->new_fc, cd->new_c); + } + s->context = cd->new_c; + s->full_context = cd->new_fc; + s->depth++; +} + +static void +display_context(TestState *s) +{ + for (int i = 1; i < s->depth; i++) + s->report("\t"); + s->report(s->context); + s->report("\n"); +} + +static void +restore_context(TestState *s, ContextData *cd) +{ + s->context = cd->old_c; + s->full_context = cd->old_fc; + s->depth--; + free(cd->new_fc); +} + //jl diff --git a/9unit.h b/9unit.h index 9641f1e..45698be 100644 --- a/9unit.h +++ b/9unit.h @@ -76,4 +76,11 @@ extern void append_test_log( const char * // the message to append ); +// Gives additional context for a test +extern void test_context( + TestState *, // the current state + const char *, // a description of the context + void (*)(TestState *) // the actual test +); + //jl diff --git a/test/mkfile b/test/mkfile index 4d748e6..d90d94f 100644 --- a/test/mkfile +++ b/test/mkfile @@ -17,8 +17,21 @@ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + . + +*/ + +#include +#include + +#include "../9unit.h" +#include "util.h" +#include "test-context.h" + +// Local Types + +typedef struct ContextData ContextData; + +struct ContextData +{ + TestState state; + const char *initial_context; + const char *initial_full_context; + int initial_depth; + const char *new_context; + const char *sub_context; + const char *sub_full_context; + int sub_depth; + const char *expected_sub_full_context; + int expected_sub_depth; +}; + +// Local Prototypes + +static void no_prior_context(TestState *); +static void init_ContextData(ContextData *); +static void run_test_context(ContextData *); +static void get_context(TestState *); +static void check_results(TestState *, ContextData *); +static void check_sub_context(TestState *); +static void clean_up(ContextData *); + +// Public Functions + +void +test_test_context(TestState *s) +{ + test_context(s, "no prior context", no_prior_context); +} + +// Local Functions + +static void +no_prior_context(TestState *s) +{ + // set initial state + ContextData cd; + cd.new_context = "my test"; + cd.initial_context = 0; + cd.initial_full_context = 0; + cd.initial_depth = 0; + init_ContextData(&cd); + + run_test_context(&cd); + cd.expected_sub_full_context = "my test"; + cd.expected_sub_depth = 1; + check_results(s, &cd); + clean_up(&cd); +} + +static void +init_ContextData(ContextData *cd) +{ + mk_sample_state(&cd->state); + cd->state.context = cd->initial_context; + cd->state.full_context = cd->initial_full_context; + cd->state.depth = cd->initial_depth; +} + +static void +run_test_context(ContextData *cd) +{ + void *old_ptr = cd->state.ptr; + cd->state.ptr = cd; + test_context(&cd->state, cd->new_context, get_context); + cd->state.ptr = old_ptr; +} + +static void +get_context(TestState *s) +{ + ContextData *cd = s->ptr; + + // get the context + if (s->context) + { + char *c = malloc(strlen(s->context) + 1); + strcpy(c, s->context); + cd->sub_context = c; + } + else cd->sub_context = 0; + + // get the full context + if (s->full_context) + { + char *fc = malloc(strlen(s->full_context) + 1); + strcpy(fc, s->full_context); + cd->sub_full_context = fc; + } + else cd->sub_full_context = 0; + + // get the depth + cd->sub_depth = s->depth; +} + +static void +check_results(TestState *s, ContextData *cd) +{ + void *old_ptr = s->ptr; + s->ptr = cd; + test_context(s, "sub context", check_sub_context); + s->ptr = old_ptr; +} + +static void +check_sub_context(TestState *s) +{ + ContextData *cd = s->ptr; +} + +static void +clean_up(ContextData *cd) +{ +} + +//jl diff --git a/test/test-context.h b/test/test-context.h new file mode 100644 index 0000000..308bcf4 --- /dev/null +++ b/test/test-context.h @@ -0,0 +1,24 @@ +/* + + 9unit + Copyright (C) Jonathan Lamothe + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program. If not, see + . + +*/ + +extern void test_test_context(TestState *); + +//jl diff --git a/test/tests.c b/test/tests.c index ea02945..626b0f9 100644 --- a/test/tests.c +++ b/test/tests.c @@ -26,6 +26,7 @@ #include "initial-state.h" #include "run-test.h" #include "append-test-log.h" +#include "test-context.h" // Internal Prototypes @@ -55,6 +56,7 @@ tests(TestState *s) test_initial_state(s); test_run_test(s); test_append_test_log(s); + test_context(s, "test_context()", test_test_context); } //jl