mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Wrote failing TDD test for timer library, not enabled
This commit is contained in:
85
repl/lib_timer.c
Normal file
85
repl/lib_timer.c
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "lib_timer.h"
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
//using sys/time.h
|
||||
var timer: opaque = createTimer();
|
||||
|
||||
timer.startTimer();
|
||||
timer.stopTimer();
|
||||
|
||||
timer.setTimer(seconds, microseconds);
|
||||
timer.getTimerSeconds();
|
||||
timer.getTimerMicroseconds();
|
||||
|
||||
var diffTimer: opaque = timer.compareTimer(rhs); //expects a stopped timer for both arguments
|
||||
|
||||
timer.timerToString(); //string representation of the timer
|
||||
*/
|
||||
|
||||
//call the hook
|
||||
typedef struct Natives {
|
||||
char* name;
|
||||
NativeFn fn;
|
||||
} Natives;
|
||||
|
||||
int hookTimer(Interpreter* interpreter, Literal identifier, Literal alias) {
|
||||
//build the natives list
|
||||
Natives natives[] = {
|
||||
// {"clock", nativeClock},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
//store the library in an aliased dictionary
|
||||
if (!IS_NULL(alias)) {
|
||||
//make sure the name isn't taken
|
||||
if (isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||
interpreter->errorOutput("Can't override an existing variable\n");
|
||||
freeLiteral(alias);
|
||||
return false;
|
||||
}
|
||||
|
||||
//create the dictionary to load up with functions
|
||||
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
|
||||
initLiteralDictionary(dictionary);
|
||||
|
||||
//load the dict with functions
|
||||
for (int i = 0; natives[i].name; i++) {
|
||||
Literal name = TO_STRING_LITERAL(copyString(natives[i].name, strlen(natives[i].name)), strlen(natives[i].name));
|
||||
Literal func = TO_FUNCTION_LITERAL((void*)natives[i].fn, 0);
|
||||
func.type = LITERAL_FUNCTION_NATIVE;
|
||||
|
||||
setLiteralDictionary(dictionary, name, func);
|
||||
|
||||
freeLiteral(name);
|
||||
freeLiteral(func);
|
||||
}
|
||||
|
||||
//build the type
|
||||
Literal type = TO_TYPE_LITERAL(LITERAL_DICTIONARY, true);
|
||||
Literal strType = TO_TYPE_LITERAL(LITERAL_STRING, true);
|
||||
Literal fnType = TO_TYPE_LITERAL(LITERAL_FUNCTION_NATIVE, true);
|
||||
TYPE_PUSH_SUBTYPE(&type, strType);
|
||||
TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||
|
||||
//set scope
|
||||
Literal dict = TO_DICTIONARY_LITERAL(dictionary);
|
||||
declareScopeVariable(interpreter->scope, alias, type);
|
||||
setScopeVariable(interpreter->scope, alias, dict, false);
|
||||
|
||||
//cleanup
|
||||
freeLiteral(dict);
|
||||
freeLiteral(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//default
|
||||
for (int i = 0; natives[i].name; i++) {
|
||||
injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
repl/lib_timer.h
Normal file
6
repl/lib_timer.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "interpreter.h"
|
||||
|
||||
int hookTimer(Interpreter* interpreter, Literal identifier, Literal alias);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "repl_tools.h"
|
||||
#include "lib_standard.h"
|
||||
#include "lib_timer.h"
|
||||
|
||||
#include "console_colors.h"
|
||||
|
||||
@@ -25,6 +26,7 @@ void repl() {
|
||||
|
||||
//inject the libs
|
||||
injectNativeHook(&interpreter, "standard", hookStandard);
|
||||
injectNativeHook(&interpreter, "timer", hookTimer);
|
||||
|
||||
for(;;) {
|
||||
printf("> ");
|
||||
|
||||
52
scripts/test/lib/timer.toy
Normal file
52
scripts/test/lib/timer.toy
Normal file
@@ -0,0 +1,52 @@
|
||||
//test the timer library
|
||||
{
|
||||
//create a timer, manipulate it's values
|
||||
import timer;
|
||||
|
||||
//create a timer
|
||||
var timer: opaque = createTimer();
|
||||
|
||||
//set the timer
|
||||
timer.setTimer(42, 8891);
|
||||
|
||||
//check the timer values
|
||||
assert timer.getTimerSeconds() == 42, "getTimerSeconds() failed";
|
||||
assert timer.getTimerMicroseconds() == 42, "getTimerMicroseconds() failed";
|
||||
}
|
||||
|
||||
{
|
||||
//create a timer, run it for a short time
|
||||
var timerA: opaque = createTimer();
|
||||
|
||||
timerA.startTimer();
|
||||
for (var i: int = 0; i < 1000 * 1000; i++);
|
||||
timerA.stopTimer();
|
||||
|
||||
//create another timer, run it for a longer time
|
||||
var timerB: opaque = createTimer();
|
||||
|
||||
timerB.startTimer();
|
||||
for (var i: int = 0; i < 1000 * 1000 * 10; i++);
|
||||
timerB.stopTimer();
|
||||
|
||||
//check to ensure that the second timer took longer than the first
|
||||
//WARNING: this has the small possibility of failing due to external factors
|
||||
var difference: opaque = timerA.compareTimer(timerB);
|
||||
|
||||
assert difference.getTimerSeconds() >= 0, "compareTimer() (seconds) failed";
|
||||
if (difference.getTimerSeconds() == 0) {
|
||||
assert difference.getTimerMicroseconds() >= 0, "compareTimer() (microseconds) failed";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
//set a timer to check string representation
|
||||
var timer: opaque = createTimer();
|
||||
|
||||
timer.setTimer(42, 999);
|
||||
|
||||
assert timer.timerToString() == "42.999", "timerToString() failed";
|
||||
}
|
||||
|
||||
|
||||
print "All good";
|
||||
@@ -12,12 +12,26 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "../repl/lib_standard.h"
|
||||
#include "../repl/lib_timer.h"
|
||||
|
||||
//supress the print output
|
||||
static void noPrintFn(const char* output) {
|
||||
//NO OP
|
||||
}
|
||||
|
||||
static int failedAsserts = 0;
|
||||
static void assertWrapper(const char* output) {
|
||||
failedAsserts++;
|
||||
fprintf(stderr, ERROR "Assertion failure: ");
|
||||
fprintf(stderr, "%s", output);
|
||||
fprintf(stderr, "\n" RESET); //default new line
|
||||
}
|
||||
|
||||
static void errorWrapper(const char* output) {
|
||||
failedAsserts++;
|
||||
fprintf(stderr, ERROR "%s" RESET, output);
|
||||
}
|
||||
|
||||
//compilation functions
|
||||
char* readFile(char* path, size_t* fileSize) {
|
||||
FILE* file = fopen(path, "rb");
|
||||
@@ -90,56 +104,65 @@ unsigned char* compileString(char* source, size_t* size) {
|
||||
return tb;
|
||||
}
|
||||
|
||||
void runBinary(unsigned char* tb, size_t size) {
|
||||
void runBinaryWithLibrary(unsigned char* tb, size_t size, char* library, HookFn hook) {
|
||||
Interpreter interpreter;
|
||||
initInterpreter(&interpreter);
|
||||
|
||||
//NOTE: supress print output for testing
|
||||
setInterpreterPrint(&interpreter, noPrintFn);
|
||||
setInterpreterAssert(&interpreter, assertWrapper);
|
||||
setInterpreterError(&interpreter, errorWrapper);
|
||||
|
||||
//inject the standard libraries into this interpreter
|
||||
injectNativeHook(&interpreter, "standard", hookStandard);
|
||||
injectNativeHook(&interpreter, library, hook);
|
||||
|
||||
runInterpreter(&interpreter, tb, size);
|
||||
freeInterpreter(&interpreter);
|
||||
}
|
||||
|
||||
void runSource(char* source) {
|
||||
size_t size = 0;
|
||||
unsigned char* tb = compileString(source, &size);
|
||||
if (!tb) {
|
||||
return;
|
||||
}
|
||||
runBinary(tb, size);
|
||||
}
|
||||
|
||||
void runSourceFile(char* fname) {
|
||||
size_t size = 0; //not used
|
||||
char* source = readFile(fname, &size);
|
||||
runSource(source);
|
||||
free((void*)source);
|
||||
}
|
||||
typedef struct Payload {
|
||||
char* fname;
|
||||
char* libname;
|
||||
HookFn hook;
|
||||
} Payload;
|
||||
|
||||
int main() {
|
||||
{
|
||||
//run each file in ../scripts/test/
|
||||
char* filenames[] = {
|
||||
"interactions.toy",
|
||||
"standard.toy",
|
||||
NULL
|
||||
Payload payloads[] = {
|
||||
{"interactions.toy", "standard", hookStandard}, //interactions needs standard
|
||||
{"standard.toy", "standard", hookStandard},
|
||||
// {"timer.toy", "timer", hookTimer},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
for (int i = 0; filenames[i]; i++) {
|
||||
printf("Running %s\n", filenames[i]);
|
||||
for (int i = 0; payloads[i].fname; i++) {
|
||||
printf("Running %s\n", payloads[i].fname);
|
||||
|
||||
char buffer[128];
|
||||
snprintf(buffer, 128, "../scripts/test/lib/%s", filenames[i]);
|
||||
char fname[128];
|
||||
snprintf(fname, 128, "../scripts/test/lib/%s", payloads[i].fname);
|
||||
|
||||
runSourceFile(buffer);
|
||||
//compile the source
|
||||
size_t size = 0;
|
||||
char* source = readFile(fname, &size);
|
||||
unsigned char* tb = compileString(source, &size);
|
||||
free((void*)source);
|
||||
|
||||
if (!tb) {
|
||||
printf(ERROR "Failed to compile file: %s" RESET, fname);
|
||||
}
|
||||
|
||||
runBinaryWithLibrary(tb, size, payloads[i].libname, payloads[i].hook);
|
||||
}
|
||||
}
|
||||
|
||||
printf(NOTICE "All good\n" RESET);
|
||||
return 0;
|
||||
if (!failedAsserts) {
|
||||
printf(NOTICE "All good\n" RESET);
|
||||
}
|
||||
else {
|
||||
printf(WARN "Problems detected in libraries\n" RESET);
|
||||
}
|
||||
|
||||
return failedAsserts;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user