Implemented tests for Toy_Bytecode and Toy_Routine

This commit is contained in:
2024-09-22 14:13:50 +10:00
parent 4567484038
commit a2625fa6d4
6 changed files with 811 additions and 15 deletions

View File

@@ -1,12 +1,16 @@
#include "toy_routine.h"
#include "toy_console_colors.h"
#include "toy_opcodes.h"
#include "toy_lexer.h"
#include "toy_parser.h"
#include <stdio.h>
#include <string.h>
//tests
int test_routine_header(Toy_Bucket* bucket) {
//simple test to ensure the header looks right
int test_routine_header_and_values(Toy_Bucket* bucket) {
//simple test to ensure the header looks right with an empty ast
{
//setup
Toy_Ast* ast = NULL;
@@ -16,8 +20,601 @@ int test_routine_header(Toy_Bucket* bucket) {
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check
//TODO
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 28 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, ast: PASS\n" TOY_CC_RESET);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 25)) != 0 ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, ast: PASS\n" TOY_CC_RESET);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//rerun the test with a more complex ast, derived from a snippet of source
{
//setup
const char* source = ";"; //interestingly, different ASTs will produce the same output
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 28 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 25)) != 0 ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce a null value
{
//setup
const char* source = "null;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 32 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_NULL ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*((unsigned char*)(buffer + 28)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 29)) != 0 ||
*((unsigned char*)(buffer + 30)) != 0 ||
*((unsigned char*)(buffer + 31)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce a boolean value
{
//setup
const char* source = "true;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 32 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_BOOLEAN ||
*((unsigned char*)(buffer + 26)) != 1 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*((unsigned char*)(buffer + 28)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 29)) != 0 ||
*((unsigned char*)(buffer + 30)) != 0 ||
*((unsigned char*)(buffer + 31)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce an integer value
{
//setup
const char* source = "42;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 36 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*(int*)(buffer + 28) != 42 ||
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 23)) != 0 ||
*((unsigned char*)(buffer + 34)) != 0 ||
*((unsigned char*)(buffer + 35)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce a float value
{
//setup
const char* source = "3.1415;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 36 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_FLOAT ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*(float*)(buffer + 28) != 3.1415f ||
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 23)) != 0 ||
*((unsigned char*)(buffer + 34)) != 0 ||
*((unsigned char*)(buffer + 35)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
return 0;
}
// int test_routine_unary(Toy_Bucket* bucket) {
// //TODO: Nothing produces a unary instruction yet
// }
int test_routine_binary(Toy_Bucket* bucket) {
//produce a simple algorithm
{
//setup
const char* source = "3 + 5;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 48 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*(int*)(buffer + 28) != 3 ||
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 33)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 34)) != 0 ||
*((unsigned char*)(buffer + 35)) != 0 ||
*(int*)(buffer + 36) != 5 ||
*((unsigned char*)(buffer + 40)) != TOY_OPCODE_ADD ||
*((unsigned char*)(buffer + 41)) != 0 ||
*((unsigned char*)(buffer + 42)) != 0 ||
*((unsigned char*)(buffer + 43)) != 0 ||
*((unsigned char*)(buffer + 44)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 45)) != 0 ||
*((unsigned char*)(buffer + 46)) != 0 ||
*((unsigned char*)(buffer + 47)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce a simple comparison
{
//setup
const char* source = "3 == 5;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 48 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*(int*)(buffer + 28) != 3 ||
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 33)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 34)) != 0 ||
*((unsigned char*)(buffer + 35)) != 0 ||
*(int*)(buffer + 36) != 5 ||
*((unsigned char*)(buffer + 40)) != TOY_OPCODE_COMPARE_EQUAL ||
*((unsigned char*)(buffer + 41)) != 0 ||
*((unsigned char*)(buffer + 42)) != 0 ||
*((unsigned char*)(buffer + 43)) != 0 ||
*((unsigned char*)(buffer + 44)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 45)) != 0 ||
*((unsigned char*)(buffer + 46)) != 0 ||
*((unsigned char*)(buffer + 47)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce a simple comparison
{
//setup
const char* source = "3 != 5;";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 52 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*(int*)(buffer + 28) != 3 ||
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 33)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 34)) != 0 ||
*((unsigned char*)(buffer + 35)) != 0 ||
*(int*)(buffer + 36) != 5 ||
*((unsigned char*)(buffer + 40)) != TOY_OPCODE_COMPARE_EQUAL ||
*((unsigned char*)(buffer + 41)) != 0 ||
*((unsigned char*)(buffer + 42)) != 0 ||
*((unsigned char*)(buffer + 43)) != 0 ||
*((unsigned char*)(buffer + 44)) != TOY_OPCODE_NEGATE ||
*((unsigned char*)(buffer + 45)) != 0 ||
*((unsigned char*)(buffer + 46)) != 0 ||
*((unsigned char*)(buffer + 47)) != 0 ||
*((unsigned char*)(buffer + 48)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 49)) != 0 ||
*((unsigned char*)(buffer + 50)) != 0 ||
*((unsigned char*)(buffer + 51)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
}
//produce a more complex algorithm
{
//setup
const char* source = "(1 + 2) * (3 + 4);";
Toy_Lexer lexer;
Toy_Parser parser;
Toy_bindLexer(&lexer, source);
Toy_bindParser(&parser, &lexer);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
//run
void* buffer = Toy_compileRoutine(ast);
int len = ((int*)buffer)[0];
//check header
int* ptr = (int*)buffer;
if ((ptr++)[0] != 72 || //total size
(ptr++)[0] != 0 || //param count
(ptr++)[0] != 0 || //jump count
(ptr++)[0] != 0 || //data count
(ptr++)[0] != 0) //subs count
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine header, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//check code
if (
//left hand side
*((unsigned char*)(buffer + 24)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 25)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 26)) != 0 ||
*((unsigned char*)(buffer + 27)) != 0 ||
*(int*)(buffer + 28) != 1 ||
*((unsigned char*)(buffer + 32)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 33)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 34)) != 0 ||
*((unsigned char*)(buffer + 35)) != 0 ||
*(int*)(buffer + 36) != 2 ||
*((unsigned char*)(buffer + 40)) != TOY_OPCODE_ADD ||
*((unsigned char*)(buffer + 41)) != 0 ||
*((unsigned char*)(buffer + 42)) != 0 ||
*((unsigned char*)(buffer + 43)) != 0 ||
//right hand side
*((unsigned char*)(buffer + 44)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 45)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 46)) != 0 ||
*((unsigned char*)(buffer + 47)) != 0 ||
*(int*)(buffer + 48) != 3 ||
*((unsigned char*)(buffer + 52)) != TOY_OPCODE_READ ||
*((unsigned char*)(buffer + 53)) != TOY_VALUE_INTEGER ||
*((unsigned char*)(buffer + 54)) != 0 ||
*((unsigned char*)(buffer + 55)) != 0 ||
*(int*)(buffer + 56) != 4 ||
*((unsigned char*)(buffer + 60)) != TOY_OPCODE_ADD ||
*((unsigned char*)(buffer + 61)) != 0 ||
*((unsigned char*)(buffer + 62)) != 0 ||
*((unsigned char*)(buffer + 63)) != 0 ||
//multiply the two values
*((unsigned char*)(buffer + 64)) != TOY_OPCODE_MULTIPLY ||
*((unsigned char*)(buffer + 65)) != 0 ||
*((unsigned char*)(buffer + 66)) != 0 ||
*((unsigned char*)(buffer + 67)) != 0 ||
*((unsigned char*)(buffer + 68)) != TOY_OPCODE_RETURN ||
*((unsigned char*)(buffer + 69)) != 0 ||
*((unsigned char*)(buffer + 70)) != 0 ||
*((unsigned char*)(buffer + 71)) != 0
)
{
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to produce the expected routine code, source: %s\n" TOY_CC_RESET, source);
//cleanup and return
TOY_FREE_ARRAY(unsigned char, buffer, len);
return -1;
}
//cleanup
TOY_FREE_ARRAY(unsigned char, buffer, len);
@@ -27,15 +624,24 @@ int test_routine_header(Toy_Bucket* bucket) {
}
int main() {
fprintf(stderr, TOY_CC_WARN "WARNING: Routine tests incomplete\n" TOY_CC_RESET);
//run each test set, returning the total errors given
int total = 0, res = 0;
{
Toy_Bucket* bucket = NULL;
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
res = test_routine_header(bucket);
res = test_routine_header_and_values(bucket);
TOY_BUCKET_FREE(bucket);
if (res == 0) {
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);
}
total += res;
}
{
Toy_Bucket* bucket = NULL;
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
res = test_routine_binary(bucket);
TOY_BUCKET_FREE(bucket);
if (res == 0) {
printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);