Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
ns_tests.h
Go to the documentation of this file.
1/* -*- C -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <lxsameer@lxsameer.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include "base.h"
22#include "serene/rt/core.h"
23#include "serene/rt/fiber.h"
25#include "serene/rt/protocols.h"
26#include "serene/rt/strings.h"
27#include "serene/rt/symbols.h"
28#include "serene/runtime.h"
29
30#define NS_TESTS(X) \
31 X("namespace::get_or_create", test_ns_get_or_create), \
32 X("namespace::get_or_create_twice", test_ns_get_twice), \
33 X("config::wiring", test_config_wiring), X("config::runtime_macros", test_runtime_macros)
34
35static void test_ns_get_or_create() {
36 MAKE_ENGINE(mm, engine);
37 MAKE_CONTEXT(engine, ctx);
38
39 srn_value_t *name = srn_string_make(ctx, &absurd_metadata, "serene.tests");
40 srn_error_t *err = nullptr;
41 srn_namespace_t *ns = srn_namespace_get_or_create(engine, AS_STRING(name), &err);
42
43 TEST_ASSERT(ns != nullptr);
44 TEST_CHECK(err == nullptr);
45 // ns should has it's own context
46 TEST_CHECK(ns->root_context != ctx);
47 TEST_CHECK(atomic_load(&ns->sym_table)->len == 0);
48 TEST_CHECK(ns->node == nullptr);
50
51 // Creation registers the namespace with the engine.
52 TEST_CHECK(atomic_load(&engine->namespaces)->len == 1);
53 TEST_CHECK(srn_context_find_namespace(ctx, "serene.tests") == ns);
54
55 RELEASE_CONTEXT(ctx);
56 SHUTDOWN_ENGINE(mm, engine);
57}
58
59// A second call with the same name returns the registered namespace rather
60// than a new one.
61static void test_ns_get_twice() {
62 MAKE_ENGINE(mm, engine);
63 MAKE_CONTEXT(engine, ctx);
64
65 srn_value_t *name = srn_string_make(ctx, &absurd_metadata, "serene.tests");
66 srn_error_t *err = nullptr;
67 srn_namespace_t *ns1 = srn_namespace_get_or_create(engine, AS_STRING(name), &err);
68 srn_namespace_t *ns2 = srn_namespace_get_or_create(engine, AS_STRING(name), &err);
69
70 TEST_ASSERT(ns1 != nullptr);
71 TEST_CHECK(ns1 == ns2);
72 TEST_CHECK(atomic_load(&engine->namespaces)->len == 1);
73
74 // A different name is a different namespace.
75 srn_value_t *other = srn_string_make(ctx, &absurd_metadata, "serene.other");
76 srn_namespace_t *ns3 = srn_namespace_get_or_create(engine, AS_STRING(other), &err);
77 TEST_CHECK(ns3 != ns1);
78 TEST_CHECK(atomic_load(&engine->namespaces)->len == 2);
79 TEST_CHECK(srn_context_find_namespace(ctx, "serene.other") == ns3);
80 TEST_CHECK(srn_context_find_namespace(ctx, "serene.missing") == nullptr);
81
82 RELEASE_CONTEXT(ctx);
83 SHUTDOWN_ENGINE(mm, engine);
84}
85
87 UNUSED(ctx);
88 UNUSED(arg);
89 return nullptr;
90}
91
92// Every configuration knob is read from the configuration, the MM block size
93// at srn_mm_init, the per fiber stack default, and the string and namespace
94// length limits.
95static void test_config_wiring() {
97 cfg.mm.block_size_magnitude = 18; // 256 KiB
98 cfg.fiber.stack_size = 256U * 1024U;
99 cfg.limits.string_max_len = 8;
100 cfg.limits.ns_name_max_len = 4;
101
102 srn_mm_t *mm = srn_mm_init(&cfg);
103 TEST_ASSERT(mm != nullptr);
104 TEST_CHECK(mm->block_size == ((size_t)1 << 18));
105
106 srn_engine_t *engine = srn_engine_make(mm, &cfg);
107 TEST_ASSERT(engine != nullptr);
108 MAKE_CONTEXT(engine, ctx);
109
110 // A keyword name reaching the configured string limit fails as an error
111 // value; a short one interns.
112 /* srn_value_t *too_long = srn_engine_intern_keyword(ctx, &absurd_metadata, "waytoolongforthis");
113 */
114 /* TEST_CHECK(TYPE(too_long) == VError); */
115 /* srn_value_t *ok = srn_engine_intern_keyword(ctx, &absurd_metadata, "ok"); */
116 /* TEST_CHECK(TYPE(ok) == VKeyword); */
117
118 // A namespace name within the configured limit is accepted. Names over the
119 // limit panic in `srn_namespace_get_or_create`, which this harness cannot
120 // observe.
121 srn_value_t *ns_name = srn_string_make(ctx, &absurd_metadata, "four");
122 TEST_ASSERT(TYPE(ns_name) == VString);
123 srn_error_t *err = nullptr;
124 srn_namespace_t *ns = srn_namespace_get_or_create(engine, AS_STRING(ns_name), &err);
125 TEST_CHECK(ns != nullptr);
126
127 // A zero per fiber stack size falls back to the configured default.
129 TEST_ASSERT(f != nullptr);
130 TEST_CHECK(srn_fiber_stack_size(f->stack) >= 256U * 1024U);
131
132 // Reap the never-run fiber while its struct (in the context block) is
133 // still alive, before the context that owns it is released.
135
136 RELEASE_CONTEXT(ctx);
137 SHUTDOWN_ENGINE(mm, engine);
138}
139
140// The bootstrap macros bring the whole runtime up and down, mm plus engine
141// from one config, the scheduler bound, and a teardown that reclaims every
142// context chain through the manager.
143static void test_runtime_macros() {
144 SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, nullptr);
145 MAKE_CONTEXT(engine, ctx);
146
147 (void)srn_fiber_spawn(ctx, config_wiring_fiber_entry, nullptr);
148 srn_sched_run(sched, 1);
149
150 RELEASE_CONTEXT(ctx);
152}
#define TEST_CHECK(cond)
Definition acutest.h:95
#define TEST_ASSERT(cond)
Definition acutest.h:117
#define RELEASE_CONTEXT(x)
Definition base.h:48
#define SHUTDOWN_ENGINE(mm, engine)
Definition base.h:40
#define MAKE_ENGINE(mm, engine)
Definition base.h:34
#define MAKE_CONTEXT(engine, x)
Definition base.h:44
#define SRN_CONFIG_DEFAULTS
srn_metadata_t absurd_metadata
We use this for testing. Defined once in core.c.
Definition core.c:26
#define TYPE(value_ref)
Definition core.h:143
@ VString
Definition core.h:101
#define AS_STRING(value_ref)
Definition core.h:154
srn_mm_t * srn_mm_init(const srn_configuration_t *config)
Initialize the memory manager, this function will panic on error.
Definition default.c:337
srn_engine_t * srn_engine_make(srn_mm_t *mm, const srn_configuration_t *config)
Create the engine over mm, copying config (the runtime's knobs) into it.
Definition engine.c:103
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
AI Generated (🤦) Fiber subsystem overview.
static size_t srn_fiber_stack_size(srn_fiber_stack_t s)
Definition fiber.h:622
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
Definition fiber.h:171
srn_namespace_t * srn_namespace_get_or_create(srn_engine_t *engine, srn_string_t *name, srn_error_t **err)
Create a new and empty namespace if it is not already created in the engine, if it exists,...
Definition namespaces.c:30
A namespace is an isolation for names nad technically a compilation unit.
static void test_ns_get_twice()
Definition ns_tests.h:61
static void test_config_wiring()
Definition ns_tests.h:95
static void test_ns_get_or_create()
Definition ns_tests.h:35
static srn_fiber_result_t config_wiring_fiber_entry(srn_context_t *ctx, void *arg)
Definition ns_tests.h:86
static void test_runtime_macros()
Definition ns_tests.h:143
#define SERENE_RUNTIME_SHUTDOWN(engine)
Tear down what SERENE_RUNTIME_INIT brought up, in reverse order, the engine (reactor,...
Definition runtime.h:58
#define SERENE_RUNTIME_INIT_WITH_SCHED(engine, sched, config)
SERENE_RUNTIME_INIT plus a sched variable bound to the engine's scheduler, which every run and fiber ...
Definition runtime.h:46
void srn_sched_shutdown(srn_scheduler_t *sched)
The one stop tear down of the fiber subsystem, should be called once srn_sched_run has returned.
Definition scheduler.c:333
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
void * arg
srn_value_t * srn_string_make(srn_context_t *ctx, srn_metadata_t *metadata, const char *src)
Create a string from a null terminated C string.
Definition strings.c:51
bool srn_string_eq(const srn_string_t *a, const srn_string_t *b)
Definition strings.c:79
Every runtime knob, in one place.
srn_fiber_config_t fiber
srn_limits_config_t limits
srn_mm_config_t mm
Engine is a structure to own the long living and main pieces of the compiler.
Definition engine.h:54
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
size_t stack_size
Size of every fiber stack, in bytes.
srn_fiber_stack_t stack
Definition fiber.h:266
size_t ns_name_max_len
Longest namespace name accepted, in bytes.
size_t string_max_len
Largest string accepted, in bytes.
size_t block_size_magnitude
Magnitude of one block the arena hands out from.
Main memory manager structure that will own all the allocated blocks and data.
Definition interface.h:112
size_t block_size
Definition interface.h:127
srn_string_t * name
Definition namespaces.h:40
srn_context_t * root_context
Definition namespaces.h:45
srn_term_t * node
The top level node of the namespace.
Definition namespaces.h:56
#define UNUSED(x)
Definition utils.h:45