unittests #9
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @@ -27,6 +27,9 @@ validate: asan msan debug | ||||
| analyze: | ||||
| 	make -rRf make/analyze.mk clean all | ||||
|  | ||||
| test: | ||||
| 	make -rRf make/test.mk test | ||||
|  | ||||
| clean: | ||||
| 	make -rRf make/release.mk clean | ||||
| 	make -rRf make/debug.mk clean | ||||
| @@ -34,6 +37,7 @@ clean: | ||||
| 	make -rRf make/msan.mk clean | ||||
| 	make -rRf make/asan.mk clean | ||||
| 	make -rRf make/analyze.mk clean | ||||
| 	make -rRf make/test.mk clean | ||||
| 	rm -rf build/ | ||||
|  | ||||
| distclean: clean | ||||
|   | ||||
							
								
								
									
										9
									
								
								make/test.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								make/test.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| .PHONY: test | ||||
|  | ||||
| BUILD_DIR=build/test/ | ||||
| TARGET=oas-tests | ||||
| SOURCES = $(filter-out src/main.c, $(shell find src/ tests/ -type f -name '*.c')) | ||||
| -include make/base.mk | ||||
|  | ||||
| test: $(BUILD_DIR)$(TARGET) | ||||
| 	$(BUILD_DIR)$(TARGET) | ||||
							
								
								
									
										6
									
								
								tests/.clang-format
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/.clang-format
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| BasedOnStyle:    LLVM | ||||
| IndentWidth:     4 | ||||
| Cpp11BracedListStyle: true | ||||
| AlignArrayOfStructures: Left | ||||
| AllowShortFunctionsOnASingleLine: Empty | ||||
| ColumnLimit: 120 | ||||
							
								
								
									
										22
									
								
								tests/ast.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/ast.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #include "../src/ast.h" | ||||
| #include "munit.h" | ||||
|  | ||||
| MunitResult test_ast_node_alloc(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     ast_node_t *node = nullptr; | ||||
|     error_t *err = ast_node_alloc(&node); | ||||
|  | ||||
|     munit_assert_ptr_not_null(node); | ||||
|     munit_assert_ptr_null(err); | ||||
|  | ||||
|     ast_node_free(node); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitTest ast_tests[] = { | ||||
|     {"/node_alloc", test_ast_node_alloc, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {nullptr,       nullptr,             nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr} | ||||
| }; | ||||
							
								
								
									
										896
									
								
								tests/lexer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										896
									
								
								tests/lexer.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,896 @@ | ||||
| #include "../src/lexer.h" | ||||
| #include "../src/error.h" | ||||
| #include "munit.h" | ||||
| #include <string.h> | ||||
|  | ||||
| void lexer_setup_memory_test(lexer_t *lex, const char *input) { | ||||
|     munit_assert_null(lex->fp); | ||||
|     FILE *stream = fmemopen((void *)input, strlen(input), "rb"); | ||||
|     munit_assert_not_null(stream); | ||||
|     lex->fp = stream; | ||||
|     lex->line_number = 0; | ||||
|     lex->character_number = 0; | ||||
|     lex->buffer_count = 0; | ||||
| } | ||||
|  | ||||
| void lexer_expect_one_token(lexer_t *lex, lexer_token_id_t id, const char *value, size_t line, size_t column) { | ||||
|     lexer_token_t token = {}; | ||||
|  | ||||
|     error_t *err = lexer_next(lex, &token); | ||||
|     munit_assert_null(err); | ||||
|  | ||||
|     munit_assert_int(token.id, ==, id); | ||||
|     munit_assert_string_equal(token.value, value); | ||||
|     munit_assert_int(token.line_number, ==, line); | ||||
|     munit_assert_int(token.character_number, ==, column); | ||||
|     lexer_token_cleanup(&token); | ||||
| } | ||||
|  | ||||
| void lexer_expect_eof(lexer_t *lex) { | ||||
|     lexer_token_t token = {}; | ||||
|     error_t *err = lexer_next(lex, &token); | ||||
|     munit_assert_ptr_equal(err, err_eof); | ||||
| } | ||||
|  | ||||
| void lexer_test_one_token(lexer_token_id_t id, const char *value) { | ||||
|     lexer_t lex = {}; | ||||
|     lexer_setup_memory_test(&lex, value); | ||||
|     lexer_expect_one_token(&lex, id, value, 0, 0); | ||||
|     lexer_expect_eof(&lex); | ||||
|     lexer_close(&lex); | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_identifier(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_IDENTIFIER, "identifier"); | ||||
|     lexer_test_one_token(TOKEN_IDENTIFIER, "_identifier"); | ||||
|     lexer_test_one_token(TOKEN_IDENTIFIER, "_identifier123_55"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| typedef struct token_data { | ||||
|     lexer_token_id_t id; | ||||
|     char *value; | ||||
|     size_t line; | ||||
|     size_t column; | ||||
| } token_data_t; | ||||
|  | ||||
| typedef struct boundary { | ||||
|     const char *input; | ||||
|     token_data_t first; | ||||
|     token_data_t second; | ||||
| } boundary_t; | ||||
|  | ||||
| void test_lexer_boundary(boundary_t boundaries[]) { | ||||
|     for (size_t i = 0; boundaries[i].input; ++i) { | ||||
|         auto boundary = boundaries[i]; | ||||
|         auto first = boundary.first; | ||||
|         auto second = boundary.second; | ||||
|  | ||||
|         lexer_t lex = {}; | ||||
|         lexer_setup_memory_test(&lex, boundary.input); | ||||
|         lexer_expect_one_token(&lex, first.id, first.value, first.line, first.column); | ||||
|         lexer_expect_one_token(&lex, second.id, second.value, second.line, second.column); | ||||
|         lexer_expect_eof(&lex); | ||||
|         lexer_close(&lex); | ||||
|     } | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_identifier_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"id:",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_COLON, ":", 0, 2}         }, | ||||
|         {"id[",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_LBRACKET, "[", 0, 2}      }, | ||||
|         {"id]",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_RBRACKET, "]", 0, 2}      }, | ||||
|         {"id+",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_PLUS, "+", 0, 2}          }, | ||||
|         {"id-",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_MINUS, "-", 0, 2}         }, | ||||
|         {"id*",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_ASTERISK, "*", 0, 2}      }, | ||||
|         {"id.",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_DOT, ".", 0, 2}           }, | ||||
|         {"id;comment", {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_COMMENT, ";comment", 0, 2}}, | ||||
|         {"id\n",       {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 2}      }, | ||||
|         {"id\r\n",     {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 2}    }, | ||||
|         {"id ",        {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 2}    }, | ||||
|         {"id\t",       {TOKEN_IDENTIFIER, "id", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 2}   }, | ||||
|         {nullptr,      {},                             {}                               }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_decimal(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "123"); | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "0"); | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "42"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_decimal_with_suffix(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "123:8"); | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "0:16"); | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "42:32"); | ||||
|     lexer_test_one_token(TOKEN_DECIMAL, "69:64"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_hexadecimal(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0x123"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0xDEAD"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0x0"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0xabcdef"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0xABCDEF"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_hexadecimal_with_suffix(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0x123:8"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0xDEAD:16"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0xABC:32"); | ||||
|     lexer_test_one_token(TOKEN_HEXADECIMAL, "0xffff:64"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_octal(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o777"); | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o0"); | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o123"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_octal_with_suffix(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o777:8"); | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o123:16"); | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o777:32"); | ||||
|     lexer_test_one_token(TOKEN_OCTAL, "0o123:64"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_binary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b101"); | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b0"); | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b1"); | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b01010101"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_binary_with_suffix(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b101:8"); | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b0:16"); | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b1:32"); | ||||
|     lexer_test_one_token(TOKEN_BINARY, "0b01010101:64"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_colon(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_COLON, ":"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_comma(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_COMMA, ","); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_lbracket(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_LBRACKET, "["); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_rbracket(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_RBRACKET, "]"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_plus(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_PLUS, "+"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_minus(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_MINUS, "-"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_asterisk(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_ASTERISK, "*"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_dot(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_DOT, "."); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_comment(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_COMMENT, ";This is a comment"); | ||||
|     lexer_test_one_token(TOKEN_COMMENT, "; Another comment"); | ||||
|     lexer_test_one_token(TOKEN_COMMENT, ";"); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_whitespace(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|     lexer_test_one_token(TOKEN_WHITESPACE, " "); | ||||
|     lexer_test_one_token(TOKEN_WHITESPACE, "  "); | ||||
|     lexer_test_one_token(TOKEN_WHITESPACE, "\t"); | ||||
|     lexer_test_one_token(TOKEN_WHITESPACE, " \t "); | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_newlines(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     // Test simple newline | ||||
|     lexer_t lex = {}; | ||||
|     lexer_setup_memory_test(&lex, "\n"); | ||||
|     lexer_expect_one_token(&lex, TOKEN_NEWLINE, "\n", 0, 0); | ||||
|     lexer_expect_eof(&lex); | ||||
|     lexer_close(&lex); | ||||
|  | ||||
|     // Test Windows-style newline | ||||
|     lexer_t lex2 = {}; | ||||
|     lexer_setup_memory_test(&lex2, "\r\n"); | ||||
|     lexer_expect_one_token(&lex2, TOKEN_NEWLINE, "\r\n", 0, 0); | ||||
|     lexer_expect_eof(&lex2); | ||||
|     lexer_close(&lex2); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_line_numbers(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     lexer_t lex = {}; | ||||
|     lexer_setup_memory_test(&lex, "a\nb\nc"); | ||||
|  | ||||
|     lexer_expect_one_token(&lex, TOKEN_IDENTIFIER, "a", 0, 0); | ||||
|     lexer_expect_one_token(&lex, TOKEN_NEWLINE, "\n", 0, 1); | ||||
|     lexer_expect_one_token(&lex, TOKEN_IDENTIFIER, "b", 1, 0); | ||||
|     lexer_expect_one_token(&lex, TOKEN_NEWLINE, "\n", 1, 1); | ||||
|     lexer_expect_one_token(&lex, TOKEN_IDENTIFIER, "c", 2, 0); | ||||
|     lexer_expect_eof(&lex); | ||||
|     lexer_close(&lex); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_decimal_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"123,",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_COMMA, ",", 0, 3}      }, | ||||
|         {"123:",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_COLON, ":", 0, 3}      }, | ||||
|         {"123[",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_LBRACKET, "[", 0, 3}   }, | ||||
|         {"123]",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_RBRACKET, "]", 0, 3}   }, | ||||
|         {"123+",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_PLUS, "+", 0, 3}       }, | ||||
|         {"123-",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_MINUS, "-", 0, 3}      }, | ||||
|         {"123*",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_ASTERISK, "*", 0, 3}   }, | ||||
|         {"123.",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_DOT, ".", 0, 3}        }, | ||||
|         {"123;",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_COMMENT, ";", 0, 3}    }, | ||||
|         {"123\n",   {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 3}   }, | ||||
|         {"123\r\n", {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 3} }, | ||||
|         {"123 ",    {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 3} }, | ||||
|         {"123\t",   {TOKEN_DECIMAL, "123", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 3}}, | ||||
|         {nullptr,   {},                           {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_hexadecimal_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"0x123,",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_COMMA, ",", 0, 5}      }, | ||||
|         {"0x123:",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_COLON, ":", 0, 5}      }, | ||||
|         {"0x123[",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_LBRACKET, "[", 0, 5}   }, | ||||
|         {"0x123]",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_RBRACKET, "]", 0, 5}   }, | ||||
|         {"0x123+",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_PLUS, "+", 0, 5}       }, | ||||
|         {"0x123-",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_MINUS, "-", 0, 5}      }, | ||||
|         {"0x123*",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_ASTERISK, "*", 0, 5}   }, | ||||
|         {"0x123.",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_DOT, ".", 0, 5}        }, | ||||
|         {"0x123;",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_COMMENT, ";", 0, 5}    }, | ||||
|         {"0x123\n",   {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 5}   }, | ||||
|         {"0x123\r\n", {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 5} }, | ||||
|         {"0x123 ",    {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 5} }, | ||||
|         {"0x123\t",   {TOKEN_HEXADECIMAL, "0x123", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 5}}, | ||||
|         {nullptr,     {},                                 {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_octal_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"0o123,",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_COMMA, ",", 0, 5}      }, | ||||
|         {"0o123:",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_COLON, ":", 0, 5}      }, | ||||
|         {"0o123[",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_LBRACKET, "[", 0, 5}   }, | ||||
|         {"0o123]",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_RBRACKET, "]", 0, 5}   }, | ||||
|         {"0o123+",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_PLUS, "+", 0, 5}       }, | ||||
|         {"0o123-",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_MINUS, "-", 0, 5}      }, | ||||
|         {"0o123*",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_ASTERISK, "*", 0, 5}   }, | ||||
|         {"0o123.",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_DOT, ".", 0, 5}        }, | ||||
|         {"0o123;",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_COMMENT, ";", 0, 5}    }, | ||||
|         {"0o123\n",   {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 5}   }, | ||||
|         {"0o123\r\n", {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 5} }, | ||||
|         {"0o123 ",    {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 5} }, | ||||
|         {"0o123\t",   {TOKEN_OCTAL, "0o123", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 5}}, | ||||
|         {nullptr,     {},                           {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_binary_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"0b101,",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_COMMA, ",", 0, 5}      }, | ||||
|         {"0b101:",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_COLON, ":", 0, 5}      }, | ||||
|         {"0b101[",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_LBRACKET, "[", 0, 5}   }, | ||||
|         {"0b101]",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_RBRACKET, "]", 0, 5}   }, | ||||
|         {"0b101+",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_PLUS, "+", 0, 5}       }, | ||||
|         {"0b101-",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_MINUS, "-", 0, 5}      }, | ||||
|         {"0b101*",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_ASTERISK, "*", 0, 5}   }, | ||||
|         {"0b101.",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_DOT, ".", 0, 5}        }, | ||||
|         {"0b101;",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_COMMENT, ";", 0, 5}    }, | ||||
|         {"0b101\n",   {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 5}   }, | ||||
|         {"0b101\r\n", {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 5} }, | ||||
|         {"0b101 ",    {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 5} }, | ||||
|         {"0b101\t",   {TOKEN_BINARY, "0b101", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 5}}, | ||||
|         {nullptr,     {},                            {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_colon_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {":,",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {"::",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {":[",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {":]",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {":+",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {":-",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {":*",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {":.",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {":;",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {":\n",   {TOKEN_COLON, ":", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {":\r\n", {TOKEN_COLON, ":", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {": ",    {TOKEN_COLON, ":", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {":\t",   {TOKEN_COLON, ":", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                       {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_comma_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {",,",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {",:",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {",[",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {",]",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {",+",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {",-",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {",*",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {",.",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {",;",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {",\n",   {TOKEN_COMMA, ",", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {",\r\n", {TOKEN_COMMA, ",", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {", ",    {TOKEN_COMMA, ",", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {",\t",   {TOKEN_COMMA, ",", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                       {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_lbracket_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"[,",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {"[:",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {"[[",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {"[]",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {"[+",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {"[-",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {"[*",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {"[.",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {"[;",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {"[\n",   {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {"[\r\n", {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {"[ ",    {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {"[\t",   {TOKEN_LBRACKET, "[", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                          {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_rbracket_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"],",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {"]:",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {"][",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {"]]",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {"]+",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {"]-",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {"]*",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {"].",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {"];",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {"]\n",   {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {"]\r\n", {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {"] ",    {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {"]\t",   {TOKEN_RBRACKET, "]", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                          {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_plus_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"+,",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {"+:",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {"+[",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {"+]",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {"++",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {"+-",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {"+*",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {"+.",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {"+;",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {"+\n",   {TOKEN_PLUS, "+", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {"+\r\n", {TOKEN_PLUS, "+", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {"+ ",    {TOKEN_PLUS, "+", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {"+\t",   {TOKEN_PLUS, "+", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                      {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_minus_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"-,",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {"-:",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {"-[",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {"-]",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {"-+",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {"--",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {"-*",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {"-.",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {"-;",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {"-\n",   {TOKEN_MINUS, "-", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {"-\r\n", {TOKEN_MINUS, "-", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {"- ",    {TOKEN_MINUS, "-", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {"-\t",   {TOKEN_MINUS, "-", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                       {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_asterisk_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"*,",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {"*:",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {"*[",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {"*]",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {"*+",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {"*-",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {"**",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {"*.",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {"*;",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {"*\n",   {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {"*\r\n", {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {"* ",    {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {"*\t",   {TOKEN_ASTERISK, "*", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                          {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_dot_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {".,",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_COMMA, ",", 0, 1}      }, | ||||
|         {".:",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_COLON, ":", 0, 1}      }, | ||||
|         {".[",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}   }, | ||||
|         {".]",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}   }, | ||||
|         {".+",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_PLUS, "+", 0, 1}       }, | ||||
|         {".-",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_MINUS, "-", 0, 1}      }, | ||||
|         {".*",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}   }, | ||||
|         {"..",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_DOT, ".", 0, 1}        }, | ||||
|         {".;",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}    }, | ||||
|         {".\n",   {TOKEN_DOT, ".", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}   }, | ||||
|         {".\r\n", {TOKEN_DOT, ".", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1} }, | ||||
|         {". ",    {TOKEN_DOT, ".", 0, 0}, {TOKEN_WHITESPACE, " ", 0, 1} }, | ||||
|         {".\t",   {TOKEN_DOT, ".", 0, 0}, {TOKEN_WHITESPACE, "\t", 0, 1}}, | ||||
|         {nullptr, {},                     {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_comment_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {";comment\n",   {TOKEN_COMMENT, ";comment", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 8}  }, | ||||
|         {";comment\r\n", {TOKEN_COMMENT, ";comment", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 8}}, | ||||
|         {nullptr,        {},                                {}                           }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_whitespace_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {" ,",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_COMMA, ",", 0, 1}     }, | ||||
|         {" :",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_COLON, ":", 0, 1}     }, | ||||
|         {" [",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_LBRACKET, "[", 0, 1}  }, | ||||
|         {" ]",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_RBRACKET, "]", 0, 1}  }, | ||||
|         {" +",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_PLUS, "+", 0, 1}      }, | ||||
|         {" -",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_MINUS, "-", 0, 1}     }, | ||||
|         {" *",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_ASTERISK, "*", 0, 1}  }, | ||||
|         {" .",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_DOT, ".", 0, 1}       }, | ||||
|         {" ;",    {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_COMMENT, ";", 0, 1}   }, | ||||
|         {" \n",   {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 1}  }, | ||||
|         {" \r\n", {TOKEN_WHITESPACE, " ", 0, 0}, {TOKEN_NEWLINE, "\r\n", 0, 1}}, | ||||
|         {nullptr, {},                            {}                           }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_newline_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"\n,",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_COMMA, ",", 1, 0}      }, | ||||
|         {"\n:",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_COLON, ":", 1, 0}      }, | ||||
|         {"\n[",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_LBRACKET, "[", 1, 0}   }, | ||||
|         {"\n]",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_RBRACKET, "]", 1, 0}   }, | ||||
|         {"\n+",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_PLUS, "+", 1, 0}       }, | ||||
|         {"\n-",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_MINUS, "-", 1, 0}      }, | ||||
|         {"\n*",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_ASTERISK, "*", 1, 0}   }, | ||||
|         {"\n.",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_DOT, ".", 1, 0}        }, | ||||
|         {"\n;",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_COMMENT, ";", 1, 0}    }, | ||||
|         {"\n\n",   {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_NEWLINE, "\n", 1, 0}   }, | ||||
|         {"\n\r\n", {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_NEWLINE, "\r\n", 1, 0} }, | ||||
|         {"\n ",    {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_WHITESPACE, " ", 1, 0} }, | ||||
|         {"\n\t",   {TOKEN_NEWLINE, "\n", 0, 0}, {TOKEN_WHITESPACE, "\t", 1, 0}}, | ||||
|         {nullptr,  {},                          {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_crlf_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"\r\n,",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_COMMA, ",", 1, 0}      }, | ||||
|         {"\r\n:",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_COLON, ":", 1, 0}      }, | ||||
|         {"\r\n[",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_LBRACKET, "[", 1, 0}   }, | ||||
|         {"\r\n]",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_RBRACKET, "]", 1, 0}   }, | ||||
|         {"\r\n+",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_PLUS, "+", 1, 0}       }, | ||||
|         {"\r\n-",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_MINUS, "-", 1, 0}      }, | ||||
|         {"\r\n*",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_ASTERISK, "*", 1, 0}   }, | ||||
|         {"\r\n.",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_DOT, ".", 1, 0}        }, | ||||
|         {"\r\n;",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_COMMENT, ";", 1, 0}    }, | ||||
|         {"\r\n\n",   {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_NEWLINE, "\n", 1, 0}   }, | ||||
|         {"\r\n\r\n", {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_NEWLINE, "\r\n", 1, 0} }, | ||||
|         {"\r\n ",    {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_WHITESPACE, " ", 1, 0} }, | ||||
|         {"\r\n\t",   {TOKEN_NEWLINE, "\r\n", 0, 0}, {TOKEN_WHITESPACE, "\t", 1, 0}}, | ||||
|         {nullptr,    {},                            {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_number_boundary(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     boundary_t boundaries[] = { | ||||
|         {"0x123:8,",     {TOKEN_HEXADECIMAL, "0x123:8", 0, 0},  {TOKEN_COMMA, ",", 0, 7}      }, | ||||
|         {"0x123:16:",    {TOKEN_HEXADECIMAL, "0x123:16", 0, 0}, {TOKEN_COLON, ":", 0, 8}      }, | ||||
|         {"0o777:32[",    {TOKEN_OCTAL, "0o777:32", 0, 0},       {TOKEN_LBRACKET, "[", 0, 8}   }, | ||||
|         {"0b101:64]",    {TOKEN_BINARY, "0b101:64", 0, 0},      {TOKEN_RBRACKET, "]", 0, 8}   }, | ||||
|         {"0x123:8+",     {TOKEN_HEXADECIMAL, "0x123:8", 0, 0},  {TOKEN_PLUS, "+", 0, 7}       }, | ||||
|         {"0x123:16-",    {TOKEN_HEXADECIMAL, "0x123:16", 0, 0}, {TOKEN_MINUS, "-", 0, 8}      }, | ||||
|         {"0o777:32*",    {TOKEN_OCTAL, "0o777:32", 0, 0},       {TOKEN_ASTERISK, "*", 0, 8}   }, | ||||
|         {"0b101:64.",    {TOKEN_BINARY, "0b101:64", 0, 0},      {TOKEN_DOT, ".", 0, 8}        }, | ||||
|         {"0x123:8;",     {TOKEN_HEXADECIMAL, "0x123:8", 0, 0},  {TOKEN_COMMENT, ";", 0, 7}    }, | ||||
|         {"0x123:16\n",   {TOKEN_HEXADECIMAL, "0x123:16", 0, 0}, {TOKEN_NEWLINE, "\n", 0, 8}   }, | ||||
|         {"0o777:32\r\n", {TOKEN_OCTAL, "0o777:32", 0, 0},       {TOKEN_NEWLINE, "\r\n", 0, 8} }, | ||||
|         {"0b101:64 ",    {TOKEN_BINARY, "0b101:64", 0, 0},      {TOKEN_WHITESPACE, " ", 0, 8} }, | ||||
|         {"0x123:8\t",    {TOKEN_HEXADECIMAL, "0x123:8", 0, 0},  {TOKEN_WHITESPACE, "\t", 0, 7}}, | ||||
|         {nullptr,        {},                                    {}                            }, | ||||
|     }; | ||||
|  | ||||
|     test_lexer_boundary(boundaries); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_maximum_length_numbers(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     char *numbers[] = { | ||||
|         "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "9999999999999999999988", | ||||
|         "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "9999999999999999998:64", | ||||
|         "0x99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "9999999999999999999988", | ||||
|         "0x99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "9999999999999999998:64", | ||||
|         nullptr, | ||||
|     }; | ||||
|  | ||||
|     for (size_t i = 0; numbers[i]; ++i) { | ||||
|         auto number = numbers[i]; | ||||
|         munit_assert_size(128, ==, strlen(number)); | ||||
|         lexer_t lex = {}; | ||||
|         lexer_token_t token = {}; | ||||
|         lexer_setup_memory_test(&lex, number); | ||||
|         lexer_next(&lex, &token); | ||||
|         munit_assert_true(token.id == TOKEN_DECIMAL || token.id == TOKEN_HEXADECIMAL); | ||||
|         munit_assert_size(128, ==, strlen(token.value)); | ||||
|         lexer_token_cleanup(&token); | ||||
|         lexer_close(&lex); | ||||
|     } | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_too_long_numbers(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     char *numbers[] = { | ||||
|         "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "99999999999999999999988", | ||||
|         "0x99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "99999999999999999999988", | ||||
|         "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "99999999999999999998:64", | ||||
|         "0x99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" | ||||
|         "99999999999999999998:64", | ||||
|     }; | ||||
|  | ||||
|     // Without suffix we expect 128 characters and then failure | ||||
|     for (size_t i = 0; i < 2; ++i) { | ||||
|         auto number = numbers[i]; | ||||
|         munit_assert_size(129, ==, strlen(number)); | ||||
|         lexer_t lex = {}; | ||||
|         lexer_token_t token = {}; | ||||
|         lexer_setup_memory_test(&lex, number); | ||||
|         lexer_next(&lex, &token); | ||||
|         munit_assert_int(TOKEN_ERROR, ==, token.id); | ||||
|         munit_assert_size(128, ==, strlen(token.value)); | ||||
|         lexer_token_cleanup(&token); | ||||
|         lexer_close(&lex); | ||||
|     } | ||||
|  | ||||
|     // With suffix we fail at the suffix boundary | ||||
|     for (size_t i = 2; i < 4; ++i) { | ||||
|         auto number = numbers[i]; | ||||
|         munit_assert_size(129, ==, strlen(number)); | ||||
|         lexer_t lex = {}; | ||||
|         lexer_token_t token = {}; | ||||
|         lexer_setup_memory_test(&lex, number); | ||||
|         lexer_next(&lex, &token); | ||||
|         munit_assert_int(TOKEN_ERROR, ==, token.id); | ||||
|         munit_assert_size(128, >=, strlen(token.value)); | ||||
|         lexer_token_cleanup(&token); | ||||
|  | ||||
|         lexer_expect_one_token(&lex, TOKEN_COLON, ":", 0, 126); | ||||
|         lexer_expect_one_token(&lex, TOKEN_DECIMAL, "64", 0, 127); | ||||
|         lexer_close(&lex); | ||||
|     } | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_max_whitespace_length(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     char whitespace[1025]; | ||||
|     memset(whitespace, ' ', 1024); | ||||
|     whitespace[1024] = '\0'; | ||||
|  | ||||
|     munit_assert_size(1024, ==, strlen(whitespace)); | ||||
|     lexer_t lex = {}; | ||||
|     lexer_token_t token = {}; | ||||
|     lexer_setup_memory_test(&lex, whitespace); | ||||
|     lexer_next(&lex, &token); | ||||
|     munit_assert_int(TOKEN_WHITESPACE, ==, token.id); | ||||
|     munit_assert_size(1024, ==, strlen(token.value)); | ||||
|     lexer_token_cleanup(&token); | ||||
|     lexer_close(&lex); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitResult test_lexer_too_long_whitespace(const MunitParameter params[], void *data) { | ||||
|     (void)params; | ||||
|     (void)data; | ||||
|  | ||||
|     char whitespace[1026]; | ||||
|     memset(whitespace, ' ', 1025); | ||||
|     whitespace[1025] = '\0'; | ||||
|  | ||||
|     munit_assert_size(1025, ==, strlen(whitespace)); | ||||
|     lexer_t lex = {}; | ||||
|     lexer_token_t token = {}; | ||||
|     lexer_setup_memory_test(&lex, whitespace); | ||||
|     lexer_next(&lex, &token); | ||||
|     munit_assert_int(TOKEN_ERROR, ==, token.id); | ||||
|     munit_assert_size(1024, ==, strlen(token.value)); | ||||
|     lexer_token_cleanup(&token); | ||||
|  | ||||
|     lexer_expect_one_token(&lex, TOKEN_WHITESPACE, " ", 0, 1024); | ||||
|     lexer_close(&lex); | ||||
|  | ||||
|     return MUNIT_OK; | ||||
| } | ||||
|  | ||||
| MunitTest lexer_tests[] = { | ||||
|     {"/identifier",              test_lexer_identifier,              nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/identifier_boundary",     test_lexer_identifier_boundary,     nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/decimal",                 test_lexer_decimal,                 nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/decimal_boundary",        test_lexer_decimal_boundary,        nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/hexadecimal",             test_lexer_hexadecimal,             nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/hexadecimal_with_suffix", test_lexer_hexadecimal_with_suffix, nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/hexadecimal_boundary",    test_lexer_hexadecimal_boundary,    nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/octal",                   test_lexer_octal,                   nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/octal_with_suffix",       test_lexer_octal_with_suffix,       nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/octal_boundary",          test_lexer_octal_boundary,          nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/binary",                  test_lexer_binary,                  nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/binary_with_suffix",      test_lexer_binary_with_suffix,      nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/binary_boundary",         test_lexer_binary_boundary,         nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/number_boundary",         test_lexer_number_boundary,         nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/colon",                   test_lexer_colon,                   nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/colon_boundary",          test_lexer_colon_boundary,          nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/comma",                   test_lexer_comma,                   nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/comma_boundary",          test_lexer_comma_boundary,          nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/lbracket",                test_lexer_lbracket,                nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/lbracket_boundary",       test_lexer_lbracket_boundary,       nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/rbracket",                test_lexer_rbracket,                nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/rbracket_boundary",       test_lexer_rbracket_boundary,       nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/plus",                    test_lexer_plus,                    nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/plus_boundary",           test_lexer_plus_boundary,           nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/minus",                   test_lexer_minus,                   nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/minus_boundary",          test_lexer_minus_boundary,          nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/asterisk",                test_lexer_asterisk,                nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/asterisk_boundary",       test_lexer_asterisk_boundary,       nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/dot",                     test_lexer_dot,                     nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/dot_boundary",            test_lexer_dot_boundary,            nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/comment",                 test_lexer_comment,                 nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/comment_boundary",        test_lexer_comment_boundary,        nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/whitespace",              test_lexer_whitespace,              nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/whitespace_boundary",     test_lexer_whitespace_boundary,     nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/newlines",                test_lexer_newlines,                nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/newline_boundary",        test_lexer_newline_boundary,        nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/crlf_boundary",           test_lexer_crlf_boundary,           nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/line_numbers",            test_lexer_line_numbers,            nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/maximum_length_numbers",  test_lexer_maximum_length_numbers,  nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/too_long_numbers",        test_lexer_too_long_numbers,        nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/max_whitespace_length",   test_lexer_max_whitespace_length,   nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {"/too_long_whitespace",     test_lexer_too_long_whitespace,     nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr}, | ||||
|     {nullptr,                    nullptr,                            nullptr, nullptr, MUNIT_TEST_OPTION_NONE, nullptr} | ||||
| }; | ||||
							
								
								
									
										16
									
								
								tests/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								tests/main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| #include "munit.h" | ||||
|  | ||||
| extern MunitTest ast_tests[]; | ||||
| extern MunitTest lexer_tests[]; | ||||
|  | ||||
| int main(int argc, char *argv[MUNIT_ARRAY_PARAM(argc + 1)]) { | ||||
|     MunitSuite suites[] = { | ||||
|         {"/ast",   ast_tests,   nullptr, 1, MUNIT_SUITE_OPTION_NONE}, | ||||
|         {"/lexer", lexer_tests, nullptr, 1, MUNIT_SUITE_OPTION_NONE}, | ||||
|         {nullptr,  nullptr,     nullptr, 0, MUNIT_SUITE_OPTION_NONE}, | ||||
|     }; | ||||
|  | ||||
|     MunitSuite master_suite = {"/oas", nullptr, suites, 1, MUNIT_SUITE_OPTION_NONE}; | ||||
|  | ||||
|     return munit_suite_main(&master_suite, nullptr, argc, argv); | ||||
| } | ||||
							
								
								
									
										2055
									
								
								tests/munit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2055
									
								
								tests/munit.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										535
									
								
								tests/munit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										535
									
								
								tests/munit.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,535 @@ | ||||
| /* µnit Testing Framework | ||||
|  * Copyright (c) 2013-2017 Evan Nemerson <evan@nemerson.com> | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person | ||||
|  * obtaining a copy of this software and associated documentation | ||||
|  * files (the "Software"), to deal in the Software without | ||||
|  * restriction, including without limitation the rights to use, copy, | ||||
|  * modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
|  * of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||||
|  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
|  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||||
|  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #if !defined(MUNIT_H) | ||||
| #define MUNIT_H | ||||
|  | ||||
| #include <stdarg.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #define MUNIT_VERSION(major, minor, revision) \ | ||||
|   (((major) << 16) | ((minor) << 8) | (revision)) | ||||
|  | ||||
| #define MUNIT_CURRENT_VERSION MUNIT_VERSION(0, 4, 1) | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER < 1600) | ||||
| #  define munit_int8_t   __int8 | ||||
| #  define munit_uint8_t  unsigned __int8 | ||||
| #  define munit_int16_t  __int16 | ||||
| #  define munit_uint16_t unsigned __int16 | ||||
| #  define munit_int32_t  __int32 | ||||
| #  define munit_uint32_t unsigned __int32 | ||||
| #  define munit_int64_t  __int64 | ||||
| #  define munit_uint64_t unsigned __int64 | ||||
| #else | ||||
| #  include <stdint.h> | ||||
| #  define munit_int8_t   int8_t | ||||
| #  define munit_uint8_t  uint8_t | ||||
| #  define munit_int16_t  int16_t | ||||
| #  define munit_uint16_t uint16_t | ||||
| #  define munit_int32_t  int32_t | ||||
| #  define munit_uint32_t uint32_t | ||||
| #  define munit_int64_t  int64_t | ||||
| #  define munit_uint64_t uint64_t | ||||
| #endif | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER < 1800) | ||||
| #  if !defined(PRIi8) | ||||
| #    define PRIi8 "i" | ||||
| #  endif | ||||
| #  if !defined(PRIi16) | ||||
| #    define PRIi16 "i" | ||||
| #  endif | ||||
| #  if !defined(PRIi32) | ||||
| #    define PRIi32 "i" | ||||
| #  endif | ||||
| #  if !defined(PRIi64) | ||||
| #    define PRIi64 "I64i" | ||||
| #  endif | ||||
| #  if !defined(PRId8) | ||||
| #    define PRId8 "d" | ||||
| #  endif | ||||
| #  if !defined(PRId16) | ||||
| #    define PRId16 "d" | ||||
| #  endif | ||||
| #  if !defined(PRId32) | ||||
| #    define PRId32 "d" | ||||
| #  endif | ||||
| #  if !defined(PRId64) | ||||
| #    define PRId64 "I64d" | ||||
| #  endif | ||||
| #  if !defined(PRIx8) | ||||
| #    define PRIx8 "x" | ||||
| #  endif | ||||
| #  if !defined(PRIx16) | ||||
| #    define PRIx16 "x" | ||||
| #  endif | ||||
| #  if !defined(PRIx32) | ||||
| #    define PRIx32 "x" | ||||
| #  endif | ||||
| #  if !defined(PRIx64) | ||||
| #    define PRIx64 "I64x" | ||||
| #  endif | ||||
| #  if !defined(PRIu8) | ||||
| #    define PRIu8 "u" | ||||
| #  endif | ||||
| #  if !defined(PRIu16) | ||||
| #    define PRIu16 "u" | ||||
| #  endif | ||||
| #  if !defined(PRIu32) | ||||
| #    define PRIu32 "u" | ||||
| #  endif | ||||
| #  if !defined(PRIu64) | ||||
| #    define PRIu64 "I64u" | ||||
| #  endif | ||||
| #else | ||||
| #  include <inttypes.h> | ||||
| #endif | ||||
|  | ||||
| #if !defined(munit_bool) | ||||
| #  if defined(bool) | ||||
| #    define munit_bool bool | ||||
| #  elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) | ||||
| #    define munit_bool _Bool | ||||
| #  else | ||||
| #    define munit_bool int | ||||
| #  endif | ||||
| #endif | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| #  define MUNIT_LIKELY(expr) (__builtin_expect ((expr), 1)) | ||||
| #  define MUNIT_UNLIKELY(expr) (__builtin_expect ((expr), 0)) | ||||
| #  define MUNIT_UNUSED __attribute__((__unused__)) | ||||
| #else | ||||
| #  define MUNIT_LIKELY(expr) (expr) | ||||
| #  define MUNIT_UNLIKELY(expr) (expr) | ||||
| #  define MUNIT_UNUSED | ||||
| #endif | ||||
|  | ||||
| #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__PGI) | ||||
| #  define MUNIT_ARRAY_PARAM(name) name | ||||
| #else | ||||
| #  define MUNIT_ARRAY_PARAM(name) | ||||
| #endif | ||||
|  | ||||
| #if !defined(_WIN32) | ||||
| #  define MUNIT_SIZE_MODIFIER "z" | ||||
| #  define MUNIT_CHAR_MODIFIER "hh" | ||||
| #  define MUNIT_SHORT_MODIFIER "h" | ||||
| #else | ||||
| #  if defined(_M_X64) || defined(__amd64__) | ||||
| #    define MUNIT_SIZE_MODIFIER "I64" | ||||
| #  else | ||||
| #    define MUNIT_SIZE_MODIFIER "" | ||||
| #  endif | ||||
| #  define MUNIT_CHAR_MODIFIER "" | ||||
| #  define MUNIT_SHORT_MODIFIER "" | ||||
| #endif | ||||
|  | ||||
| #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L | ||||
| #  define MUNIT_NO_RETURN _Noreturn | ||||
| #elif defined(__GNUC__) | ||||
| #  define MUNIT_NO_RETURN __attribute__((__noreturn__)) | ||||
| #elif defined(_MSC_VER) | ||||
| #  define MUNIT_NO_RETURN __declspec(noreturn) | ||||
| #else | ||||
| #  define MUNIT_NO_RETURN | ||||
| #endif | ||||
|  | ||||
| #if defined(_MSC_VER) &&  (_MSC_VER >= 1500) | ||||
| #  define MUNIT_PUSH_DISABLE_MSVC_C4127_ __pragma(warning(push)) __pragma(warning(disable:4127)) | ||||
| #  define MUNIT_POP_DISABLE_MSVC_C4127_ __pragma(warning(pop)) | ||||
| #else | ||||
| #  define MUNIT_PUSH_DISABLE_MSVC_C4127_ | ||||
| #  define MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
| #endif | ||||
|  | ||||
| typedef enum { | ||||
|   MUNIT_LOG_DEBUG, | ||||
|   MUNIT_LOG_INFO, | ||||
|   MUNIT_LOG_WARNING, | ||||
|   MUNIT_LOG_ERROR | ||||
| } MunitLogLevel; | ||||
|  | ||||
| #if defined(__GNUC__) && !defined(__MINGW32__) | ||||
| #  define MUNIT_PRINTF(string_index, first_to_check) __attribute__((format (printf, string_index, first_to_check))) | ||||
| #else | ||||
| #  define MUNIT_PRINTF(string_index, first_to_check) | ||||
| #endif | ||||
|  | ||||
| MUNIT_PRINTF(4, 5) | ||||
| void munit_logf_ex(MunitLogLevel level, const char* filename, int line, const char* format, ...); | ||||
|  | ||||
| #define munit_logf(level, format, ...) \ | ||||
|   munit_logf_ex(level, __FILE__, __LINE__, format, __VA_ARGS__) | ||||
|  | ||||
| #define munit_log(level, msg) \ | ||||
|   munit_logf(level, "%s", msg) | ||||
|  | ||||
| MUNIT_NO_RETURN | ||||
| MUNIT_PRINTF(3, 4) | ||||
| void munit_errorf_ex(const char* filename, int line, const char* format, ...); | ||||
|  | ||||
| #define munit_errorf(format, ...) \ | ||||
|   munit_errorf_ex(__FILE__, __LINE__, format, __VA_ARGS__) | ||||
|  | ||||
| #define munit_error(msg) \ | ||||
|   munit_errorf("%s", msg) | ||||
|  | ||||
| #define munit_assert(expr) \ | ||||
|   do { \ | ||||
|     if (!MUNIT_LIKELY(expr)) { \ | ||||
|       munit_error("assertion failed: " #expr); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_true(expr) \ | ||||
|   do { \ | ||||
|     if (!MUNIT_LIKELY(expr)) { \ | ||||
|       munit_error("assertion failed: " #expr " is not true"); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_false(expr) \ | ||||
|   do { \ | ||||
|     if (!MUNIT_LIKELY(!(expr))) { \ | ||||
|       munit_error("assertion failed: " #expr " is not false"); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_type_full(prefix, suffix, T, fmt, a, op, b)   \ | ||||
|   do { \ | ||||
|     T munit_tmp_a_ = (a); \ | ||||
|     T munit_tmp_b_ = (b); \ | ||||
|     if (!(munit_tmp_a_ op munit_tmp_b_)) {                               \ | ||||
|       munit_errorf("assertion failed: %s %s %s (" prefix "%" fmt suffix " %s " prefix "%" fmt suffix ")", \ | ||||
|                    #a, #op, #b, munit_tmp_a_, #op, munit_tmp_b_); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_type(T, fmt, a, op, b) \ | ||||
|   munit_assert_type_full("", "", T, fmt, a, op, b) | ||||
|  | ||||
| #define munit_assert_char(a, op, b) \ | ||||
|   munit_assert_type_full("'\\x", "'", char, "02" MUNIT_CHAR_MODIFIER "x", a, op, b) | ||||
| #define munit_assert_uchar(a, op, b) \ | ||||
|   munit_assert_type_full("'\\x", "'", unsigned char, "02" MUNIT_CHAR_MODIFIER "x", a, op, b) | ||||
| #define munit_assert_short(a, op, b) \ | ||||
|   munit_assert_type(short, MUNIT_SHORT_MODIFIER "d", a, op, b) | ||||
| #define munit_assert_ushort(a, op, b) \ | ||||
|   munit_assert_type(unsigned short, MUNIT_SHORT_MODIFIER "u", a, op, b) | ||||
| #define munit_assert_int(a, op, b) \ | ||||
|   munit_assert_type(int, "d", a, op, b) | ||||
| #define munit_assert_uint(a, op, b) \ | ||||
|   munit_assert_type(unsigned int, "u", a, op, b) | ||||
| #define munit_assert_long(a, op, b) \ | ||||
|   munit_assert_type(long int, "ld", a, op, b) | ||||
| #define munit_assert_ulong(a, op, b) \ | ||||
|   munit_assert_type(unsigned long int, "lu", a, op, b) | ||||
| #define munit_assert_llong(a, op, b) \ | ||||
|   munit_assert_type(long long int, "lld", a, op, b) | ||||
| #define munit_assert_ullong(a, op, b) \ | ||||
|   munit_assert_type(unsigned long long int, "llu", a, op, b) | ||||
|  | ||||
| #define munit_assert_size(a, op, b) \ | ||||
|   munit_assert_type(size_t, MUNIT_SIZE_MODIFIER "u", a, op, b) | ||||
|  | ||||
| #define munit_assert_float(a, op, b) \ | ||||
|   munit_assert_type(float, "f", a, op, b) | ||||
| #define munit_assert_double(a, op, b) \ | ||||
|   munit_assert_type(double, "g", a, op, b) | ||||
| #define munit_assert_ptr(a, op, b) \ | ||||
|   munit_assert_type(const void*, "p", a, op, b) | ||||
|  | ||||
| #define munit_assert_int8(a, op, b)             \ | ||||
|   munit_assert_type(munit_int8_t, PRIi8, a, op, b) | ||||
| #define munit_assert_uint8(a, op, b) \ | ||||
|   munit_assert_type(munit_uint8_t, PRIu8, a, op, b) | ||||
| #define munit_assert_int16(a, op, b) \ | ||||
|   munit_assert_type(munit_int16_t, PRIi16, a, op, b) | ||||
| #define munit_assert_uint16(a, op, b) \ | ||||
|   munit_assert_type(munit_uint16_t, PRIu16, a, op, b) | ||||
| #define munit_assert_int32(a, op, b) \ | ||||
|   munit_assert_type(munit_int32_t, PRIi32, a, op, b) | ||||
| #define munit_assert_uint32(a, op, b) \ | ||||
|   munit_assert_type(munit_uint32_t, PRIu32, a, op, b) | ||||
| #define munit_assert_int64(a, op, b) \ | ||||
|   munit_assert_type(munit_int64_t, PRIi64, a, op, b) | ||||
| #define munit_assert_uint64(a, op, b) \ | ||||
|   munit_assert_type(munit_uint64_t, PRIu64, a, op, b) | ||||
|  | ||||
| #define munit_assert_double_equal(a, b, precision) \ | ||||
|   do { \ | ||||
|     const double munit_tmp_a_ = (a); \ | ||||
|     const double munit_tmp_b_ = (b); \ | ||||
|     const double munit_tmp_diff_ = ((munit_tmp_a_ - munit_tmp_b_) < 0) ? \ | ||||
|       -(munit_tmp_a_ - munit_tmp_b_) : \ | ||||
|       (munit_tmp_a_ - munit_tmp_b_); \ | ||||
|     if (MUNIT_UNLIKELY(munit_tmp_diff_ > 1e-##precision)) { \ | ||||
|       munit_errorf("assertion failed: %s == %s (%0." #precision "g == %0." #precision "g)", \ | ||||
| 		   #a, #b, munit_tmp_a_, munit_tmp_b_); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #include <string.h> | ||||
| #define munit_assert_string_equal(a, b) \ | ||||
|   do { \ | ||||
|     const char* munit_tmp_a_ = a; \ | ||||
|     const char* munit_tmp_b_ = b; \ | ||||
|     if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) != 0)) { \ | ||||
|       munit_errorf("assertion failed: string %s == %s (\"%s\" == \"%s\")", \ | ||||
|                    #a, #b, munit_tmp_a_, munit_tmp_b_); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_string_not_equal(a, b) \ | ||||
|   do { \ | ||||
|     const char* munit_tmp_a_ = a; \ | ||||
|     const char* munit_tmp_b_ = b; \ | ||||
|     if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) == 0)) { \ | ||||
|       munit_errorf("assertion failed: string %s != %s (\"%s\" == \"%s\")", \ | ||||
|                    #a, #b, munit_tmp_a_, munit_tmp_b_); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_memory_equal(size, a, b) \ | ||||
|   do { \ | ||||
|     const unsigned char* munit_tmp_a_ = (const unsigned char*) (a); \ | ||||
|     const unsigned char* munit_tmp_b_ = (const unsigned char*) (b); \ | ||||
|     const size_t munit_tmp_size_ = (size); \ | ||||
|     if (MUNIT_UNLIKELY(memcmp(munit_tmp_a_, munit_tmp_b_, munit_tmp_size_)) != 0) { \ | ||||
|       size_t munit_tmp_pos_; \ | ||||
|       for (munit_tmp_pos_ = 0 ; munit_tmp_pos_ < munit_tmp_size_ ; munit_tmp_pos_++) { \ | ||||
|         if (munit_tmp_a_[munit_tmp_pos_] != munit_tmp_b_[munit_tmp_pos_]) { \ | ||||
|           munit_errorf("assertion failed: memory %s == %s, at offset %" MUNIT_SIZE_MODIFIER "u", \ | ||||
|                        #a, #b, munit_tmp_pos_); \ | ||||
|           break; \ | ||||
|         } \ | ||||
|       } \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_memory_not_equal(size, a, b) \ | ||||
|   do { \ | ||||
|     const unsigned char* munit_tmp_a_ = (const unsigned char*) (a); \ | ||||
|     const unsigned char* munit_tmp_b_ = (const unsigned char*) (b); \ | ||||
|     const size_t munit_tmp_size_ = (size); \ | ||||
|     if (MUNIT_UNLIKELY(memcmp(munit_tmp_a_, munit_tmp_b_, munit_tmp_size_)) == 0) { \ | ||||
|       munit_errorf("assertion failed: memory %s != %s (%zu bytes)", \ | ||||
|                    #a, #b, munit_tmp_size_); \ | ||||
|     } \ | ||||
|     MUNIT_PUSH_DISABLE_MSVC_C4127_ \ | ||||
|   } while (0) \ | ||||
|   MUNIT_POP_DISABLE_MSVC_C4127_ | ||||
|  | ||||
| #define munit_assert_ptr_equal(a, b) \ | ||||
|   munit_assert_ptr(a, ==, b) | ||||
| #define munit_assert_ptr_not_equal(a, b) \ | ||||
|   munit_assert_ptr(a, !=, b) | ||||
| #define munit_assert_null(ptr) \ | ||||
|   munit_assert_ptr(ptr, ==, NULL) | ||||
| #define munit_assert_not_null(ptr) \ | ||||
|   munit_assert_ptr(ptr, !=, NULL) | ||||
| #define munit_assert_ptr_null(ptr) \ | ||||
|   munit_assert_ptr(ptr, ==, NULL) | ||||
| #define munit_assert_ptr_not_null(ptr) \ | ||||
|   munit_assert_ptr(ptr, !=, NULL) | ||||
|  | ||||
| /*** Memory allocation ***/ | ||||
|  | ||||
| void* munit_malloc_ex(const char* filename, int line, size_t size); | ||||
|  | ||||
| #define munit_malloc(size) \ | ||||
|   munit_malloc_ex(__FILE__, __LINE__, (size)) | ||||
|  | ||||
| #define munit_new(type) \ | ||||
|   ((type*) munit_malloc(sizeof(type))) | ||||
|  | ||||
| #define munit_calloc(nmemb, size) \ | ||||
|   munit_malloc((nmemb) * (size)) | ||||
|  | ||||
| #define munit_newa(type, nmemb) \ | ||||
|   ((type*) munit_calloc((nmemb), sizeof(type))) | ||||
|  | ||||
| /*** Random number generation ***/ | ||||
|  | ||||
| void munit_rand_seed(munit_uint32_t seed); | ||||
| munit_uint32_t munit_rand_uint32(void); | ||||
| int munit_rand_int_range(int min, int max); | ||||
| double munit_rand_double(void); | ||||
| void munit_rand_memory(size_t size, munit_uint8_t buffer[MUNIT_ARRAY_PARAM(size)]); | ||||
|  | ||||
| /*** Tests and Suites ***/ | ||||
|  | ||||
| typedef enum { | ||||
|   /* Test successful */ | ||||
|   MUNIT_OK, | ||||
|   /* Test failed */ | ||||
|   MUNIT_FAIL, | ||||
|   /* Test was skipped */ | ||||
|   MUNIT_SKIP, | ||||
|   /* Test failed due to circumstances not intended to be tested | ||||
|    * (things like network errors, invalid parameter value, failure to | ||||
|    * allocate memory in the test harness, etc.). */ | ||||
|   MUNIT_ERROR | ||||
| } MunitResult; | ||||
|  | ||||
| typedef struct { | ||||
|   char*  name; | ||||
|   char** values; | ||||
| } MunitParameterEnum; | ||||
|  | ||||
| typedef struct { | ||||
|   char* name; | ||||
|   char* value; | ||||
| } MunitParameter; | ||||
|  | ||||
| const char* munit_parameters_get(const MunitParameter params[], const char* key); | ||||
|  | ||||
| typedef enum { | ||||
|   MUNIT_TEST_OPTION_NONE             = 0, | ||||
|   MUNIT_TEST_OPTION_SINGLE_ITERATION = 1 << 0, | ||||
|   MUNIT_TEST_OPTION_TODO             = 1 << 1 | ||||
| } MunitTestOptions; | ||||
|  | ||||
| typedef MunitResult (* MunitTestFunc)(const MunitParameter params[], void* user_data_or_fixture); | ||||
| typedef void*       (* MunitTestSetup)(const MunitParameter params[], void* user_data); | ||||
| typedef void        (* MunitTestTearDown)(void* fixture); | ||||
|  | ||||
| typedef struct { | ||||
|   char*               name; | ||||
|   MunitTestFunc       test; | ||||
|   MunitTestSetup      setup; | ||||
|   MunitTestTearDown   tear_down; | ||||
|   MunitTestOptions    options; | ||||
|   MunitParameterEnum* parameters; | ||||
| } MunitTest; | ||||
|  | ||||
| typedef enum { | ||||
|   MUNIT_SUITE_OPTION_NONE = 0 | ||||
| } MunitSuiteOptions; | ||||
|  | ||||
| typedef struct MunitSuite_ MunitSuite; | ||||
|  | ||||
| struct MunitSuite_ { | ||||
|   char*             prefix; | ||||
|   MunitTest*        tests; | ||||
|   MunitSuite*       suites; | ||||
|   unsigned int      iterations; | ||||
|   MunitSuiteOptions options; | ||||
| }; | ||||
|  | ||||
| int munit_suite_main(const MunitSuite* suite, void* user_data, int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]); | ||||
|  | ||||
| /* Note: I'm not very happy with this API; it's likely to change if I | ||||
|  * figure out something better.  Suggestions welcome. */ | ||||
|  | ||||
| typedef struct MunitArgument_ MunitArgument; | ||||
|  | ||||
| struct MunitArgument_ { | ||||
|   char* name; | ||||
|   munit_bool (* parse_argument)(const MunitSuite* suite, void* user_data, int* arg, int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]); | ||||
|   void (* write_help)(const MunitArgument* argument, void* user_data); | ||||
| }; | ||||
|  | ||||
| int munit_suite_main_custom(const MunitSuite* suite, | ||||
|                             void* user_data, | ||||
|                             int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)], | ||||
|                             const MunitArgument arguments[]); | ||||
|  | ||||
| #if defined(MUNIT_ENABLE_ASSERT_ALIASES) | ||||
|  | ||||
| #define assert_true(expr) munit_assert_true(expr) | ||||
| #define assert_false(expr) munit_assert_false(expr) | ||||
| #define assert_char(a, op, b) munit_assert_char(a, op, b) | ||||
| #define assert_uchar(a, op, b) munit_assert_uchar(a, op, b) | ||||
| #define assert_short(a, op, b) munit_assert_short(a, op, b) | ||||
| #define assert_ushort(a, op, b) munit_assert_ushort(a, op, b) | ||||
| #define assert_int(a, op, b) munit_assert_int(a, op, b) | ||||
| #define assert_uint(a, op, b) munit_assert_uint(a, op, b) | ||||
| #define assert_long(a, op, b) munit_assert_long(a, op, b) | ||||
| #define assert_ulong(a, op, b) munit_assert_ulong(a, op, b) | ||||
| #define assert_llong(a, op, b) munit_assert_llong(a, op, b) | ||||
| #define assert_ullong(a, op, b) munit_assert_ullong(a, op, b) | ||||
| #define assert_size(a, op, b) munit_assert_size(a, op, b) | ||||
| #define assert_float(a, op, b) munit_assert_float(a, op, b) | ||||
| #define assert_double(a, op, b) munit_assert_double(a, op, b) | ||||
| #define assert_ptr(a, op, b) munit_assert_ptr(a, op, b) | ||||
|  | ||||
| #define assert_int8(a, op, b) munit_assert_int8(a, op, b) | ||||
| #define assert_uint8(a, op, b) munit_assert_uint8(a, op, b) | ||||
| #define assert_int16(a, op, b) munit_assert_int16(a, op, b) | ||||
| #define assert_uint16(a, op, b) munit_assert_uint16(a, op, b) | ||||
| #define assert_int32(a, op, b) munit_assert_int32(a, op, b) | ||||
| #define assert_uint32(a, op, b) munit_assert_uint32(a, op, b) | ||||
| #define assert_int64(a, op, b) munit_assert_int64(a, op, b) | ||||
| #define assert_uint64(a, op, b) munit_assert_uint64(a, op, b) | ||||
|  | ||||
| #define assert_double_equal(a, b, precision) munit_assert_double_equal(a, b, precision) | ||||
| #define assert_string_equal(a, b) munit_assert_string_equal(a, b) | ||||
| #define assert_string_not_equal(a, b) munit_assert_string_not_equal(a, b) | ||||
| #define assert_memory_equal(size, a, b) munit_assert_memory_equal(size, a, b) | ||||
| #define assert_memory_not_equal(size, a, b) munit_assert_memory_not_equal(size, a, b) | ||||
| #define assert_ptr_equal(a, b) munit_assert_ptr_equal(a, b) | ||||
| #define assert_ptr_not_equal(a, b) munit_assert_ptr_not_equal(a, b) | ||||
| #define assert_ptr_null(ptr) munit_assert_null_equal(ptr) | ||||
| #define assert_ptr_not_null(ptr) munit_assert_not_null(ptr) | ||||
|  | ||||
| #define assert_null(ptr) munit_assert_null(ptr) | ||||
| #define assert_not_null(ptr) munit_assert_not_null(ptr) | ||||
|  | ||||
| #endif /* defined(MUNIT_ENABLE_ASSERT_ALIASES) */ | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* !defined(MUNIT_H) */ | ||||
|  | ||||
| #if defined(MUNIT_ENABLE_ASSERT_ALIASES) | ||||
| #  if defined(assert) | ||||
| #    undef assert | ||||
| #  endif | ||||
| #  define assert(expr) munit_assert(expr) | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user