Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
reader_tests.h File Reference
#include <string.h>
#include <serene/ir/reader.h>
#include <serene/rt/context.h>
#include <serene/runtime.h>
#include "base.h"
#include "serene/rt/fiber.h"
Include dependency graph for reader_tests.h:

Go to the source code of this file.

Macros

#define READER_TESTS(X)

Functions

static srn_error_t * read_source (srn_context_t *ctx, const char *src, size_t len)
static void test_reader_malformed_utf8_in_string ()
static void test_reader_truncated_utf8_at_end ()
static void test_reader_trailing_whitespace_and_comment ()
static void test_reader_tree_has_no_error_on_success ()
static void test_reader_location_len_over_64k ()
static void test_reader_read_list_from_buffer ()

Macro Definition Documentation

◆ READER_TESTS

#define READER_TESTS ( X)
Value:
X("ir::reader::read_list_from_buffer", test_reader_read_list_from_buffer), \
X("ir::reader::malformed_utf8_in_string", test_reader_malformed_utf8_in_string), \
X("ir::reader::truncated_utf8_at_end", test_reader_truncated_utf8_at_end), \
X("ir::reader::trailing_whitespace_and_comment", test_reader_trailing_whitespace_and_comment), \
X("ir::reader::tree_has_no_error_on_success", test_reader_tree_has_no_error_on_success), \
X("ir::reader::location_len_over_64k", test_reader_location_len_over_64k)
static void test_reader_truncated_utf8_at_end()
static void test_reader_tree_has_no_error_on_success()
static void test_reader_trailing_whitespace_and_comment()
static void test_reader_malformed_utf8_in_string()
static void test_reader_read_list_from_buffer()
static void test_reader_location_len_over_64k()

Definition at line 30 of file reader_tests.h.

30#define READER_TESTS(X) \
31 X("ir::reader::read_list_from_buffer", test_reader_read_list_from_buffer), \
32 X("ir::reader::malformed_utf8_in_string", test_reader_malformed_utf8_in_string), \
33 X("ir::reader::truncated_utf8_at_end", test_reader_truncated_utf8_at_end), \
34 X("ir::reader::trailing_whitespace_and_comment", test_reader_trailing_whitespace_and_comment), \
35 X("ir::reader::tree_has_no_error_on_success", test_reader_tree_has_no_error_on_success), \
36 X("ir::reader::location_len_over_64k", test_reader_location_len_over_64k)

Function Documentation

◆ read_source()

srn_error_t * read_source ( srn_context_t * ctx,
const char * src,
size_t len )
static

Definition at line 40 of file reader_tests.h.

40 {
41 srn_sexp_parser_t parser = {
42 .ctx = ctx,
43 .reading_context = nullptr,
44 .buffer_id = 0,
45 .buffer = (const unsigned char *)src,
46 .len = len,
47 .pos = 0,
48 };
49 reader_fiber_arg_t fiber_arg = {.parser = &parser, .tree = nullptr};
50
51 auto f = srn_fiber_spawn(ctx, read_from_buffer, &fiber_arg);
53 return (srn_error_t *)f->result;
54}
srn_fiber_t * srn_fiber_spawn(srn_context_t *ctx, srn_fiber_entry_t entry, void *arg)
Make and schedule a fiber with every default, the engine's scheduler, the configured stack size,...
Definition fiber.c:250
srn_fiber_result_t read_from_buffer(srn_context_t *ctx, void *arg)
Definition reader.c:584
void srn_sched_run(srn_scheduler_t *sched, size_t nworkers)
Run the scheduler with nworkers os threads draining it, returning once the pool goes quiescent (every...
Definition scheduler.c:875
const size_t len
srn_engine_t * engine
Long term state of the compiler.
Definition context.h:49
srn_scheduler_t * scheduler
The fiber scheduler, that is the entry point of the fiber subsystem.
Definition engine.h:78
A runtime error, a tag classifying the failure and a human-readable message.
Definition errors.h:173
Here is the call graph for this function:
Here is the caller graph for this function:

◆ test_reader_location_len_over_64k()

void test_reader_location_len_over_64k ( )
static

Definition at line 148 of file reader_tests.h.

148 {
149 MAKE_ENGINE(mm, engine);
150 MAKE_CONTEXT(engine, ctx);
151
152 const size_t body = 70000;
153 char *src = ALLOCN_OR_PANIC(ctx, char, body + 3);
154 src[0] = '"';
155 memset(src + 1, 'a', body);
156 src[body + 1] = '"';
157 src[body + 2] = '\0';
158
159 srn_sexp_parser_t parser = {
160 .ctx = ctx,
161 .reading_context = nullptr,
162 .buffer_id = 0,
163 .buffer = (const unsigned char *)src,
164 .len = body + 2,
165 .pos = 0,
166 };
167 reader_fiber_arg_t fiber_arg = {.parser = &parser, .tree = nullptr};
168
169 auto f = srn_fiber_spawn(ctx, read_from_buffer, &fiber_arg);
170 srn_sched_run(engine->scheduler, 1);
171 ASSERT_NULL(f->result);
172
173 srn_sexp_node_t *node = array_list_get(&fiber_arg.tree->exprs, 0).data;
174 ASSERT_NOT_NULL(node);
175 TEST_CHECK(node->metadata->loc->offset == 0);
176 TEST_CHECK(node->metadata->loc->len == body + 2);
177
178 RELEASE_CONTEXT(ctx);
179 SHUTDOWN_ENGINE(mm, engine);
180}
#define TEST_CHECK(cond)
Definition acutest.h:95
array_list_maybe_element_t array_list_get(const array_list_t *al, array_list_index_t n)
Negative index is not supported.
Definition array_list.c:235
#define RELEASE_CONTEXT(x)
Definition base.h:48
#define ASSERT_NOT_NULL(x)
Definition base.h:30
#define SHUTDOWN_ENGINE(mm, engine)
Definition base.h:40
#define MAKE_ENGINE(mm, engine)
Definition base.h:34
#define ASSERT_NULL(x)
Definition base.h:31
#define MAKE_CONTEXT(engine, x)
Definition base.h:44
#define ALLOCN_OR_PANIC(ctx, T, N)
Definition context.h:99
array_list_elem_t data
Definition array_list.h:142
srn_sexp_tree_t * tree
Definition reader.h:184
srn_src_location_t * loc
nullptr is a valid value and represents an unknown location.
Definition core.h:74
srn_metadata_t * metadata
Definition reader.h:121
array_list_t exprs
Definition reader.h:156
uint32_t len
Length of the form in bytes.
Definition core.h:62
uint32_t offset
Byte offset of the form's first byte in the buffer.
Definition core.h:59
Here is the call graph for this function:

◆ test_reader_malformed_utf8_in_string()

void test_reader_malformed_utf8_in_string ( )
static

Definition at line 60 of file reader_tests.h.

60 {
61 MAKE_ENGINE(mm, engine);
62 MAKE_CONTEXT(engine, ctx);
63
64 const char src[] = "\"\x80\"";
65 srn_error_t *err = read_source(ctx, src, sizeof(src) - 1);
66
67 ASSERT_NOT_NULL(err);
69 TEST_CHECK(err->as.metadata->loc->offset == 1);
70
71 RELEASE_CONTEXT(ctx);
72 SHUTDOWN_ENGINE(mm, engine);
73}
@ IR_PARSE_ERROR
Definition errors.h:146
static srn_error_t * read_source(srn_context_t *ctx, const char *src, size_t len)
union srn_error_t::@110141362101221075206211275212023153042233307220 as
srn_error_tag_t tag
Definition errors.h:175
Here is the call graph for this function:

◆ test_reader_read_list_from_buffer()

void test_reader_read_list_from_buffer ( )
static

Definition at line 185 of file reader_tests.h.

185 {
186 MAKE_ENGINE(mm, engine);
187 MAKE_CONTEXT(engine, ctx);
188 auto sched = engine->scheduler;
189
190 const char *src = "(foo bar baz)";
191
192 srn_sexp_parser_t parser = {
193 .ctx = ctx,
194 .reading_context = nullptr,
195 .buffer_id = 0,
196 .buffer = (const unsigned char *)src,
197 .len = strlen(src),
198 .pos = 0,
199 };
200
201 reader_fiber_arg_t fiber_arg = {
202 .parser = &parser,
203 .tree = nullptr,
204 };
205
206 auto f = srn_fiber_spawn(ctx, read_from_buffer, &fiber_arg);
207 srn_sched_run(sched, 1);
208
209 srn_fiber_result_t result = f->result;
211
212 srn_sexp_tree_t *tree = fiber_arg.tree;
213 ASSERT_NOT_NULL(tree);
214 TEST_CHECK(tree->exprs.len == 1);
215
216 srn_sexp_node_t *root = array_list_get(&tree->exprs, 0).data;
217 ASSERT_NOT_NULL(root);
218 TEST_CHECK(root->type == SRN_SEXP_LIST);
219 TEST_CHECK(root->as.list->len == 3);
220
221 srn_sexp_node_t *cons1 = root->as.list->head;
222 ASSERT_NOT_NULL(cons1);
223 TEST_CHECK(cons1->type == SRN_SEXP_CONS);
224 TEST_CHECK(strcmp(cons1->as.cons->head->as.atom->name, "foo") == 0);
225
226 srn_sexp_node_t *cons2 = cons1->as.cons->tail;
227 ASSERT_NOT_NULL(cons2);
228 TEST_CHECK(strcmp(cons2->as.cons->head->as.atom->name, "bar") == 0);
229
230 srn_sexp_node_t *cons3 = cons2->as.cons->tail;
231 ASSERT_NOT_NULL(cons3);
232 TEST_CHECK(strcmp(cons3->as.cons->head->as.atom->name, "baz") == 0);
233
234 // The chain must terminate, not loop back to cons1.
235 TEST_CHECK(cons3->as.cons->tail == nullptr);
236
237 RELEASE_CONTEXT(ctx);
238 SHUTDOWN_ENGINE(mm, engine);
239}
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
Definition fiber.h:171
@ SRN_SEXP_CONS
Definition reader.h:53
@ SRN_SEXP_LIST
Definition reader.h:54
auto result
size_t len
logical length.
Definition array_list.h:168
char * name
Definition reader.h:64
srn_sexp_node_t * tail
Definition reader.h:98
srn_sexp_node_t * head
Definition reader.h:97
srn_sexp_node_t * head
Definition reader.h:110
srn_sexp_list_t * list
Definition reader.h:125
union srn_sexp_node_t::@313353022266020117306231170157030062126255275140 as
srn_sexp_cons_t * cons
Definition reader.h:126
srn_sexp_node_type_e type
Definition reader.h:120
srn_sexp_atom_t * atom
Definition reader.h:124
Here is the call graph for this function:

◆ test_reader_trailing_whitespace_and_comment()

void test_reader_trailing_whitespace_and_comment ( )
static

Definition at line 92 of file reader_tests.h.

92 {
93 const char *cases[] = {"foo\n", "(a b)\n\n", "foo ; trailing comment", " ", ""};
94
95 // A scheduler runs once per engine, so every case gets its own.
96 for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
97 MAKE_ENGINE(mm, engine);
98 MAKE_CONTEXT(engine, ctx);
99
100 srn_error_t *err = read_source(ctx, cases[i], strlen(cases[i]));
101 TEST_CHECK_(err == nullptr, "case %zu: '%s'", i, cases[i]);
102
103 RELEASE_CONTEXT(ctx);
104 SHUTDOWN_ENGINE(mm, engine);
105 }
106}
#define TEST_CHECK_(cond,...)
Definition acutest.h:94
Here is the call graph for this function:

◆ test_reader_tree_has_no_error_on_success()

void test_reader_tree_has_no_error_on_success ( )
static

Definition at line 111 of file reader_tests.h.

111 {
112 MAKE_ENGINE(mm, engine);
113
114 for (int round = 0; round < 3; round++) {
115 srn_context_t *junk = srn_context_make(engine);
116 const size_t n = 64 * 1024;
117 char *p = ALLOCN_OR_PANIC(junk, char, n);
118 memset(p, 0xFF, n);
120 }
121
122 MAKE_CONTEXT(engine, ctx);
123
124 const char *src = "(foo)";
125 srn_sexp_parser_t parser = {
126 .ctx = ctx,
127 .reading_context = nullptr,
128 .buffer_id = 0,
129 .buffer = (const unsigned char *)src,
130 .len = strlen(src),
131 .pos = 0,
132 };
133 reader_fiber_arg_t fiber_arg = {.parser = &parser, .tree = nullptr};
134
135 auto f = srn_fiber_spawn(ctx, read_from_buffer, &fiber_arg);
136 srn_sched_run(engine->scheduler, 1);
137 ASSERT_NULL(f->result);
138
139 srn_sexp_tree_t *tree = fiber_arg.tree;
140 ASSERT_NOT_NULL(tree);
141 TEST_CHECK(!HAS_ERROR(*tree));
142
143 RELEASE_CONTEXT(ctx);
144 SHUTDOWN_ENGINE(mm, engine);
145}
int n
Definition acutest.h:525
srn_context_t * srn_context_make(srn_engine_t *engine)
Make an empty context, by allocating a new memory block.
Definition context.c:39
int srn_context_release(srn_context_t *ctx)
Definition context.c:64
#define HAS_ERROR(x)
True when x – a value carrying an ERROR_HEADER – has an error attached.
Definition errors.h:70
Here is the call graph for this function:

◆ test_reader_truncated_utf8_at_end()

void test_reader_truncated_utf8_at_end ( )
static

Definition at line 77 of file reader_tests.h.

77 {
78 MAKE_ENGINE(mm, engine);
79 MAKE_CONTEXT(engine, ctx);
80
81 const char src[] = "foo \xE2";
82 srn_error_t *err = read_source(ctx, src, sizeof(src) - 1);
83
84 ASSERT_NOT_NULL(err);
86 TEST_CHECK(err->as.metadata->loc->offset == 4);
87
88 RELEASE_CONTEXT(ctx);
89 SHUTDOWN_ENGINE(mm, engine);
90}
Here is the call graph for this function: