/* * Copyright (C) 2015-2017 Alibaba Group Holding Limited */ #include #include #include #include #include #include #include #include "yunit.h" #define TAG "yunit" extern k_mm_head *g_kmm_head; typedef struct yunit_test_case_node_s { struct yunit_test_case_node_s *next; const char *name; yunit_test_case_proc test_proc; } yunit_test_case_node_t; typedef struct yunit_test_suite_node_s { struct yunit_test_suite_node_s *next; const char *name; yunit_test_suit_init init; yunit_test_suit_deinit deinit; yunit_test_case_setup setup; yunit_test_case_teardown teardown; yunit_test_case_node_t test_case_list_header; } yunit_test_suite_node_t; #define TEST_RESULT_MESSAGE_LENGTH 64 typedef struct yunit_test_case_result_s { struct yunit_test_case_result_s *next; const char *file; size_t line; char msg[TEST_RESULT_MESSAGE_LENGTH]; } yunit_test_case_result_t; typedef struct { yunit_test_suite_node_t test_suite_list_header; int all_test_cases_count; int failed_test_cases_count; int fatal_test_cases_count; yunit_test_case_result_t failed_test_case_result; } yunit_test_context_t; static int yunit_run_test_case_list( yunit_test_suite_node_t *suite, yunit_test_case_node_t *test_case_list_header); yunit_test_context_t g_test_context; void yunit_test_init(void) { memset(&g_test_context, 0, sizeof(yunit_test_context_t)); } void yunit_test_deinit(void) { yunit_test_suite_node_t *test_suite_node = g_test_context.test_suite_list_header.next; while (test_suite_node != NULL) { yunit_test_case_node_t *test_case_node = test_suite_node->test_case_list_header.next; while (test_case_node != NULL) { yunit_test_case_node_t *test_case_node_next = test_case_node->next; aos_free(test_case_node); test_case_node = test_case_node_next; } yunit_test_suite_node_t *test_suite_node_next = test_suite_node->next; aos_free(test_suite_node); test_suite_node = test_suite_node_next; } yunit_test_case_result_t *test_case_result = g_test_context.failed_test_case_result.next; while (test_case_result != NULL) { yunit_test_case_result_t *test_case_result_next = test_case_result->next; aos_free(test_case_result); test_case_result = test_case_result_next; } } void *yunit_add_test_suite( const char *name, yunit_test_suit_init init, yunit_test_suit_deinit deinit, yunit_test_case_setup setup, yunit_test_case_teardown teardown) { yunit_test_suite_node_t *node = aos_malloc(sizeof(yunit_test_suite_node_t)); if (node == NULL) { printf("%s\n", "out of memory"); return NULL; } memset(node, 0, sizeof(yunit_test_suite_node_t)); node->next = NULL; node->name = name; node->init = init; node->deinit = deinit; node->setup = setup; node->teardown = teardown; yunit_test_suite_node_t *prev = &g_test_context.test_suite_list_header; while (prev->next != NULL) { prev = prev->next; } prev->next = node; return node; } int yunit_add_test_case(void *test_suite, const char *name, yunit_test_case_proc proc) { yunit_test_suite_node_t *test_suite_node = test_suite; yunit_test_case_node_t *prev = &test_suite_node->test_case_list_header; while (prev->next != NULL) { prev = prev->next; } yunit_test_case_node_t *node = aos_malloc(sizeof(yunit_test_case_node_t)); memset(node, 0, sizeof(yunit_test_case_node_t)); if (node == NULL) { printf("%s\n", "out of memory"); return -1; } node->name = name; node->test_proc = proc; prev->next = node; return 0; } int yunit_add_test_suites(yunit_test_suite_t *test_suit_array) { int i = 0; while (test_suit_array[i].name != NULL) { yunit_test_suite_t *test_suite = &test_suit_array[i++]; void *test_suite_node = yunit_add_test_suite( test_suite->name, test_suite->init, test_suite->deinit, test_suite->setup, test_suite->teardown); if (test_suite_node == NULL) { return -1; } int j = 0; yunit_test_case_t *test_case_array = test_suite->test_case_array; while (test_case_array[j].name != NULL) { yunit_test_case_t *test_case = &test_case_array[j++]; int ret = yunit_add_test_case( test_suite_node, test_case->name, test_case->test_proc); if (ret == -1) { return ret; } } } return 0; } void *yunit_get_test_suite(const char *name) { yunit_test_suite_node_t *node = g_test_context.test_suite_list_header.next; while (node != NULL) { if (strcmp(node->name, name) == 0) { return node; } node = node->next; } return NULL; } void *yunit_get_test_case(void *test_suite, const char *name) { yunit_test_suite_node_t *test_suite_node = test_suite; yunit_test_case_node_t *node = test_suite_node->test_case_list_header.next; while (node != NULL) { if (strcmp(node->name, name) == 0) { return node; } node = node->next; } return NULL; } int yunit_test_run(void) { int ret = 0; yunit_test_suite_node_t *test_suite = g_test_context.test_suite_list_header.next; while (test_suite != NULL) { ret = yunit_run_test_suite(test_suite, 1); if (ret != 0) { return ret; } test_suite = test_suite->next; } return ret; } int yunit_run_test_suite(void *test_suite, int test_times) { int ret = 0; int index = 0; yunit_test_suite_node_t *node = NULL; if (NULL == test_suite || test_times < 1) { printf("param error\n"); return -1; } node = test_suite; printf("Run test suite:%s\n", node->name); for (index = 0; index < test_times; index++) { if (node->init != NULL) { node->init(); } ret = yunit_run_test_case_list(node, &node->test_case_list_header); if (node->deinit != NULL) { node->deinit(); } if (ret != 0) { printf("Run test suite %s index:%d failed ret:%d\n", node->name, index + 1, ret); } } return 0; } static int _run_test_case(void *test_suite, void *test_case) { yunit_test_suite_node_t *test_suite_node = test_suite; yunit_test_case_node_t *test_case_node = test_case; int cnt1 = g_test_context.failed_test_cases_count + g_test_context.fatal_test_cases_count; int cnt2; long long now = aos_now_ms(); int delta; if (test_suite_node->setup != NULL) { test_suite_node->setup(); } fprintf(stderr, "Run test case:%s start ... free heap = %d\n", test_case_node->name, g_kmm_head->free_size); if (test_case_node->test_proc != NULL) { test_case_node->test_proc(); } if (test_suite_node->teardown != NULL) { test_suite_node->teardown(); } cnt2 = g_test_context.failed_test_cases_count + g_test_context.fatal_test_cases_count; delta = aos_now_ms() - now; if ((cnt2 - cnt1) > 0) //There are some failed { fprintf(stderr, "Run test case:%s finished elapsed time:%d ms failed:%d\n", test_case_node->name, delta, cnt2 - cnt1); } else { fprintf(stderr, "Run test case:%s finished elapsed time:%d ms\n", test_case_node->name, delta); } return 0; } int yunit_run_test_case(void *test_suite, void *test_case) { int ret = 0; yunit_test_suite_node_t *tnode = test_suite; yunit_test_case_node_t *tcase = test_case; printf("Run test suites %s\n", tnode->name); if (tnode->init != NULL) { tnode->init(); } ret = _run_test_case(tnode, tcase); if (tnode->deinit != NULL) { tnode->deinit(); } if (ret != 0) { LOGE(TAG, "Suite:%s fail ret = %d", tnode->name, ret); return ret; } return 0; } int yunit_run_test_case_list(yunit_test_suite_node_t *test_suite, yunit_test_case_node_t *test_case_list_header) { int ret = 0; yunit_test_case_node_t *node = test_case_list_header->next; while (node != NULL) { ret = _run_test_case(test_suite, node); if (ret != 0) { return ret; } node = node->next; } return ret; } void yunit_add_test_case_result(int type, const char *file, size_t line, const char *fmt, ...) { g_test_context.all_test_cases_count++; if (type == TEST_RESULT_SUCCESS) { return; } if (type == TEST_RESULT_FAILURE) { g_test_context.failed_test_cases_count++; } else if (type == TEST_RESULT_FATAL) { g_test_context.fatal_test_cases_count++; } else { } yunit_test_case_result_t *result = aos_malloc(sizeof(yunit_test_case_result_t)); if (result == NULL) { printf("%s\n", "out of memory"); return; } memset(result, 0, sizeof(yunit_test_case_result_t)); va_list args; va_start(args, fmt); vsnprintf(result->msg, TEST_RESULT_MESSAGE_LENGTH, fmt, args); va_end(args); result->file = file; result->line = line; yunit_test_case_result_t *prev = &g_test_context.failed_test_case_result; while (prev != NULL && prev->next != NULL) { prev = prev->next; } prev->next = result; } void yunit_test_print_result(void) { int failed_times = 0; int passed_times = 0; printf("\n--------------------------------\n"); failed_times = g_test_context.failed_test_cases_count + g_test_context.fatal_test_cases_count; passed_times = g_test_context.all_test_cases_count - failed_times; if (failed_times > 0) { printf("total:%d test cases, passed:%d failed:%d\n\n", g_test_context.all_test_cases_count, passed_times, failed_times); } else { printf("total:%d test cases, passed:%d\n\n", g_test_context.all_test_cases_count, passed_times); } yunit_test_case_result_t *result = g_test_context.failed_test_case_result.next; while (result != NULL) { printf("failed at %s(#%d) %s\n", result->file, result->line, result->msg); result = result->next; } printf("\n--------------------------------\n"); }