Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/gravity
Path: blob/master/src/cli/unittest.c
1218 views
1
//
2
// unittest.c
3
// gravity
4
//
5
// Created by Marco Bambini on 23/03/16.
6
// Copyright © 2016 CreoLabs. All rights reserved.
7
//
8
9
#include "gravity_compiler.h"
10
#include "gravity_utils.h"
11
#include "gravity_core.h"
12
#include "gravity_vm.h"
13
14
typedef struct {
15
bool processed;
16
17
uint32_t ncount;
18
uint32_t nsuccess;
19
uint32_t nfailure;
20
21
error_type_t expected_error;
22
gravity_value_t expected_value;
23
int32_t expected_row;
24
int32_t expected_col;
25
} test_data;
26
27
static void unittest_init (const char *target_file, test_data *data) {
28
#pragma unused(target_file)
29
++data->ncount;
30
data->processed = false;
31
}
32
33
static void unittest_cleanup (const char *target_file, test_data *data) {
34
#pragma unused(target_file,data)
35
}
36
37
static void unittest_callback (error_type_t error_type, const char *description, const char *notes, gravity_value_t value, int32_t row, int32_t col, void *xdata) {
38
test_data *data = (test_data *)xdata;
39
data->expected_error = error_type;
40
data->expected_value = value;
41
data->expected_row = row;
42
data->expected_col = col;
43
44
if (notes) printf("\tNOTE: %s\n", notes);
45
printf("\t%s\n", description);
46
}
47
48
// MARK: -
49
50
static void callback_error (error_type_t error_type, const char *message, error_desc_t error_desc, void *xdata) {
51
test_data *data = (test_data *)xdata;
52
53
if (data->processed == true) return; // ignore 2nd error
54
data->processed = true;
55
56
const char *type = "NONE";
57
if (error_type == GRAVITY_ERROR_SYNTAX) type = "SYNTAX";
58
else if (error_type == GRAVITY_ERROR_SEMANTIC) type = "SEMANTIC";
59
else if (error_type == GRAVITY_ERROR_RUNTIME) type = "RUNTIME";
60
else if (error_type == GRAVITY_WARNING) type = "WARNING";
61
62
if (error_type == GRAVITY_ERROR_RUNTIME) printf("\tRUNTIME ERROR: ");
63
else printf("\t%s ERROR on %d (%d,%d): ", type, error_desc.fileid, error_desc.lineno, error_desc.colno);
64
printf("%s\n", message);
65
66
bool same_error = (data->expected_error == error_type);
67
bool same_row = (data->expected_row != -1) ? (data->expected_row == error_desc.lineno) : true;
68
bool same_col = (data->expected_col != -1) ? (data->expected_col == error_desc.colno) : true;
69
70
if (same_error && same_row && same_col) {
71
++data->nsuccess;
72
printf("\tSUCCESS\n");
73
} else {
74
++data->nfailure;
75
printf("\tFAILURE\n");
76
}
77
}
78
79
static const char *callback_read (const char *path, size_t *size, uint32_t *fileid, void *xdata) {
80
#pragma unused(fileid,xdata)
81
return file_read(path, size);
82
}
83
84
static void test_folder (const char *folder_path, test_data *data) {
85
DIRREF dir = directory_init(folder_path);
86
if (!dir) return;
87
88
const char *target_file;
89
while ((target_file = directory_read(dir))) {
90
// if file is a folder then start recursion
91
const char *full_path = file_buildpath(target_file, folder_path);
92
if (is_directory(full_path)) {
93
// skip disabled folder
94
if (strcmp(target_file, "disabled") == 0) continue;
95
96
test_folder(full_path, data);
97
continue;
98
}
99
100
// load source code
101
size_t size = 0;
102
const char *source_code = file_read(full_path, &size);
103
assert(source_code);
104
105
// start unit test
106
unittest_init(target_file, data);
107
108
// compile and run source code
109
printf("\n%d\tTest file: %s\n", data->ncount, target_file);
110
printf("\tTest path: %s\n", full_path);
111
mem_free(full_path);
112
113
// initialize compiler and delegates
114
gravity_delegate_t delegate = {
115
.xdata = (void *)data,
116
.error_callback = callback_error,
117
.unittest_callback = unittest_callback,
118
.loadfile_callback = callback_read
119
};
120
121
gravity_compiler_t *compiler = gravity_compiler_create(&delegate);
122
gravity_closure_t *closure = gravity_compiler_run(compiler, source_code, size, 0, false);
123
gravity_vm *vm = gravity_vm_new(&delegate);
124
gravity_compiler_transfer(compiler, vm);
125
gravity_compiler_free(compiler);
126
127
if (closure) {
128
if (gravity_vm_run(vm, closure)) {
129
data->processed = true;
130
gravity_value_t result = gravity_vm_result(vm);
131
if (gravity_value_equals(result, data->expected_value)) {
132
++data->nsuccess;
133
printf("\tSUCCESS\n");
134
} else {
135
++data->nfailure;
136
printf("\tFAILURE\n");
137
}
138
gravity_value_free(NULL, data->expected_value);
139
}
140
}
141
gravity_vm_free(vm);
142
143
// case for empty files or simple declarations test
144
if (!data->processed) {
145
++data->nsuccess;
146
printf("\tSUCCESS\n");
147
}
148
149
// cleanup unitest
150
unittest_cleanup(target_file, data);
151
}
152
}
153
154
int main (int argc, const char* argv[]) {
155
test_data data = {
156
.ncount = 0,
157
.nsuccess = 0,
158
.nfailure = 0
159
};
160
161
if (argc != 2) {
162
printf("Usage: unittest /path/to/unitest/\n");
163
return 0;
164
}
165
166
// print console header
167
printf("==============================================\n");
168
printf("Gravity UnitTest\n");
169
printf("Gravity version %s\n", GRAVITY_VERSION);
170
printf("Build date: %s\n", GRAVITY_BUILD_DATE);
171
printf("==============================================\n");
172
173
mem_init();
174
nanotime_t tstart = nanotime();
175
test_folder(argv[1], &data);
176
nanotime_t tend = nanotime();
177
178
double result = ((double)((data.nsuccess * 100)) / (double)data.ncount);
179
printf("\n\n");
180
printf("==============================================\n");
181
printf("Total Tests: %d\n", data.ncount);
182
printf("Total Successes: %d\n", data.nsuccess);
183
printf("Total Failures: %d\n", data.nfailure);
184
printf("Result: %.2f %%\n", result);
185
printf("Time: %.4f ms\n", millitime(tstart, tend));
186
printf("==============================================\n");
187
printf("\n");
188
189
return 0;
190
}
191
192