trackler 2.0.8.19 → 2.0.8.20
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|