Consolidated test conditions
This commit is contained in:
parent
f6ef0c1cee
commit
2810a9eb14
|
|
@ -19,7 +19,7 @@ typedef struct {
|
||||||
LexerInfo lexer_info;
|
LexerInfo lexer_info;
|
||||||
} LexerTest;
|
} LexerTest;
|
||||||
|
|
||||||
const char *TOKEN_TYPES[] = {
|
const char *TOKEN_TYPES_NAMES[] = {
|
||||||
"End of File",
|
"End of File",
|
||||||
"Identifier",
|
"Identifier",
|
||||||
"Integer",
|
"Integer",
|
||||||
|
|
@ -32,6 +32,17 @@ const char *TOKEN_TYPES[] = {
|
||||||
"Type Tuple",
|
"Type Tuple",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *INTEGER_TYPES_NAMES[] = {
|
||||||
|
"i64",
|
||||||
|
"i32",
|
||||||
|
"i16",
|
||||||
|
"i8",
|
||||||
|
"u64",
|
||||||
|
"u32",
|
||||||
|
"u16",
|
||||||
|
"u8",
|
||||||
|
};
|
||||||
|
|
||||||
// Test start and end helpers
|
// Test start and end helpers
|
||||||
|
|
||||||
static LexerTest start_up_test(const char *test_name, const char *test_code) {
|
static LexerTest start_up_test(const char *test_name, const char *test_code) {
|
||||||
|
|
@ -47,30 +58,30 @@ static void clean_up_test(LexerResult result) {
|
||||||
clean_token_result(result.result);
|
clean_token_result(result.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestResult logic_fail_test(LexerTest test, LexerResult result, const char *message) {
|
static TestResult logic_fail_test(LexerTest *test, LexerResult result, const char *message) {
|
||||||
clean_up_test(result);
|
clean_up_test(result);
|
||||||
test.result.status = TEST_LOGIC_FAIL;
|
test->result.status = TEST_LOGIC_FAIL;
|
||||||
test.result.message = message;
|
test->result.message = message;
|
||||||
return test.result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestResult error_fail_test(LexerTest test, LexerResult result, SlsError error) {
|
static TestResult error_fail_test(LexerTest *test, LexerResult result, SlsError error) {
|
||||||
clean_up_test(result);
|
clean_up_test(result);
|
||||||
test.result.status = TEST_ERROR_FAIL;
|
test->result.status = TEST_ERROR_FAIL;
|
||||||
test.result.error = error;
|
test->result.error = error;
|
||||||
return test.result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestResult skip_test(LexerTest test, LexerResult result) {
|
static TestResult skip_test(LexerTest *test, LexerResult result) {
|
||||||
clean_up_test(result);
|
clean_up_test(result);
|
||||||
test.result.status = TEST_NOT_IMPLEMENTED;
|
test->result.status = TEST_NOT_IMPLEMENTED;
|
||||||
return test.result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestResult pass_test(LexerTest test, LexerResult result) {
|
static TestResult pass_test(LexerTest *test, LexerResult result) {
|
||||||
clean_up_test(result);
|
clean_up_test(result);
|
||||||
test.result.status = TEST_PASS;
|
test->result.status = TEST_PASS;
|
||||||
return test.result;
|
return test->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test messages
|
// Test messages
|
||||||
|
|
@ -83,9 +94,16 @@ static char *unexpected_end_of_token_stream(size_t i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *token_should_be(size_t i, TokenType should, TokenType found) {
|
static char *token_should_be(size_t i, TokenType should, TokenType found) {
|
||||||
size_t length = floor(log10(i + 1)) + strnlen(TOKEN_TYPES[should], 13) + strnlen(TOKEN_TYPES[found], 13) + 35;
|
size_t length = floor(log10(i + 1)) + strnlen(TOKEN_TYPES_NAMES[should], 13) + strnlen(TOKEN_TYPES_NAMES[found], 13) + 35;
|
||||||
char *string = malloc(sizeof(char) * length);
|
char *string = malloc(sizeof(char) * length);
|
||||||
snprintf(string, length, "Token #%d should be a %s, but found a %s", i, TOKEN_TYPES[should], TOKEN_TYPES[found]);
|
snprintf(string, length, "Token #%d should be a %s, but found a %s", i, TOKEN_TYPES_NAMES[should], TOKEN_TYPES_NAMES[found]);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *integer_type_should_be(size_t i, TokenType should, TokenType found) {
|
||||||
|
size_t length = floor(log10(i + 1)) + strnlen(INTEGER_TYPES_NAMES[should], 5) + strnlen(INTEGER_TYPES_NAMES[found], 5) + 48;
|
||||||
|
char *string = malloc(sizeof(char) * length);
|
||||||
|
snprintf(string, length, "Token #%d integer type should be a %s, but found a %s", i, TOKEN_TYPES_NAMES[should], TOKEN_TYPES_NAMES[found]);
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,24 +114,94 @@ static char *integer_value_should_be(size_t i, uint64_t should, uint64_t found)
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *identifier_should_be_literal(size_t i) {
|
||||||
|
size_t length = floor(log10(i + 1)) + 51;
|
||||||
|
char *string = malloc(sizeof(char) * length);
|
||||||
|
snprintf(string, length, "Token #%d identifier should be an identifier literal", i);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *identifier_should_not_be_literal(size_t i) {
|
||||||
|
size_t length = floor(log10(i + 1)) + 55;
|
||||||
|
char *string = malloc(sizeof(char) * length);
|
||||||
|
snprintf(string, length, "Token #%d identifier should not be an identifier literal", i);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *token_length_should_be(size_t i, TokenType type, uint64_t should, uint64_t found) {
|
||||||
|
size_t length = floor(log10(i + 1)) + strnlen(TOKEN_TYPES_NAMES[type], 13) + floor(log10(should + 1)) + floor(log10(found + 1)) + 47;
|
||||||
|
char *string = malloc(sizeof(char) * length);
|
||||||
|
snprintf(string, length, "Token #%d of type %s length should be %d, but found %d", i, TOKEN_TYPES_NAMES[type], should, found);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *token_name_should_be(size_t i, TokenType type, size_t length, const char *should, const char *found) {
|
||||||
|
size_t length = floor(log10(i + 1)) + strnlen(TOKEN_TYPES_NAMES[type], 13) + strnlen(should, length) + strnlen(found, length) + 45;
|
||||||
|
char *string = malloc(sizeof(char) * length);
|
||||||
|
snprintf(string, length, "Token #%d of type %s name should be %s, but found %s", i, TOKEN_TYPES_NAMES[type], should, found);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
// Test parts
|
// Test parts
|
||||||
|
|
||||||
static Boolean test_integer_value(LexerTest test, LexerResult result, size_t i, IntegerBuiltInType type, uint64_t value) {
|
static Boolean test_integer_value(LexerTest *test, LexerResult result, size_t i, IntegerBuiltInType type, uint64_t value) {
|
||||||
LexerTokenResult *head = get_token(result.result, i);
|
LexerTokenResult *head = get_token(result.result, i);
|
||||||
if (head == 0) {
|
if (head == 0) {
|
||||||
logic_fail_test(test, result, unexpected_end_of_token_stream(i));
|
logic_fail_test(test, result, unexpected_end_of_token_stream(i+1));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->type == SLS_ERROR) {
|
} if (head->type == SLS_ERROR) {
|
||||||
error_fail_test(test, result, result.error);
|
error_fail_test(test, result, result.error);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->result.type != TOKEN_INTEGER) {
|
} if (head->result.type != TOKEN_INTEGER) {
|
||||||
logic_fail_test(test, result, token_should_be(i, TOKEN_INTEGER, head->result.type));
|
logic_fail_test(test, result, token_should_be(i + 1, TOKEN_INTEGER, head->result.type));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->result.integer_literal.type != type) {
|
} if (head->result.integer_literal.type != type) {
|
||||||
logic_fail_test(test, result, "First integer type should be ");
|
logic_fail_test(test, result, integer_type_should_be(i + 1, type, head->result.integer_literal.type));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} if (head->result.integer_literal.value != value) {
|
} if (head->result.integer_literal.value != value) {
|
||||||
logic_fail_test(test, result, integer_value_should_be(i, value, head->result.integer_literal.value));
|
logic_fail_test(test, result, integer_value_should_be(i + 1, value, head->result.integer_literal.value));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Boolean test_identifier_value(LexerTest *test, LexerResult result, size_t i, Boolean is_literal, const char *name) {
|
||||||
|
LexerTokenResult *head = get_token(result.result, i);
|
||||||
|
if (head == 0) {
|
||||||
|
logic_fail_test(test, result, unexpected_end_of_token_stream(i+1));
|
||||||
|
return TRUE;
|
||||||
|
} if (head->type == SLS_ERROR) {
|
||||||
|
error_fail_test(test, result, result.error);
|
||||||
|
return TRUE;
|
||||||
|
} if (head->result.type != TOKEN_IDENTIFIER) {
|
||||||
|
logic_fail_test(test, result, token_should_be(i + 1, TOKEN_IDENTIFIER, head->result.type));
|
||||||
|
return TRUE;
|
||||||
|
} if (head->result.identifier.is_literal != is_literal) {
|
||||||
|
logic_fail_test(test, result, is_literal ? identifier_should_be_literal(i + 1) : identifier_should_not_be_literal(i+1));
|
||||||
|
return TRUE;
|
||||||
|
} if (head->result.identifier.length == strnlen(name)) {
|
||||||
|
logic_fail_test(test, result, token_length_should_be(i + 1, TOKEN_IDENTIFIER, strnlen(name), head->result.identifier.length));
|
||||||
|
return TRUE;
|
||||||
|
} if (strcmp(head->result.identifier.name, "+") != 0) {
|
||||||
|
logic_fail_test(test, result, token_length_should_be(i + 1, TOKEN_IDENTIFIER, strnlen(name), head->result.identifier.length));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Boolean test_eof_value(LexerTest *test, LexerResult result, size_t i) {
|
||||||
|
LexerTokenResult *head = get_token(result.result, i);
|
||||||
|
if (head == 0) {
|
||||||
|
logic_fail_test(test, result, unexpected_end_of_token_stream(i+1));
|
||||||
|
return TRUE;
|
||||||
|
} if (head->type == SLS_ERROR) {
|
||||||
|
error_fail_test(test, result, result.error);
|
||||||
|
return TRUE;
|
||||||
|
} if (head->result.type != TOKEN_EOF) {
|
||||||
|
logic_fail_test(test, result, token_should_be(i + 1, TOKEN_EOF, head->result.type));
|
||||||
|
return TRUE;
|
||||||
|
} if (head->next != 0) {
|
||||||
|
logic_fail_test(test, result, "Expected end of token stream (more tokens found)");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
@ -127,58 +215,19 @@ static TestResult test_add_statement() {
|
||||||
LexerResult result = lexical_analysis(&test.lexer_info);
|
LexerResult result = lexical_analysis(&test.lexer_info);
|
||||||
|
|
||||||
if (result.type == SLS_ERROR)
|
if (result.type == SLS_ERROR)
|
||||||
return error_fail_test(test, result, result.error);
|
return error_fail_test(&test, result, result.error);
|
||||||
|
|
||||||
LexerTokenResult *head = result.result;
|
LexerTokenResult *head = result.result;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
if (head == 0)
|
if (test_integer_value(&test, result, i, INTEGER_I64, 3)) return test.result;
|
||||||
return logic_fail_test(test, result, "Unexpected end of token stream (0 tokens found)");
|
i++;
|
||||||
if (head->type == SLS_ERROR)
|
if (test_integer_value(&test, result, i, INTEGER_I64, 4)) return test.result;
|
||||||
return error_fail_test(test, result, result.error);
|
i++;
|
||||||
if (head->result.type != TOKEN_INTEGER)
|
if (test_identifier_value(&test, result, i, FALSE, "+")) return test.result;
|
||||||
return logic_fail_test(test, result, "First token should be an integer");
|
i++;
|
||||||
if (head->result.integer_literal.type != INTEGER_I64)
|
if (test_eof_value(&test, result, i)) return test.result;
|
||||||
return logic_fail_test(test, result, "First integer type should be i64");
|
return pass_test(&test, result);
|
||||||
if (head->result.integer_literal.value != 3)
|
|
||||||
return logic_fail_test(test, result, "First integer value should be 3");
|
|
||||||
|
|
||||||
head = head->next;
|
|
||||||
if (head == 0)
|
|
||||||
return logic_fail_test(test, result, "Unexpected end of token stream (1 token found)");
|
|
||||||
if (head->type == SLS_ERROR)
|
|
||||||
return error_fail_test(test, result, result.error);
|
|
||||||
if (head->result.type != TOKEN_INTEGER)
|
|
||||||
return logic_fail_test(test, result, "Second token should be an integer");
|
|
||||||
if (head->result.integer_literal.type != INTEGER_I64)
|
|
||||||
return logic_fail_test(test, result, "Second integer type should be `i64`");
|
|
||||||
if (head->result.integer_literal.value != 4)
|
|
||||||
return logic_fail_test(test, result, "Second integer value should be `4`");
|
|
||||||
|
|
||||||
head = head->next;
|
|
||||||
if (head == 0)
|
|
||||||
return logic_fail_test(test, result, "Unexpected end of token stream (2 tokens found)");
|
|
||||||
if (head->type == SLS_ERROR)
|
|
||||||
return error_fail_test(test, result, result.error);
|
|
||||||
if (head->result.type != TOKEN_IDENTIFIER)
|
|
||||||
return logic_fail_test(test, result, "Third token should be an identifier");
|
|
||||||
if (head->result.identifier.is_literal == TRUE)
|
|
||||||
return logic_fail_test(test, result, "Identifier should not be a literal identifier");
|
|
||||||
if (head->result.identifier.length == 1)
|
|
||||||
return logic_fail_test(test, result, "Identifier length should be `1`");
|
|
||||||
if (strcmp(head->result.identifier.name, "+") != 0)
|
|
||||||
return logic_fail_test(test, result, "Identifier name should be `+`");
|
|
||||||
|
|
||||||
head = head->next;
|
|
||||||
if (head == 0)
|
|
||||||
return logic_fail_test(test, result, "Unexpected end of token stream (3 tokens found)");
|
|
||||||
if (head->type == SLS_ERROR)
|
|
||||||
return error_fail_test(test, result, result.error);
|
|
||||||
if (head->result.type != TOKEN_EOF)
|
|
||||||
return logic_fail_test(test, result, "Fourth token should be EOF");
|
|
||||||
if (head->next == 0)
|
|
||||||
return logic_fail_test(test, result, "Expected end of token stream (more tokens found)");
|
|
||||||
|
|
||||||
return pass_test(test, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TestsReport run_lexer_tests() {
|
TestsReport run_lexer_tests() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue