unity: don't use stdio in runner, fix code style

This commit is contained in:
Ivan Grokhotkov 2018-10-25 15:44:50 +08:00
parent 6091021e83
commit a98674d78b
3 changed files with 150 additions and 150 deletions

View file

@ -40,19 +40,11 @@ uint32_t unity_exec_time_get_ms(void);
#define UNITY_EXEC_TIME_STOP() unity_exec_time_stop() #define UNITY_EXEC_TIME_STOP() unity_exec_time_stop()
#define UNITY_EXEC_TIME_MS() unity_exec_time_get_ms() #define UNITY_EXEC_TIME_MS() unity_exec_time_get_ms()
#ifdef CONFIG_UNITY_ENABLE_TEST_RUNNER #ifdef CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER
#include "unity_test_case.h" #include "unity_test_runner.h"
void unity_run_menu() __attribute__((noreturn)); #endif //CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER
void unity_run_tests_with_filter(const char* filter);
void unity_run_all_tests();
void unity_run_single_test_by_name(const char* name);
#endif //CONFIG_UNITY_ENABLE_TEST_RUNNER
// shorthand to check esp_err_t return code // shorthand to check esp_err_t return code
#define TEST_ESP_OK(rc) TEST_ASSERT_EQUAL_HEX32(ESP_OK, rc) #define TEST_ESP_OK(rc) TEST_ASSERT_EQUAL_HEX32(ESP_OK, rc)

View file

@ -14,6 +14,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
// This file gets included from unity.h via unity_internals.h via unity_config.h // This file gets included from unity.h via unity_internals.h via unity_config.h
// It is inside #ifdef __cplusplus / extern "C" block, so we can // It is inside #ifdef __cplusplus / extern "C" block, so we can
@ -54,7 +55,7 @@
typedef void (* test_func)(void); typedef void (* test_func)(void);
struct test_desc_t typedef struct test_desc_t
{ {
const char* name; const char* name;
const char* desc; const char* desc;
@ -64,9 +65,9 @@ struct test_desc_t
uint8_t test_fn_count; uint8_t test_fn_count;
const char ** test_fn_name; const char ** test_fn_name;
struct test_desc_t* next; struct test_desc_t* next;
}; } test_desc_t;
void unity_testcase_register(struct test_desc_t* desc); void unity_testcase_register(test_desc_t* desc);
/* Test case macro, a-la CATCH framework. /* Test case macro, a-la CATCH framework.
@ -86,7 +87,7 @@ void unity_testcase_register(struct test_desc_t* desc);
static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \ static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \
{ \ { \
static test_func test_fn_[] = {&UNITY_TEST_UID(test_func_)}; \ static test_func test_fn_[] = {&UNITY_TEST_UID(test_func_)}; \
static struct test_desc_t UNITY_TEST_UID(test_desc_) = { \ static test_desc_t UNITY_TEST_UID(test_desc_) = { \
.name = name_, \ .name = name_, \
.desc = desc_, \ .desc = desc_, \
.fn = test_fn_, \ .fn = test_fn_, \
@ -116,7 +117,7 @@ void unity_testcase_register(struct test_desc_t* desc);
UNITY_TEST_FN_SET(__VA_ARGS__); \ UNITY_TEST_FN_SET(__VA_ARGS__); \
static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \ static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \
{ \ { \
static struct test_desc_t UNITY_TEST_UID(test_desc_) = { \ static test_desc_t UNITY_TEST_UID(test_desc_) = { \
.name = name_, \ .name = name_, \
.desc = desc_"[multi_stage]", \ .desc = desc_"[multi_stage]", \
.fn = UNITY_TEST_UID(test_functions), \ .fn = UNITY_TEST_UID(test_functions), \
@ -141,7 +142,7 @@ void unity_testcase_register(struct test_desc_t* desc);
UNITY_TEST_FN_SET(__VA_ARGS__); \ UNITY_TEST_FN_SET(__VA_ARGS__); \
static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \ static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \
{ \ { \
static struct test_desc_t UNITY_TEST_UID(test_desc_) = { \ static test_desc_t UNITY_TEST_UID(test_desc_) = { \
.name = name_, \ .name = name_, \
.desc = desc_"[multi_device]", \ .desc = desc_"[multi_device]", \
.fn = UNITY_TEST_UID(test_functions), \ .fn = UNITY_TEST_UID(test_functions), \
@ -162,3 +163,12 @@ void unity_testcase_register(struct test_desc_t* desc);
* field names are treated as annotations and don't affect initialization * field names are treated as annotations and don't affect initialization
* order. Also make sure all the fields are initialized. * order. Also make sure all the fields are initialized.
*/ */
void unity_run_test_by_name(const char *name);
void unity_run_tests_by_tag(const char *tag, bool invert);
void unity_run_all_tests();
void unity_run_menu();

View file

@ -14,30 +14,25 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include "esp_clk.h"
#include "soc/cpu.h"
#include "unity.h" #include "unity.h"
/* similar to UNITY_PRINT_EOL */
#define UNITY_PRINT_TAB() UNITY_OUTPUT_CHAR('\t')
// Pointers to the head and tail of linked list of test description structs: // Pointers to the head and tail of linked list of test description structs:
static struct test_desc_t* s_unity_tests_first = NULL; static test_desc_t *s_unity_tests_first = NULL;
static struct test_desc_t* s_unity_tests_last = NULL; static test_desc_t *s_unity_tests_last = NULL;
// Inverse of the filter void unity_testcase_register(test_desc_t *desc)
static bool s_invert = false;
void unity_testcase_register(struct test_desc_t* desc)
{ {
if (!s_unity_tests_first) if (!s_unity_tests_first) {
{
s_unity_tests_first = desc; s_unity_tests_first = desc;
s_unity_tests_last = desc; s_unity_tests_last = desc;
} } else {
else test_desc_t *temp = s_unity_tests_first;
{
struct test_desc_t* temp = s_unity_tests_first;
s_unity_tests_first = desc; s_unity_tests_first = desc;
s_unity_tests_first->next = temp; s_unity_tests_first->next = temp;
} }
@ -49,47 +44,58 @@ void unity_testcase_register(struct test_desc_t* desc)
* (1)master case * (1)master case
* (2)slave case * (2)slave case
* */ * */
static void print_multiple_function_test_menu(const struct test_desc_t* test_ms) static void print_multiple_function_test_menu(const test_desc_t *test_ms)
{ {
printf("%s\n", test_ms->name); UnityPrint(test_ms->name);
for (int i = 0; i < test_ms->test_fn_count; i++) UNITY_PRINT_EOL();
{ for (int i = 0; i < test_ms->test_fn_count; i++) {
printf("\t(%d)\t\"%s\"\n", i+1, test_ms->test_fn_name[i]); UNITY_PRINT_TAB();
UnityPrint("(");
UnityPrintNumberUnsigned(i + 1);
UnityPrint(")");
UNITY_PRINT_TAB();
UnityPrint("\"");
UnityPrint(test_ms->test_fn_name[i]);
UnityPrint("\"");
UNITY_PRINT_EOL();
} }
} }
void multiple_function_option(const struct test_desc_t* test_ms) static void multiple_function_option(const test_desc_t *test_ms)
{ {
int selection; int selection;
char cmdline[256] = {0}; char cmdline[256] = {0};
print_multiple_function_test_menu(test_ms); print_multiple_function_test_menu(test_ms);
while(strlen(cmdline) == 0) while (strlen(cmdline) == 0) {
{
unity_gets(cmdline, sizeof(cmdline)); unity_gets(cmdline, sizeof(cmdline));
if(strlen(cmdline) == 0) { if (strlen(cmdline) == 0) {
/* if input was newline, print a new menu */ /* if input was newline, print a new menu */
print_multiple_function_test_menu(test_ms); print_multiple_function_test_menu(test_ms);
} }
} }
selection = atoi((const char *) cmdline) - 1; selection = atoi((const char *) cmdline) - 1;
if(selection >= 0 && selection < test_ms->test_fn_count) { if (selection >= 0 && selection < test_ms->test_fn_count) {
UnityDefaultTestRun(test_ms->fn[selection], test_ms->name, test_ms->line); UnityDefaultTestRun(test_ms->fn[selection], test_ms->name, test_ms->line);
} else { } else {
printf("Invalid selection, your should input number 1-%d!", test_ms->test_fn_count); UnityPrint("Invalid selection, your should input number 1-");
UnityPrintNumber(test_ms->test_fn_count);
UNITY_PRINT_EOL();
} }
} }
static void unity_run_single_test(const struct test_desc_t* test) static void unity_run_single_test(const test_desc_t *test)
{ {
printf("Running %s...\n", test->name); UnityPrint("Running ");
UnityPrint(test->name);
UnityPrint("...");
UNITY_PRINT_EOL();
// Unit test runner expects to see test name before the test starts // Unit test runner expects to see test name before the test starts
fflush(stdout); UNITY_OUTPUT_FLUSH();
unity_flush();
Unity.TestFile = test->file; Unity.TestFile = test->file;
Unity.CurrentDetail1 = test->desc; Unity.CurrentDetail1 = test->desc;
if(test->test_fn_count == 1) { if (test->test_fn_count == 1) {
UnityDefaultTestRun(test->fn[0], test->name, test->line); UnityDefaultTestRun(test->fn[0], test->name, test->line);
} else { } else {
multiple_function_option(test); multiple_function_option(test);
@ -98,51 +104,34 @@ static void unity_run_single_test(const struct test_desc_t* test)
static void unity_run_single_test_by_index(int index) static void unity_run_single_test_by_index(int index)
{ {
const struct test_desc_t* test; const test_desc_t *test;
for (test = s_unity_tests_first; test != NULL && index != 0; test = test->next, --index) for (test = s_unity_tests_first; test != NULL && index != 0; test = test->next, --index) {
{ ;
} }
if (test != NULL) if (test != NULL) {
{
unity_run_single_test(test); unity_run_single_test(test);
} }
} }
static void unity_run_single_test_by_index_parse(const char* filter, int index_max) static void unity_run_single_test_by_index_parse(const char *filter, int index_max)
{ {
if (s_invert)
{
printf("Inverse is not supported for that kind of filter\n");
return;
}
int test_index = strtol(filter, NULL, 10); int test_index = strtol(filter, NULL, 10);
if (test_index >= 1 && test_index <= index_max) if (test_index >= 1 && test_index <= index_max) {
{ UNITY_EXEC_TIME_START();
uint32_t start;
RSR(CCOUNT, start);
unity_run_single_test_by_index(test_index - 1); unity_run_single_test_by_index(test_index - 1);
uint32_t end; UNITY_EXEC_TIME_STOP();
RSR(CCOUNT, end); UnityPrint("Test ran in ");
uint32_t ms = (end - start) / (esp_clk_cpu_freq() / 1000); UnityPrintNumberUnsigned(UNITY_EXEC_TIME_MS());
printf("Test ran in %dms\n", ms); UnityPrint("ms");
UNITY_PRINT_EOL();
UNITY_OUTPUT_FLUSH();
} }
} }
void unity_run_single_test_by_name(const char* filter) void unity_run_test_by_name(const char *name)
{ {
if (s_invert) for (const test_desc_t *test = s_unity_tests_first; test != NULL; test = test->next) {
{ if (strcmp(test->name, name) == 0) {
printf("Inverse is not supported for that kind of filter\n");
return;
}
char tmp[256];
strncpy(tmp, filter + 1, sizeof(tmp) - 1);
tmp[strlen(filter) - 2] = 0;
for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next)
{
if (strcmp(test->name, tmp) == 0)
{
unity_run_single_test(test); unity_run_single_test(test);
} }
} }
@ -150,39 +139,33 @@ void unity_run_single_test_by_name(const char* filter)
void unity_run_all_tests() void unity_run_all_tests()
{ {
if (s_invert) for (const test_desc_t *test = s_unity_tests_first; test != NULL; test = test->next) {
{
printf("Inverse is not supported for that kind of filter\n");
return;
}
for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next)
{
unity_run_single_test(test); unity_run_single_test(test);
} }
} }
void unity_run_tests_with_filter(const char* filter) void unity_run_tests_by_tag(const char *tag, bool invert)
{ {
if (s_invert) UnityPrint("Running tests ");
{ if (invert) {
++filter; UnityPrint("NOT ");
} }
printf("Running tests %smatching '%s'...\n", s_invert ? "NOT " : "", filter); UnityPrint("matching '");
UnityPrint(tag);
UnityPrint("'...");
UNITY_PRINT_EOL();
for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next) for (const test_desc_t *test = s_unity_tests_first; test != NULL; test = test->next) {
{ if ((strstr(test->desc, tag) != NULL) == !invert) {
if ((strstr(test->desc, filter) != NULL) == !s_invert)
{
unity_run_single_test(test); unity_run_single_test(test);
} }
} }
} }
static void trim_trailing_space(char* str) static void trim_trailing_space(char *str)
{ {
char* end = str + strlen(str) - 1; char *end = str + strlen(str) - 1;
while (end >= str && isspace((int) *end)) while (end >= str && isspace((int) *end)) {
{
*end = 0; *end = 0;
--end; --end;
} }
@ -191,31 +174,51 @@ static void trim_trailing_space(char* str)
static int print_test_menu(void) static int print_test_menu(void)
{ {
int test_counter = 0; int test_counter = 0;
printf("\n\nHere's the test menu, pick your combo:\n"); UNITY_PRINT_EOL();
for (const struct test_desc_t* test = s_unity_tests_first; UNITY_PRINT_EOL();
test != NULL; UnityPrint("Here's the test menu, pick your combo:");
test = test->next, ++test_counter) UNITY_PRINT_EOL();
{ for (const test_desc_t *test = s_unity_tests_first;
printf("(%d)\t\"%s\" %s\n", test_counter + 1, test->name, test->desc); test != NULL;
if(test->test_fn_count > 1) test = test->next, ++test_counter) {
{
for (int i = 0; i < test->test_fn_count; i++) UnityPrint("(");
{ UnityPrintNumber(test_counter + 1);
printf("\t(%d)\t\"%s\"\n", i+1, test->test_fn_name[i]); UnityPrint(")");
UNITY_PRINT_TAB();
UnityPrint("\"");
UnityPrint(test->name);
UnityPrint("\" ");
UnityPrint(test->desc);
UNITY_PRINT_EOL();
if (test->test_fn_count > 1) {
for (int i = 0; i < test->test_fn_count; i++) {
UNITY_PRINT_TAB();
UnityPrint("(");
UnityPrintNumber(i + 1);
UnityPrint(")");
UNITY_PRINT_TAB();
UnityPrint("\"");
UnityPrint(test->test_fn_name[i]);
UnityPrint("\"");
UNITY_PRINT_EOL();
} }
} }
} }
printf("\nEnter test for running.\n"); /* unit_test.py needs it for finding the end of test menu */ UNITY_PRINT_EOL();
return test_counter; UnityPrint("Enter test for running."); /* unit_test.py needs it for finding the end of test menu */
UNITY_PRINT_EOL();
UNITY_OUTPUT_FLUSH();
return test_counter;
} }
static int get_test_count(void) static int get_test_count(void)
{ {
int test_counter = 0; int test_counter = 0;
for (const struct test_desc_t* test = s_unity_tests_first; for (const test_desc_t *test = s_unity_tests_first;
test != NULL; test != NULL;
test = test->next) test = test->next) {
{
++test_counter; ++test_counter;
} }
return test_counter; return test_counter;
@ -223,23 +226,23 @@ static int get_test_count(void)
void unity_run_menu() void unity_run_menu()
{ {
printf("\n\nPress ENTER to see the list of tests.\n"); UNITY_PRINT_EOL();
UNITY_PRINT_EOL();
UnityPrint("Press ENTER to see the list of tests.");
UNITY_PRINT_EOL();
int test_count = get_test_count(); int test_count = get_test_count();
while (true) while (true) {
{
char cmdline[256] = { 0 }; char cmdline[256] = { 0 };
while(strlen(cmdline) == 0) while (strlen(cmdline) == 0) {
{
unity_gets(cmdline, sizeof(cmdline)); unity_gets(cmdline, sizeof(cmdline));
trim_trailing_space(cmdline); trim_trailing_space(cmdline);
if(strlen(cmdline) == 0) { if (strlen(cmdline) == 0) {
/* if input was newline, print a new menu */ /* if input was newline, print a new menu */
print_test_menu(); print_test_menu();
} }
} }
/*use '-' to show test history. Need to do it before UNITY_BEGIN cleanup history */ /*use '-' to show test history. Need to do it before UNITY_BEGIN cleanup history */
if (cmdline[0] == '-') if (cmdline[0] == '-') {
{
UNITY_END(); UNITY_END();
continue; continue;
} }
@ -247,35 +250,30 @@ void unity_run_menu()
UNITY_BEGIN(); UNITY_BEGIN();
size_t idx = 0; size_t idx = 0;
if (cmdline[idx] == '!') bool invert = false;
{ if (cmdline[idx] == '!') {
s_invert = true; invert = true;
++idx; ++idx;
} }
else
{
s_invert = false;
}
if (cmdline[idx] == '*') if (cmdline[idx] == '*') {
{
unity_run_all_tests(); unity_run_all_tests();
} } else if (cmdline[idx] == '[') {
else if (cmdline[idx] =='[') unity_run_tests_by_tag(cmdline + idx, invert);
{ } else if (cmdline[idx] == '"') {
unity_run_tests_with_filter(cmdline + idx); char* end = strrchr(cmdline, '"');
} if (end > &cmdline[idx]) {
else if (cmdline[idx] =='"') *end = 0;
{ unity_run_test_by_name(cmdline + idx + 1);
unity_run_single_test_by_name(cmdline + idx); }
} } else if (isdigit((unsigned char)cmdline[idx])) {
else if (isdigit((unsigned char)cmdline[idx]))
{
unity_run_single_test_by_index_parse(cmdline + idx, test_count); unity_run_single_test_by_index_parse(cmdline + idx, test_count);
} }
UNITY_END(); UNITY_END();
printf("Enter next test, or 'enter' to see menu\n"); UnityPrint("Enter next test, or 'enter' to see menu");
UNITY_PRINT_EOL();
UNITY_OUTPUT_FLUSH();
} }
} }