Refactor test interface
This commit is contained in:
@@ -40,3 +40,8 @@ the agent to update the implementation.
|
|||||||
|
|
||||||
When creating a commit, make sure that both the user's and the agent's modifications
|
When creating a commit, make sure that both the user's and the agent's modifications
|
||||||
are included in the commit.
|
are included in the commit.
|
||||||
|
|
||||||
|
Only create a commit when specifically asked for that. Never assume implicitly that the
|
||||||
|
user wants you to create a commit.
|
||||||
|
Even if they asked you to create a commit in an earlier task, it does not mean that
|
||||||
|
you should also create a commit in a later task.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
static jmp_buf s_testJmp;
|
static jmp_buf s_testJmp;
|
||||||
static const char* s_failMsg;
|
static const char* s_failMsg;
|
||||||
@@ -16,22 +17,6 @@ void fail(const char* msg) {
|
|||||||
longjmp(s_testJmp, 1);
|
longjmp(s_testJmp, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assert_not_null(void* ptr, const char* msg) {
|
|
||||||
if (ptr == NULL) {
|
|
||||||
fail(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assert_str(const char* expected, const char* actual, const char* msg) {
|
|
||||||
if (expected == NULL || actual == NULL || strcmp(expected, actual) != 0) {
|
|
||||||
fail(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assert_log(const char* expected, const char* msg) {
|
|
||||||
assert_str(expected, s_logOutput, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* read_file_content(const char* filepath) {
|
char* read_file_content(const char* filepath) {
|
||||||
FILE* f;
|
FILE* f;
|
||||||
long size;
|
long size;
|
||||||
@@ -53,6 +38,56 @@ char* read_file_content(const char* filepath) {
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assert_not_null(void* ptr, const char* msg) {
|
||||||
|
if (ptr == NULL) {
|
||||||
|
fail(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_string(const char* expected, String actual, const char* msg) {
|
||||||
|
if (expected == NULL || actual.data == NULL || strlen(expected) != actual.length || strncmp(expected, actual.data, actual.length) != 0) {
|
||||||
|
fail(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_str(const char* expected, const char* actual, const char* msg) {
|
||||||
|
if (expected == NULL || actual == NULL || strcmp(expected, actual) != 0) {
|
||||||
|
fail(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenStream* tokenstream_get_test(void) {
|
||||||
|
char* filepath = NULL;
|
||||||
|
TokenStream* ts = NULL;
|
||||||
|
|
||||||
|
filepath = format_string("v0/tests/%s.c2", s_currentTestName);
|
||||||
|
if (!filepath) {
|
||||||
|
fail("out of memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_testSource) free(s_testSource);
|
||||||
|
s_testSource = read_file_content(filepath);
|
||||||
|
if (!s_testSource) {
|
||||||
|
fail("could not read test source file");
|
||||||
|
free(filepath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ts = tokenstream_open(filepath, s_testSource);
|
||||||
|
free(filepath);
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module* test_get_ast(void) {
|
||||||
|
TokenStream* ts = tokenstream_get_test();
|
||||||
|
if (!ts) return NULL;
|
||||||
|
return parser_parse(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assert_log(const char* expected, const char* msg) {
|
||||||
|
assert_str(expected, s_logOutput, msg);
|
||||||
|
}
|
||||||
|
|
||||||
void assert_log_file(const char* msg) {
|
void assert_log_file(const char* msg) {
|
||||||
char* filepath = format_string("v0/tests/%s.log", s_currentTestName);
|
char* filepath = format_string("v0/tests/%s.log", s_currentTestName);
|
||||||
const char* generate;
|
const char* generate;
|
||||||
@@ -109,28 +144,6 @@ void assert_false(bool condition, const char* msg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenStream* tokenstream_get_test(void) {
|
|
||||||
char* filepath = NULL;
|
|
||||||
TokenStream* ts = NULL;
|
|
||||||
|
|
||||||
filepath = format_string("v0/tests/%s.c2", s_currentTestName);
|
|
||||||
if (!filepath) {
|
|
||||||
fail("out of memory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_testSource) free(s_testSource);
|
|
||||||
s_testSource = read_file_content(filepath);
|
|
||||||
if (!s_testSource) {
|
|
||||||
fail("could not read test source file");
|
|
||||||
free(filepath);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ts = tokenstream_open(filepath, s_testSource);
|
|
||||||
free(filepath);
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_append(const char* msg) {
|
static void log_append(const char* msg) {
|
||||||
size_t oldLen = s_logOutput ? strlen(s_logOutput) : 0;
|
size_t oldLen = s_logOutput ? strlen(s_logOutput) : 0;
|
||||||
size_t newLen = oldLen + strlen(msg) + 1;
|
size_t newLen = oldLen + strlen(msg) + 1;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#define TEST_H
|
#define TEST_H
|
||||||
|
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
#include "ast.h"
|
||||||
|
|
||||||
typedef void (*Test)(void);
|
typedef void (*Test)(void);
|
||||||
|
|
||||||
@@ -35,6 +36,17 @@ void assert_not_null(void* ptr, const char* msg);
|
|||||||
*/
|
*/
|
||||||
void assert_str(const char* expected, const char* actual, const char* msg);
|
void assert_str(const char* expected, const char* actual, const char* msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that a string has the expected value.
|
||||||
|
*
|
||||||
|
* Calls `fail` if the assertion does not hold.
|
||||||
|
*
|
||||||
|
* @param expected The expected value. This is typically a string literal.
|
||||||
|
* @param actual The actual value. This is typically an expression.
|
||||||
|
* @param msg The message to print if these do not match.
|
||||||
|
*/
|
||||||
|
void assert_string(const char* expected, String actual, const char* msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that the logged output matches the expected value.
|
* Asserts that the logged output matches the expected value.
|
||||||
*/
|
*/
|
||||||
@@ -66,7 +78,17 @@ void assert_false(bool condition, const char* msg);
|
|||||||
/**
|
/**
|
||||||
* Get the token stream used for this test.
|
* Get the token stream used for this test.
|
||||||
* It reads from the `v0/tests/xyz.c2` file, where xyz is the test name.
|
* It reads from the `v0/tests/xyz.c2` file, where xyz is the test name.
|
||||||
|
*
|
||||||
|
* At the end of the test, the tokenstream will be freed automatically by the test harness.
|
||||||
*/
|
*/
|
||||||
TokenStream* tokenstream_get_test(void);
|
TokenStream* test_get_tokenstream(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a parsed module for the this test.
|
||||||
|
* It reads from the `v0/tests/xyz.c2` file, where xyz is the test name.
|
||||||
|
*
|
||||||
|
* At the end of the test, the AST will be freed automatically by the test harness.
|
||||||
|
*/
|
||||||
|
Module* test_get_ast(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+8
-34
@@ -6,16 +6,10 @@
|
|||||||
static void test_parser_module_name(void) {
|
static void test_parser_module_name(void) {
|
||||||
TokenStream* ts = tokenstream_open("test.c", "module my_module;");
|
TokenStream* ts = tokenstream_open("test.c", "module my_module;");
|
||||||
Module* m = parser_parse(ts);
|
Module* m = parser_parse(ts);
|
||||||
char* buf;
|
|
||||||
|
|
||||||
assert_not_null(m, "expected module to be parsed");
|
assert_not_null(m, "expected module to be parsed");
|
||||||
buf = malloc(m->name.text.length + 1);
|
assert_string("my_module", m->name.text, "expected name 'my_module'");
|
||||||
memcpy(buf, m->name.text.data, m->name.text.length);
|
parser_free(m);
|
||||||
buf[m->name.text.length] = '\0';
|
|
||||||
assert_str("my_module", buf, "expected name 'my_module'");
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
parser_free(m);
|
|
||||||
tokenstream_close(ts);
|
tokenstream_close(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,49 +56,29 @@ static void test_parser_bad_import_name(void) {
|
|||||||
static void test_parser_imports(void) {
|
static void test_parser_imports(void) {
|
||||||
TokenStream* ts = tokenstream_open("test.c", "module my_module; import other_module;");
|
TokenStream* ts = tokenstream_open("test.c", "module my_module; import other_module;");
|
||||||
Module* m = parser_parse(ts);
|
Module* m = parser_parse(ts);
|
||||||
char* buf;
|
|
||||||
|
|
||||||
assert_not_null(m, "expected module to be parsed");
|
assert_not_null(m, "expected module to be parsed");
|
||||||
buf = malloc(m->name.text.length + 1);
|
assert_string("my_module", m->name.text, "expected name 'my_module'");
|
||||||
memcpy(buf, m->name.text.data, m->name.text.length);
|
|
||||||
buf[m->name.text.length] = '\0';
|
|
||||||
assert_str("my_module", buf, "expected name 'my_module'");
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
assert_not_null(m->imports, "expected imports to be parsed");
|
assert_not_null(m->imports, "expected imports to be parsed");
|
||||||
assert_int(1, (int)m->import_count, "expected one import");
|
assert_int(1, (int)m->import_count, "expected one import");
|
||||||
buf = malloc(m->imports[0].module_name.text.length + 1);
|
assert_string("other_module", m->imports[0].module_name.text, "expected import name 'other_module'");
|
||||||
memcpy(buf, m->imports[0].module_name.text.data, m->imports[0].module_name.text.length);
|
|
||||||
buf[m->imports[0].module_name.text.length] = '\0';
|
|
||||||
assert_str("other_module", buf, "expected import name 'other_module'");
|
|
||||||
free(buf);
|
|
||||||
assert_false(m->imports[0].is_public, "expected import to not be public");
|
assert_false(m->imports[0].is_public, "expected import to not be public");
|
||||||
|
parser_free(m);
|
||||||
parser_free(m);
|
|
||||||
tokenstream_close(ts);
|
tokenstream_close(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_parser_public_imports(void) {
|
static void test_parser_public_imports(void) {
|
||||||
TokenStream* ts = tokenstream_open("test.c", "module my_module; import public other_module;");
|
TokenStream* ts = tokenstream_open("test.c", "module my_module; import public other_module;");
|
||||||
Module* m = parser_parse(ts);
|
Module* m = parser_parse(ts);
|
||||||
char* buf;
|
|
||||||
|
|
||||||
assert_not_null(m, "expected module to be parsed");
|
assert_not_null(m, "expected module to be parsed");
|
||||||
buf = malloc(m->name.text.length + 1);
|
assert_string("my_module", m->name.text, "expected name 'my_module'");
|
||||||
memcpy(buf, m->name.text.data, m->name.text.length);
|
|
||||||
buf[m->name.text.length] = '\0';
|
|
||||||
assert_str("my_module", buf, "expected name 'my_module'");
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
assert_not_null(m->imports, "expected imports to be parsed");
|
assert_not_null(m->imports, "expected imports to be parsed");
|
||||||
assert_int(1, (int)m->import_count, "expected one import");
|
assert_int(1, (int)m->import_count, "expected one import");
|
||||||
buf = malloc(m->imports[0].module_name.text.length + 1);
|
assert_string("other_module", m->imports[0].module_name.text, "expected import name 'other_module'");
|
||||||
memcpy(buf, m->imports[0].module_name.text.data, m->imports[0].module_name.text.length);
|
|
||||||
buf[m->imports[0].module_name.text.length] = '\0';
|
|
||||||
assert_str("other_module", buf, "expected import name 'other_module'");
|
|
||||||
free(buf);
|
|
||||||
assert_true(m->imports[0].is_public, "expected import to be public");
|
assert_true(m->imports[0].is_public, "expected import to be public");
|
||||||
|
parser_free(m);
|
||||||
parser_free(m);
|
|
||||||
tokenstream_close(ts);
|
tokenstream_close(ts);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* Contains runtime information about types.
|
||||||
|
*/
|
||||||
|
#ifndef TYPES_H
|
||||||
|
#define TYPES_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user