Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
seq_tests.h File Reference
#include <stdio.h>
#include <serene/rt/context.h>
#include <serene/rt/impl/seq.h>
#include "base.h"
Include dependency graph for seq_tests.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  seq_dummy

Macros

#define SEQ_TESTS(X)
#define SEQ_TEST_LOG(...)

Typedefs

typedef struct seq_dummy seq_dummy

Functions

static void test_seq_empty ()
void test_seq_push_less_than_32 ()
void test_seq_push_more_than_32 ()
static void test_seq_branching_push ()
 Two pushes branched off one head must not see each other's element.
static void test_seq_branching_promotion ()
 Two branches that each promote their own diverging tail into the same root slot must not overwrite each other.

Macro Definition Documentation

◆ SEQ_TEST_LOG

#define SEQ_TEST_LOG ( ...)

Definition at line 37 of file seq_tests.h.

◆ SEQ_TESTS

#define SEQ_TESTS ( X)
Value:
X("seq::empty", test_seq_empty), X("seq::push_less_than_32", test_seq_push_less_than_32), \
X("seq::push_more_than_32", test_seq_push_more_than_32), \
X("seq::branching_push", test_seq_branching_push), \
X("seq::branching_promotion", test_seq_branching_promotion)
static void test_seq_branching_promotion()
Two branches that each promote their own diverging tail into the same root slot must not overwrite ea...
Definition seq_tests.h:170
void test_seq_push_more_than_32()
Definition seq_tests.h:83
static void test_seq_branching_push()
Two pushes branched off one head must not see each other's element.
Definition seq_tests.h:131
void test_seq_push_less_than_32()
Definition seq_tests.h:59
static void test_seq_empty()
Definition seq_tests.h:45

Definition at line 28 of file seq_tests.h.

28#define SEQ_TESTS(X) \
29 X("seq::empty", test_seq_empty), X("seq::push_less_than_32", test_seq_push_less_than_32), \
30 X("seq::push_more_than_32", test_seq_push_more_than_32), \
31 X("seq::branching_push", test_seq_branching_push), \
32 X("seq::branching_promotion", test_seq_branching_promotion)

Typedef Documentation

◆ seq_dummy

typedef struct seq_dummy seq_dummy

Function Documentation

◆ test_seq_branching_promotion()

void test_seq_branching_promotion ( )
static

Two branches that each promote their own diverging tail into the same root slot must not overwrite each other.

96 shared elements put the base at a 64 element tree plus a full tail; 33 pushes per branch force two promotions each, the second landing in the same fringe slot of a root that used to be shared.

Definition at line 170 of file seq_tests.h.

170 {
171 MAKE_ENGINE(mm, engine);
172 MAKE_CONTEXT(engine, ctx);
173
174 int *vals = ALLOCN(ctx, int, 96);
175 seq_t s = seq_empty(ctx);
176 for (int i = 0; i < 96; i++) {
177 vals[i] = i;
178 s = seq_push(&s, (seq_elem_t)&vals[i]);
179 }
180
181 int *b1_vals = ALLOCN(ctx, int, 33);
182 int *b2_vals = ALLOCN(ctx, int, 33);
183 seq_t b1 = s;
184 seq_t b2 = s;
185 for (int i = 0; i < 33; i++) {
186 b1_vals[i] = 1000 + i;
187 b2_vals[i] = 2000 + i;
188 b1 = seq_push(&b1, (seq_elem_t)&b1_vals[i]);
189 b2 = seq_push(&b2, (seq_elem_t)&b2_vals[i]);
190 }
191
192 TEST_CHECK(s.len == 96);
193 TEST_CHECK(b1.len == 129);
194 TEST_CHECK(b2.len == 129);
195
196 // The shared prefix must read the same through every head.
197 for (int i = 0; i < 96; i++) {
198 TEST_CHECK(seq_get(&s, (size_t)i).data == (seq_elem_t)&vals[i]);
199 TEST_CHECK(seq_get(&b1, (size_t)i).data == (seq_elem_t)&vals[i]);
200 TEST_CHECK(seq_get(&b2, (size_t)i).data == (seq_elem_t)&vals[i]);
201 }
202
203 // Each branch must read only its own suffix.
204 for (int i = 0; i < 33; i++) {
205 TEST_CHECK(seq_get(&b1, (size_t)(96 + i)).data == (seq_elem_t)&b1_vals[i]);
206 TEST_CHECK(seq_get(&b2, (size_t)(96 + i)).data == (seq_elem_t)&b2_vals[i]);
207 }
208
209 RELEASE_CONTEXT(ctx);
210 SHUTDOWN_ENGINE(mm, engine);
211}
#define TEST_CHECK(cond)
Definition acutest.h:95
#define RELEASE_CONTEXT(x)
Definition base.h:46
#define SHUTDOWN_ENGINE(mm, engine)
Definition base.h:38
#define MAKE_ENGINE(mm, engine)
Definition base.h:32
#define MAKE_CONTEXT(engine, x)
Definition base.h:42
#define ALLOCN(ctx, T, N)
Definition context.h:85
seq_t seq_empty(const srn_context_t *ctx)
Create an empty seq pinned to ctx.
Definition seq.c:100
seq_lookup_result_t seq_get(const seq_t *seq, size_t n)
Negative index is not supported.
Definition seq.c:205
seq_t seq_push(const seq_t *seq, seq_elem_t x)
Definition seq.c:113
void * seq_elem_t
We use generic pointers to refer to internal nodes, leaf nodes and even elements.
Definition seq.h:131
Definition seq.h:155
size_t len
logical length.
Definition seq.h:161
Here is the call graph for this function:

◆ test_seq_branching_push()

void test_seq_branching_push ( )
static

Two pushes branched off one head must not see each other's element.

The tail buffer is shared between versions, so without copy on write the second push clobbers the first branch's slot.

Definition at line 131 of file seq_tests.h.

131 {
132 MAKE_ENGINE(mm, engine);
133 MAKE_CONTEXT(engine, ctx);
134
135 seq_t s = seq_empty(ctx);
136 for (int i = 0; i < 5; i++) {
137 seq_dummy *d = ALLOC(ctx, seq_dummy);
138 d->foo = i;
139 d->bar = i;
140 s = seq_push(&s, (seq_elem_t)d);
141 }
142
143 seq_dummy da = {.foo = 100, .bar = 1};
144 seq_dummy db = {.foo = 200, .bar = 2};
145
146 seq_t b1 = seq_push(&s, (seq_elem_t)&da);
147 seq_t b2 = seq_push(&s, (seq_elem_t)&db);
148
149 TEST_CHECK(s.len == 5);
150 TEST_CHECK(b1.len == 6);
151 TEST_CHECK(b2.len == 6);
152
153 seq_lookup_result_t r1 = seq_get(&b1, 5);
154 TEST_CHECK(r1.maybe_error == nullptr);
155 TEST_CHECK(r1.data == (seq_elem_t)&da);
156
157 seq_lookup_result_t r2 = seq_get(&b2, 5);
158 TEST_CHECK(r2.maybe_error == nullptr);
159 TEST_CHECK(r2.data == (seq_elem_t)&db);
160
161 RELEASE_CONTEXT(ctx);
162 SHUTDOWN_ENGINE(mm, engine);
163}
#define ALLOC(ctx, T)
Definition context.h:84
seq_elem_t data
Definition seq.h:135
Here is the call graph for this function:

◆ test_seq_empty()

void test_seq_empty ( )
static

Definition at line 45 of file seq_tests.h.

45 {
46 MAKE_ENGINE(mm, engine);
47 MAKE_CONTEXT(engine, ctx);
48 auto s = seq_empty(ctx);
49
50 TEST_CHECK(s.len == 0);
51 TEST_CHECK(s.tail_len == 0);
52 TEST_CHECK(s.root == nullptr);
53 TEST_CHECK(s.maybe_error == nullptr);
54
55 RELEASE_CONTEXT(ctx);
56 SHUTDOWN_ENGINE(mm, engine);
57}
Here is the call graph for this function:

◆ test_seq_push_less_than_32()

void test_seq_push_less_than_32 ( )

Definition at line 59 of file seq_tests.h.

59 {
60 MAKE_ENGINE(mm, engine);
61 MAKE_CONTEXT(engine, ctx);
62
63 seq_dummy d = {.foo = 10, .bar = 20}; // NOLINT
64 auto s = seq_empty(ctx);
65 auto s1 = seq_push(&s, (seq_elem_t)&d);
66 TEST_CHECK(s.len == 0);
67 TEST_CHECK(s.tail_len == 0);
68 TEST_CHECK(s.root == nullptr);
69 TEST_CHECK(s.maybe_error == nullptr);
70
71 TEST_CHECK(s1.len == 1);
72 TEST_CHECK(s1.tail_len == 1);
73 TEST_CHECK(s1.root == nullptr);
74 TEST_CHECK(s1.maybe_error == nullptr);
75 seq_dummy *d1 = (seq_dummy *)s1.tail[0];
76 TEST_CHECK(d1->foo == 10);
77 TEST_CHECK(d1->bar == 20);
78
79 RELEASE_CONTEXT(ctx);
80 SHUTDOWN_ENGINE(mm, engine);
81}
Here is the call graph for this function:

◆ test_seq_push_more_than_32()

void test_seq_push_more_than_32 ( )

Definition at line 83 of file seq_tests.h.

83 {
84 MAKE_ENGINE(mm, engine);
85 MAKE_CONTEXT(engine, ctx);
86
87 seq_t s = seq_empty(ctx);
88
89 for (int i = 0; i < 2000; i++) {
90
91 seq_dummy *d = ALLOC(ctx, seq_dummy);
92 d->foo = i;
93 d->bar = 3000 - i;
94 s = seq_push(&s, (seq_elem_t)d);
95 }
96
97 TEST_CHECK(s.len == 2000);
98 TEST_CHECK(s.tail_len == 16);
99 TEST_CHECK(s.root != nullptr);
100 TEST_CHECK(s.maybe_error == nullptr);
101
102 seq_dummy *d1 = (seq_dummy *)s.tail[0];
103
104 ASSERT_NOT_NULL(d1);
105 TEST_CHECK(d1->foo == 1984);
106 TEST_CHECK(d1->bar == 3000 - d1->foo);
107
108 seq_dummy *d2 = (seq_dummy *)s.tail[s.tail_len - 1];
109 ASSERT_NOT_NULL(d2);
110 TEST_CHECK(d2->foo == 1999);
111 TEST_CHECK(d2->bar == 3000 - d2->foo);
112
113 for (int i = 0; i < 2000; i++) {
114 seq_lookup_result_t res = seq_get(&s, (size_t)i);
115 TEST_CHECK(res.maybe_error == nullptr);
117 seq_dummy *d = (seq_dummy *)res.data;
118
119 SEQ_TEST_LOG("%d %d %d", i, d->foo, d->bar);
120 TEST_CHECK(d->foo == i);
121 TEST_CHECK(d->bar == 3000 - i);
122 };
123
124 RELEASE_CONTEXT(ctx);
125 SHUTDOWN_ENGINE(mm, engine);
126}
#define ASSERT_NOT_NULL(x)
Definition base.h:30
#define SEQ_TEST_LOG(...)
Definition seq_tests.h:37
seq_node_t * root
NULL means “all data is in tail”
Definition seq.h:167
seq_elem_t * tail
small tail array for fast push/pop.
Definition seq.h:170
uint16_t tail_len
0..SEQ_BR
Definition seq.h:163
Here is the call graph for this function: