trackler 2.0.8.19 → 2.0.8.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/common/exercises/phone-number/canonical-data.json +2 -2
- data/lib/trackler/version.rb +1 -1
- data/tracks/c/config.json +7 -0
- data/tracks/c/exercises/react/makefile +16 -0
- data/tracks/c/exercises/react/src/example.c +185 -0
- data/tracks/c/exercises/react/src/react.h +29 -0
- data/tracks/c/exercises/react/test/test_react.c +324 -0
- data/tracks/c/exercises/react/test/vendor/unity.c +1300 -0
- data/tracks/c/exercises/react/test/vendor/unity.h +274 -0
- data/tracks/c/exercises/react/test/vendor/unity_internals.h +701 -0
- data/tracks/csharp/.travis.yml +2 -9
- data/tracks/csharp/appveyor.yml +3 -3
- data/tracks/csharp/build.cake +13 -4
- data/tracks/csharp/build.ps1 +56 -164
- data/tracks/csharp/build.sh +33 -78
- data/tracks/csharp/circle.yml +2 -4
- data/tracks/csharp/config.json +2 -1
- data/tracks/csharp/exercises/leap/LeapTest.cs +8 -8
- data/tracks/csharp/generators/CanonicalData.cs +19 -0
- data/tracks/csharp/generators/CanonicalDataCase.cs +24 -0
- data/tracks/csharp/generators/CanonicalDataCaseJsonConverter.cs +32 -0
- data/tracks/csharp/generators/CanonicalDataCasesJsonConverter.cs +30 -0
- data/tracks/csharp/generators/CanonicalDataParser.cs +28 -0
- data/tracks/csharp/generators/ExerciseCollection.cs +23 -0
- data/tracks/csharp/generators/Exercises/Exercise.cs +14 -0
- data/tracks/csharp/generators/Exercises/LeapExercise.cs +35 -0
- data/tracks/csharp/generators/Generators.csproj +12 -0
- data/tracks/csharp/generators/Generators.csproj.user +6 -0
- data/tracks/csharp/generators/Generators.sln +22 -0
- data/tracks/csharp/generators/Program.cs +59 -0
- data/tracks/csharp/generators/TestClass.cs +13 -0
- data/tracks/csharp/generators/TestClassRenderer.cs +36 -0
- data/tracks/csharp/generators/TestMethod.cs +9 -0
- data/tracks/csharp/generators/TestMethodNameTransformer.cs +11 -0
- data/tracks/csharp/generators/TestMethodRenderer.cs +18 -0
- data/tracks/csharp/generators/To.cs +7 -0
- data/tracks/csharp/generators/generate.ps1 +2 -0
- data/tracks/csharp/generators/generate.sh +4 -0
- data/tracks/delphi/config.json +8 -0
- data/tracks/delphi/exercises/phone-number/uPhoneNumberExample.pas +6 -6
- data/tracks/delphi/exercises/phone-number/uPhoneNumberTests.pas +28 -17
- data/tracks/delphi/exercises/roman-numerals/RomanNumerals.dpr +60 -0
- data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsExample.pas +49 -0
- data/tracks/delphi/exercises/roman-numerals/uRomanNumeralsTest.pas +216 -0
- data/tracks/elixir/config.json +22 -0
- data/tracks/elixir/exercises/poker/example.exs +136 -0
- data/tracks/elixir/exercises/poker/poker.exs +34 -0
- data/tracks/elixir/exercises/poker/poker_test.exs +217 -0
- data/tracks/elixir/exercises/protein-translation/example.exs +62 -0
- data/tracks/elixir/exercises/protein-translation/protein_translation.exs +34 -0
- data/tracks/elixir/exercises/protein-translation/protein_translation_test.exs +87 -0
- data/tracks/elixir/exercises/say/example.exs +139 -0
- data/tracks/elixir/exercises/say/say.exs +8 -0
- data/tracks/elixir/exercises/say/say_test.exs +85 -0
- data/tracks/go/exercises/robot-name/example.go +2 -0
- data/tracks/go/exercises/robot-name/robot_name_test.go +9 -1
- data/tracks/go/exercises/roman-numerals/roman_numerals_test.go +4 -1
- data/tracks/go/exercises/saddle-points/saddle_points_test.go +6 -6
- data/tracks/php/config.json +7 -0
- data/tracks/php/exercises/grade-school/example.php +35 -0
- data/tracks/php/exercises/grade-school/grade-school_test.php +84 -0
- metadata +43 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb72b896068a0db09871303423eb36d77ae12e79
|
4
|
+
data.tar.gz: b4f173c7a80ecc1a8dad8b60f163a92085a97a82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36f010e19529f3ff4f39e0a8b3aa16ecbba03834b7fbc36a644e1abef9dc9e1d05e3bb17a81c3ffdecc2daeb9ed0d3c08d68387b1559cd8b3154bad7cf52a2bf
|
7
|
+
data.tar.gz: 9ebce40e4a533258b9920f11ae1354e29aeb926704bf074eb05733d13364335be3e93a993e6f8b3fd7422c131286c3a4d9d38c244ebbe5e0b4b8e8198d0838dc
|
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"exercise": "phone-number",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.2",
|
4
4
|
"cases": [
|
5
5
|
{
|
6
6
|
"description": "Cleanup user-entered phone numbers",
|
@@ -35,7 +35,7 @@
|
|
35
35
|
"expected": null
|
36
36
|
},
|
37
37
|
{
|
38
|
-
"description": "invalid when 11 digits",
|
38
|
+
"description": "invalid when 11 digits does not start with a 1",
|
39
39
|
"property": "clean",
|
40
40
|
"phrase": "21234567890",
|
41
41
|
"expected": null
|
data/lib/trackler/version.rb
CHANGED
data/tracks/c/config.json
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
CFLAGS = -std=c99
|
2
|
+
CFLAGS += -Wall
|
3
|
+
CFLAGS += -Wextra
|
4
|
+
CFLAGS += -pedantic
|
5
|
+
CFLAGS += -Werror
|
6
|
+
|
7
|
+
|
8
|
+
test: tests.out
|
9
|
+
@./tests.out
|
10
|
+
|
11
|
+
clean:
|
12
|
+
rm -f *.o *.out
|
13
|
+
|
14
|
+
tests.out: test/test_react.c src/react.c src/react.h
|
15
|
+
@echo Compiling $@
|
16
|
+
@cc $(CFLAGS) src/react.c test/vendor/unity.c test/test_react.c -o tests.out
|
@@ -0,0 +1,185 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include "react.h"
|
3
|
+
|
4
|
+
enum cell_kind {
|
5
|
+
kind_input,
|
6
|
+
kind_compute1,
|
7
|
+
kind_compute2,
|
8
|
+
};
|
9
|
+
|
10
|
+
struct child {
|
11
|
+
struct cell *cell;
|
12
|
+
struct child *next;
|
13
|
+
};
|
14
|
+
|
15
|
+
struct cb {
|
16
|
+
callback_id id;
|
17
|
+
callback f;
|
18
|
+
void *obj;
|
19
|
+
struct cb *next;
|
20
|
+
};
|
21
|
+
|
22
|
+
struct reactor {
|
23
|
+
struct child *first;
|
24
|
+
struct child *last;
|
25
|
+
};
|
26
|
+
|
27
|
+
struct cell {
|
28
|
+
struct reactor *reactor;
|
29
|
+
int value;
|
30
|
+
enum cell_kind kind;
|
31
|
+
struct cell *input1;
|
32
|
+
struct cell *input2;
|
33
|
+
compute1 compute1;
|
34
|
+
compute2 compute2;
|
35
|
+
struct cb *cb;
|
36
|
+
int callbacks_issued;
|
37
|
+
};
|
38
|
+
|
39
|
+
struct reactor *create_reactor()
|
40
|
+
{
|
41
|
+
return calloc(1, sizeof(struct reactor));
|
42
|
+
}
|
43
|
+
|
44
|
+
void destroy_reactor(struct reactor *r)
|
45
|
+
{
|
46
|
+
struct child *child = r->first;
|
47
|
+
while (child) {
|
48
|
+
struct cb *cb = child->cell->cb;
|
49
|
+
while (cb) {
|
50
|
+
struct cb *next_cb = cb->next;
|
51
|
+
free(cb);
|
52
|
+
cb = next_cb;
|
53
|
+
}
|
54
|
+
free(child->cell);
|
55
|
+
|
56
|
+
struct child *next = child->next;
|
57
|
+
free(child);
|
58
|
+
child = next;
|
59
|
+
}
|
60
|
+
free(r);
|
61
|
+
}
|
62
|
+
|
63
|
+
static void add_child(struct reactor *r, struct cell *cell)
|
64
|
+
{
|
65
|
+
struct child *child = calloc(1, sizeof(struct child));
|
66
|
+
child->cell = cell;
|
67
|
+
if (!r->first) {
|
68
|
+
r->first = child;
|
69
|
+
} else {
|
70
|
+
r->last->next = child;
|
71
|
+
}
|
72
|
+
r->last = child;
|
73
|
+
}
|
74
|
+
|
75
|
+
struct cell *create_input_cell(struct reactor *r, int initial_value)
|
76
|
+
{
|
77
|
+
struct cell *c = calloc(1, sizeof(struct cell));
|
78
|
+
add_child(r, c);
|
79
|
+
c->reactor = r;
|
80
|
+
c->kind = kind_input;
|
81
|
+
c->value = initial_value;
|
82
|
+
return c;
|
83
|
+
}
|
84
|
+
|
85
|
+
struct cell *create_compute1_cell(struct reactor *r, struct cell *input,
|
86
|
+
compute1 compute)
|
87
|
+
{
|
88
|
+
struct cell *c = calloc(1, sizeof(struct cell));
|
89
|
+
add_child(r, c);
|
90
|
+
c->reactor = r;
|
91
|
+
c->kind = kind_compute1;
|
92
|
+
c->input1 = input;
|
93
|
+
c->compute1 = compute;
|
94
|
+
c->value = compute(get_cell_value(input));
|
95
|
+
return c;
|
96
|
+
}
|
97
|
+
|
98
|
+
struct cell *create_compute2_cell(struct reactor *r, struct cell *input1,
|
99
|
+
struct cell *input2, compute2 compute)
|
100
|
+
{
|
101
|
+
struct cell *c = calloc(1, sizeof(struct cell));
|
102
|
+
add_child(r, c);
|
103
|
+
c->reactor = r;
|
104
|
+
c->kind = kind_compute2;
|
105
|
+
c->input1 = input1;
|
106
|
+
c->input2 = input2;
|
107
|
+
c->compute2 = compute;
|
108
|
+
c->value = compute(get_cell_value(input1), get_cell_value(input2));
|
109
|
+
return c;
|
110
|
+
}
|
111
|
+
|
112
|
+
int get_cell_value(struct cell *c)
|
113
|
+
{
|
114
|
+
return c->value;
|
115
|
+
}
|
116
|
+
|
117
|
+
static void propagate(struct cell *c)
|
118
|
+
{
|
119
|
+
int new_value;
|
120
|
+
switch (c->kind) {
|
121
|
+
case kind_compute1:
|
122
|
+
new_value = c->compute1(get_cell_value(c->input1));
|
123
|
+
break;
|
124
|
+
case kind_compute2:
|
125
|
+
new_value =
|
126
|
+
c->compute2(get_cell_value(c->input1), get_cell_value(c->input2));
|
127
|
+
break;
|
128
|
+
default:
|
129
|
+
return;
|
130
|
+
}
|
131
|
+
|
132
|
+
if (new_value != c->value) {
|
133
|
+
c->value = new_value;
|
134
|
+
for (struct cb * cb = c->cb; cb; cb = cb->next) {
|
135
|
+
cb->f(cb->obj, new_value);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
}
|
140
|
+
|
141
|
+
void set_cell_value(struct cell *c, int new_value)
|
142
|
+
{
|
143
|
+
c->value = new_value;
|
144
|
+
struct reactor *r = c->reactor;
|
145
|
+
|
146
|
+
// We take the very naive route of updating all cells.
|
147
|
+
// Traversing the tree and only updating the cells dependent on the just-changed cell is possible,
|
148
|
+
// but requires much more memory management to make each cell aware of its dependents.
|
149
|
+
for (struct child * child = r->first; child; child = child->next) {
|
150
|
+
propagate(child->cell);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
callback_id add_callback(struct cell *c, void *obj, callback f)
|
155
|
+
{
|
156
|
+
struct cb *cb = calloc(1, sizeof(struct cb));
|
157
|
+
cb->id = c->callbacks_issued++;
|
158
|
+
cb->next = c->cb;
|
159
|
+
cb->obj = obj;
|
160
|
+
cb->f = f;
|
161
|
+
c->cb = cb;
|
162
|
+
return cb->id;
|
163
|
+
}
|
164
|
+
|
165
|
+
void remove_callback(struct cell *c, callback_id to_remove)
|
166
|
+
{
|
167
|
+
if (!c->cb) {
|
168
|
+
return;
|
169
|
+
}
|
170
|
+
// this dummy starting node reduces code duplication,
|
171
|
+
// in case the ID to remove is at the head of the list.
|
172
|
+
struct cb dummy;
|
173
|
+
dummy.next = c->cb;
|
174
|
+
for (struct cb * prev = &dummy, *cb = c->cb; cb;
|
175
|
+
prev = prev->next, cb = cb->next) {
|
176
|
+
if (cb->id == to_remove) {
|
177
|
+
if (cb == c->cb) {
|
178
|
+
c->cb = cb->next;
|
179
|
+
}
|
180
|
+
prev->next = cb->next;
|
181
|
+
free(cb);
|
182
|
+
return;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#ifndef REACT_H
|
2
|
+
#define REACT_H
|
3
|
+
|
4
|
+
struct reactor;
|
5
|
+
struct cell;
|
6
|
+
|
7
|
+
typedef int (*compute1) (int);
|
8
|
+
typedef int (*compute2) (int, int);
|
9
|
+
|
10
|
+
struct reactor *create_reactor();
|
11
|
+
// destroy_reactor should free all cells created under that reactor.
|
12
|
+
void destroy_reactor(struct reactor *);
|
13
|
+
|
14
|
+
struct cell *create_input_cell(struct reactor *, int initial_value);
|
15
|
+
struct cell *create_compute1_cell(struct reactor *, struct cell *, compute1);
|
16
|
+
struct cell *create_compute2_cell(struct reactor *, struct cell *,
|
17
|
+
struct cell *, compute2);
|
18
|
+
|
19
|
+
int get_cell_value(struct cell *);
|
20
|
+
void set_cell_value(struct cell *, int new_value);
|
21
|
+
|
22
|
+
typedef void (*callback) (void *, int);
|
23
|
+
typedef int callback_id;
|
24
|
+
|
25
|
+
// The callback should be called with the same void * given in add_callback.
|
26
|
+
callback_id add_callback(struct cell *, void *, callback);
|
27
|
+
void remove_callback(struct cell *, callback_id);
|
28
|
+
|
29
|
+
#endif
|
@@ -0,0 +1,324 @@
|
|
1
|
+
#include <stddef.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include "vendor/unity.h"
|
4
|
+
#include "../src/react.h"
|
5
|
+
|
6
|
+
void test_input_cells_have_value(void)
|
7
|
+
{
|
8
|
+
struct reactor *r = create_reactor();
|
9
|
+
struct cell *input = create_input_cell(r, 2);
|
10
|
+
|
11
|
+
TEST_ASSERT_EQUAL_INT(2, get_cell_value(input));
|
12
|
+
|
13
|
+
destroy_reactor(r);
|
14
|
+
}
|
15
|
+
|
16
|
+
void test_input_cells_value_can_be_set(void)
|
17
|
+
{
|
18
|
+
struct reactor *r = create_reactor();
|
19
|
+
struct cell *input = create_input_cell(r, 4);
|
20
|
+
|
21
|
+
set_cell_value(input, 20);
|
22
|
+
TEST_ASSERT_EQUAL_INT(20, get_cell_value(input));
|
23
|
+
|
24
|
+
destroy_reactor(r);
|
25
|
+
}
|
26
|
+
|
27
|
+
static int plus1(int x)
|
28
|
+
{
|
29
|
+
return x + 1;
|
30
|
+
}
|
31
|
+
|
32
|
+
void test_compute_cells_calculate_initial_value(void)
|
33
|
+
{
|
34
|
+
struct reactor *r = create_reactor();
|
35
|
+
struct cell *input = create_input_cell(r, 1);
|
36
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
37
|
+
|
38
|
+
TEST_ASSERT_EQUAL_INT(2, get_cell_value(output));
|
39
|
+
|
40
|
+
destroy_reactor(r);
|
41
|
+
}
|
42
|
+
|
43
|
+
static int concat_digits(int a, int b)
|
44
|
+
{
|
45
|
+
return b * 10 + a;
|
46
|
+
}
|
47
|
+
|
48
|
+
void test_compute_cells_take_inputs_in_the_right_order(void)
|
49
|
+
{
|
50
|
+
struct reactor *r = create_reactor();
|
51
|
+
struct cell *one = create_input_cell(r, 1);
|
52
|
+
struct cell *two = create_input_cell(r, 2);
|
53
|
+
struct cell *output = create_compute2_cell(r, one, two, concat_digits);
|
54
|
+
|
55
|
+
TEST_ASSERT_EQUAL_INT(21, get_cell_value(output));
|
56
|
+
|
57
|
+
destroy_reactor(r);
|
58
|
+
}
|
59
|
+
|
60
|
+
void test_compute_cells_update_value_when_dependencies_are_changed(void)
|
61
|
+
{
|
62
|
+
struct reactor *r = create_reactor();
|
63
|
+
struct cell *input = create_input_cell(r, 1);
|
64
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
65
|
+
|
66
|
+
set_cell_value(input, 3);
|
67
|
+
TEST_ASSERT_EQUAL_INT(4, get_cell_value(output));
|
68
|
+
|
69
|
+
destroy_reactor(r);
|
70
|
+
}
|
71
|
+
|
72
|
+
static int times2(int x)
|
73
|
+
{
|
74
|
+
return x * 2;
|
75
|
+
}
|
76
|
+
|
77
|
+
static int times30(int x)
|
78
|
+
{
|
79
|
+
return x * 30;
|
80
|
+
}
|
81
|
+
|
82
|
+
static int plus(int x, int y)
|
83
|
+
{
|
84
|
+
return x + y;
|
85
|
+
}
|
86
|
+
|
87
|
+
void test_compute_cells_can_depend_on_other_compute_cells(void)
|
88
|
+
{
|
89
|
+
struct reactor *r = create_reactor();
|
90
|
+
struct cell *input = create_input_cell(r, 1);
|
91
|
+
struct cell *times_two = create_compute1_cell(r, input, times2);
|
92
|
+
struct cell *times_thirty = create_compute1_cell(r, input, times30);
|
93
|
+
struct cell *output = create_compute2_cell(r, times_two, times_thirty, plus);
|
94
|
+
|
95
|
+
TEST_ASSERT_EQUAL_INT(32, get_cell_value(output));
|
96
|
+
set_cell_value(input, 3);
|
97
|
+
TEST_ASSERT_EQUAL_INT(96, get_cell_value(output));
|
98
|
+
|
99
|
+
destroy_reactor(r);
|
100
|
+
}
|
101
|
+
|
102
|
+
struct cbinfo {
|
103
|
+
int last_value;
|
104
|
+
int times_called;
|
105
|
+
};
|
106
|
+
|
107
|
+
static void cb_spy(void *obj, int v)
|
108
|
+
{
|
109
|
+
struct cbinfo *cbinfo = (struct cbinfo *)obj;
|
110
|
+
cbinfo->last_value = v;
|
111
|
+
++cbinfo->times_called;
|
112
|
+
}
|
113
|
+
|
114
|
+
void test_compute_cells_fire_callbacks(void)
|
115
|
+
{
|
116
|
+
struct reactor *r = create_reactor();
|
117
|
+
struct cell *input = create_input_cell(r, 1);
|
118
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
119
|
+
|
120
|
+
struct cbinfo cbinfo = { -1, 0 };
|
121
|
+
add_callback(output, &cbinfo, cb_spy);
|
122
|
+
|
123
|
+
set_cell_value(input, 3);
|
124
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo.times_called);
|
125
|
+
TEST_ASSERT_EQUAL_INT(4, cbinfo.last_value);
|
126
|
+
|
127
|
+
destroy_reactor(r);
|
128
|
+
}
|
129
|
+
|
130
|
+
static void cb_noop(void *obj, int v)
|
131
|
+
{
|
132
|
+
(void)obj;
|
133
|
+
(void)v;
|
134
|
+
}
|
135
|
+
|
136
|
+
void test_compute_cells_dont_access_callback_obj(void)
|
137
|
+
{
|
138
|
+
struct reactor *r = create_reactor();
|
139
|
+
struct cell *input = create_input_cell(r, 1);
|
140
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
141
|
+
|
142
|
+
add_callback(output, NULL, cb_noop);
|
143
|
+
|
144
|
+
set_cell_value(input, 3);
|
145
|
+
|
146
|
+
destroy_reactor(r);
|
147
|
+
}
|
148
|
+
|
149
|
+
static int big_if_three(int x)
|
150
|
+
{
|
151
|
+
return x < 3 ? 111 : 222;
|
152
|
+
}
|
153
|
+
|
154
|
+
void test_callbacks_only_fire_on_change(void)
|
155
|
+
{
|
156
|
+
struct reactor *r = create_reactor();
|
157
|
+
struct cell *input = create_input_cell(r, 1);
|
158
|
+
struct cell *output = create_compute1_cell(r, input, big_if_three);
|
159
|
+
|
160
|
+
struct cbinfo cbinfo = { -1, 0 };
|
161
|
+
add_callback(output, &cbinfo, cb_spy);
|
162
|
+
|
163
|
+
set_cell_value(input, 2);
|
164
|
+
TEST_ASSERT_EQUAL_INT(0, cbinfo.times_called);
|
165
|
+
|
166
|
+
set_cell_value(input, 4);
|
167
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo.times_called);
|
168
|
+
TEST_ASSERT_EQUAL_INT(222, cbinfo.last_value);
|
169
|
+
|
170
|
+
destroy_reactor(r);
|
171
|
+
}
|
172
|
+
|
173
|
+
void test_callbacks_can_be_added_and_removed(void)
|
174
|
+
{
|
175
|
+
struct reactor *r = create_reactor();
|
176
|
+
struct cell *input = create_input_cell(r, 11);
|
177
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
178
|
+
|
179
|
+
struct cbinfo cbinfo1 = { -1, 0 };
|
180
|
+
callback_id cb1 = add_callback(output, &cbinfo1, cb_spy);
|
181
|
+
struct cbinfo cbinfo2 = { -1, 0 };
|
182
|
+
add_callback(output, &cbinfo2, cb_spy);
|
183
|
+
|
184
|
+
set_cell_value(input, 31);
|
185
|
+
|
186
|
+
remove_callback(output, cb1);
|
187
|
+
struct cbinfo cbinfo3 = { -1, 0 };
|
188
|
+
add_callback(output, &cbinfo3, cb_spy);
|
189
|
+
|
190
|
+
set_cell_value(input, 41);
|
191
|
+
|
192
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo1.times_called);
|
193
|
+
TEST_ASSERT_EQUAL_INT(32, cbinfo1.last_value);
|
194
|
+
TEST_ASSERT_EQUAL_INT(2, cbinfo2.times_called);
|
195
|
+
TEST_ASSERT_EQUAL_INT(42, cbinfo2.last_value);
|
196
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo3.times_called);
|
197
|
+
TEST_ASSERT_EQUAL_INT(42, cbinfo3.last_value);
|
198
|
+
|
199
|
+
destroy_reactor(r);
|
200
|
+
}
|
201
|
+
|
202
|
+
void test_removing_most_recent_callback(void)
|
203
|
+
{
|
204
|
+
struct reactor *r = create_reactor();
|
205
|
+
struct cell *input = create_input_cell(r, 11);
|
206
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
207
|
+
|
208
|
+
struct cbinfo cbinfo1 = { -1, 0 };
|
209
|
+
add_callback(output, &cbinfo1, cb_spy);
|
210
|
+
struct cbinfo cbinfo2 = { -1, 0 };
|
211
|
+
callback_id cb2 = add_callback(output, &cbinfo2, cb_spy);
|
212
|
+
remove_callback(output, cb2);
|
213
|
+
|
214
|
+
set_cell_value(input, 31);
|
215
|
+
|
216
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo1.times_called);
|
217
|
+
TEST_ASSERT_EQUAL_INT(32, cbinfo1.last_value);
|
218
|
+
TEST_ASSERT_EQUAL_INT(0, cbinfo2.times_called);
|
219
|
+
|
220
|
+
destroy_reactor(r);
|
221
|
+
}
|
222
|
+
|
223
|
+
void test_removing_a_callback_multiple_times(void)
|
224
|
+
{
|
225
|
+
struct reactor *r = create_reactor();
|
226
|
+
struct cell *input = create_input_cell(r, 11);
|
227
|
+
struct cell *output = create_compute1_cell(r, input, plus1);
|
228
|
+
|
229
|
+
struct cbinfo cbinfo1 = { -1, 0 };
|
230
|
+
callback_id cb1 = add_callback(output, &cbinfo1, cb_spy);
|
231
|
+
struct cbinfo cbinfo2 = { -1, 0 };
|
232
|
+
add_callback(output, &cbinfo2, cb_spy);
|
233
|
+
for (int i = 0; i < 10; ++i) {
|
234
|
+
remove_callback(output, cb1);
|
235
|
+
}
|
236
|
+
|
237
|
+
set_cell_value(input, 2);
|
238
|
+
|
239
|
+
TEST_ASSERT_EQUAL_INT(0, cbinfo1.times_called);
|
240
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo2.times_called);
|
241
|
+
TEST_ASSERT_EQUAL_INT(3, cbinfo2.last_value);
|
242
|
+
|
243
|
+
destroy_reactor(r);
|
244
|
+
}
|
245
|
+
|
246
|
+
static int minus1(int x)
|
247
|
+
{
|
248
|
+
return x - 1;
|
249
|
+
}
|
250
|
+
|
251
|
+
static int times(int x, int y)
|
252
|
+
{
|
253
|
+
return x * y;
|
254
|
+
}
|
255
|
+
|
256
|
+
void test_callbacks_only_called_once_even_if_multiple_inputs_change(void)
|
257
|
+
{
|
258
|
+
struct reactor *r = create_reactor();
|
259
|
+
struct cell *input = create_input_cell(r, 1);
|
260
|
+
struct cell *plus_one = create_compute1_cell(r, input, plus1);
|
261
|
+
struct cell *minus_one1 = create_compute1_cell(r, input, minus1);
|
262
|
+
struct cell *minus_one2 = create_compute1_cell(r, minus_one1, minus1);
|
263
|
+
struct cell *output = create_compute2_cell(r, plus_one, minus_one2, times);
|
264
|
+
|
265
|
+
struct cbinfo cbinfo = { -1, 0 };
|
266
|
+
add_callback(output, &cbinfo, cb_spy);
|
267
|
+
|
268
|
+
set_cell_value(input, 4);
|
269
|
+
|
270
|
+
TEST_ASSERT_EQUAL_INT(1, cbinfo.times_called);
|
271
|
+
TEST_ASSERT_EQUAL_INT(10, cbinfo.last_value);
|
272
|
+
|
273
|
+
destroy_reactor(r);
|
274
|
+
}
|
275
|
+
|
276
|
+
static int minus(int x, int y)
|
277
|
+
{
|
278
|
+
return x - y;
|
279
|
+
}
|
280
|
+
|
281
|
+
void test_callbacks_not_called_if_inputs_change_but_output_doesnt(void)
|
282
|
+
{
|
283
|
+
struct reactor *r = create_reactor();
|
284
|
+
struct cell *input = create_input_cell(r, 1);
|
285
|
+
struct cell *plus_one = create_compute1_cell(r, input, plus1);
|
286
|
+
struct cell *minus_one = create_compute1_cell(r, input, minus1);
|
287
|
+
struct cell *always_two =
|
288
|
+
create_compute2_cell(r, plus_one, minus_one, minus);
|
289
|
+
|
290
|
+
struct cbinfo cbinfo = { -1, 0 };
|
291
|
+
add_callback(always_two, &cbinfo, cb_spy);
|
292
|
+
|
293
|
+
for (int i = 0; i < 10; ++i) {
|
294
|
+
set_cell_value(input, i);
|
295
|
+
}
|
296
|
+
|
297
|
+
TEST_ASSERT_EQUAL_INT(0, cbinfo.times_called);
|
298
|
+
|
299
|
+
destroy_reactor(r);
|
300
|
+
}
|
301
|
+
|
302
|
+
int main(void)
|
303
|
+
{
|
304
|
+
UnityBegin("test/test_react.c");
|
305
|
+
|
306
|
+
RUN_TEST(test_input_cells_have_value);
|
307
|
+
RUN_TEST(test_input_cells_value_can_be_set);
|
308
|
+
RUN_TEST(test_compute_cells_calculate_initial_value);
|
309
|
+
RUN_TEST(test_compute_cells_take_inputs_in_the_right_order);
|
310
|
+
RUN_TEST(test_compute_cells_update_value_when_dependencies_are_changed);
|
311
|
+
RUN_TEST(test_compute_cells_can_depend_on_other_compute_cells);
|
312
|
+
RUN_TEST(test_compute_cells_fire_callbacks);
|
313
|
+
RUN_TEST(test_compute_cells_dont_access_callback_obj);
|
314
|
+
RUN_TEST(test_callbacks_only_fire_on_change);
|
315
|
+
RUN_TEST(test_callbacks_can_be_added_and_removed);
|
316
|
+
RUN_TEST(test_removing_most_recent_callback);
|
317
|
+
RUN_TEST(test_removing_a_callback_multiple_times);
|
318
|
+
RUN_TEST(test_callbacks_only_called_once_even_if_multiple_inputs_change);
|
319
|
+
RUN_TEST(test_callbacks_not_called_if_inputs_change_but_output_doesnt);
|
320
|
+
|
321
|
+
UnityEnd();
|
322
|
+
|
323
|
+
return 0;
|
324
|
+
}
|