@@ -99,20 +99,49 @@ fn error_setting_a_compute_cell() {
99
99
assert ! ( reactor. set_value( output, 3 ) . is_err( ) ) ;
100
100
}
101
101
102
+ /// A CallbackRecorder helps tests whether callbacks get called correctly.
103
+ /// You'll see it used in tests that deal with callbacks.
104
+ /// The names should be descriptive enough so that the tests make sense,
105
+ /// so it's not necessary to fully understand the implementation,
106
+ /// though you are welcome to.
107
+ struct CallbackRecorder {
108
+ // Note that this `Cell` is https://doc.rust-lang.org/std/cell/
109
+ // a mechanism to allow internal mutability,
110
+ // distinct from the cells (input cells, compute cells) in the reactor
111
+ value : std:: cell:: Cell < Option < isize > > ,
112
+ }
113
+
114
+ impl CallbackRecorder {
115
+ fn new ( ) -> Self {
116
+ CallbackRecorder {
117
+ value : std:: cell:: Cell :: new ( None ) ,
118
+ }
119
+ }
120
+
121
+ fn expect_to_have_been_called_with ( & self , v : isize ) {
122
+ assert_ne ! ( self . value. get( ) , None , "Callback was not called, but should have been" ) ;
123
+ assert_eq ! ( self . value. replace( None ) , Some ( v) , "Callback was called with incorrect value" ) ;
124
+ }
125
+
126
+ fn expect_not_to_have_been_called ( & self ) {
127
+ assert_eq ! ( self . value. get( ) , None , "Callback was called, but should not have been" ) ;
128
+ }
129
+
130
+ fn callback_called ( & self , v : isize ) {
131
+ assert_eq ! ( self . value. replace( Some ( v) ) , None , "Callback was called too many times; can't be called with {}" , v) ;
132
+ }
133
+ }
134
+
102
135
#[ test]
103
136
#[ ignore]
104
137
fn compute_cells_fire_callbacks ( ) {
105
- // This is a bit awkward, but the closure mutably borrows `values`.
106
- // So we have to end its borrow by taking reactor out of scope.
107
- let mut values = Vec :: new ( ) ;
108
- {
109
- let mut reactor = Reactor :: new ( ) ;
110
- let input = reactor. create_input ( 1 ) ;
111
- let output = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
112
- assert ! ( reactor. add_callback( output, |v| values. push( v) ) . is_ok( ) ) ;
113
- assert ! ( reactor. set_value( input, 3 ) . is_ok( ) ) ;
114
- }
115
- assert_eq ! ( values, vec![ 4 ] ) ;
138
+ let cb = CallbackRecorder :: new ( ) ;
139
+ let mut reactor = Reactor :: new ( ) ;
140
+ let input = reactor. create_input ( 1 ) ;
141
+ let output = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
142
+ assert ! ( reactor. add_callback( output, |v| cb. callback_called( v) ) . is_ok( ) ) ;
143
+ assert ! ( reactor. set_value( input, 3 ) . is_ok( ) ) ;
144
+ cb. expect_to_have_been_called_with ( 4 ) ;
116
145
}
117
146
118
147
#[ test]
@@ -127,95 +156,96 @@ fn error_adding_callback_to_nonexistent_cell() {
127
156
#[ test]
128
157
#[ ignore]
129
158
fn callbacks_only_fire_on_change ( ) {
130
- let mut values = Vec :: new ( ) ;
131
- {
132
- let mut reactor = Reactor :: new ( ) ;
133
- let input = reactor . create_input ( 1 ) ;
134
- let output = reactor. create_compute ( & [ input ] , |v| if v [ 0 ] < 3 { 111 } else { 222 } ) . unwrap ( ) ;
135
- assert ! ( reactor . add_callback ( output , |v| values . push ( v ) ) . is_ok ( ) ) ;
136
- assert ! ( reactor. set_value( input, 2 ) . is_ok( ) ) ;
137
- assert ! ( reactor . set_value ( input , 4 ) . is_ok ( ) ) ;
138
- }
139
- assert_eq ! ( values , vec! [ 222 ] ) ;
159
+ let cb = CallbackRecorder :: new ( ) ;
160
+ let mut reactor = Reactor :: new ( ) ;
161
+ let input = reactor . create_input ( 1 ) ;
162
+ let output = reactor . create_compute ( & [ input ] , |v| if v [ 0 ] < 3 { 111 } else { 222 } ) . unwrap ( ) ;
163
+ assert ! ( reactor. add_callback ( output , |v| cb . callback_called ( v ) ) . is_ok ( ) ) ;
164
+
165
+ assert ! ( reactor. set_value( input, 2 ) . is_ok( ) ) ;
166
+ cb . expect_not_to_have_been_called ( ) ;
167
+ assert ! ( reactor . set_value ( input , 4 ) . is_ok ( ) ) ;
168
+ cb . expect_to_have_been_called_with ( 222 ) ;
140
169
}
141
170
142
171
#[ test]
143
172
#[ ignore]
144
173
fn callbacks_can_be_added_and_removed ( ) {
145
- let mut values1 = Vec :: new ( ) ;
146
- let mut values2 = Vec :: new ( ) ;
147
- let mut values3 = Vec :: new ( ) ;
148
- {
149
- let mut reactor = Reactor :: new ( ) ;
150
- let input = reactor. create_input ( 11 ) ;
151
- let output = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
152
- let callback = reactor. add_callback ( output, |v| values1. push ( v) ) . unwrap ( ) ;
153
- assert ! ( reactor. add_callback( output, |v| values2. push( v) ) . is_ok( ) ) ;
154
- assert ! ( reactor. set_value( input, 31 ) . is_ok( ) ) ;
155
- assert ! ( reactor. remove_callback( output, callback) . is_ok( ) ) ;
156
- assert ! ( reactor. add_callback( output, |v| values3. push( v) ) . is_ok( ) ) ;
157
- assert ! ( reactor. set_value( input, 41 ) . is_ok( ) ) ;
158
- }
159
- assert_eq ! ( values1, vec![ 32 ] ) ;
160
- assert_eq ! ( values2, vec![ 32 , 42 ] ) ;
161
- assert_eq ! ( values3, vec![ 42 ] ) ;
174
+ let cb1 = CallbackRecorder :: new ( ) ;
175
+ let cb2 = CallbackRecorder :: new ( ) ;
176
+ let cb3 = CallbackRecorder :: new ( ) ;
177
+
178
+ let mut reactor = Reactor :: new ( ) ;
179
+ let input = reactor. create_input ( 11 ) ;
180
+ let output = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
181
+
182
+ let callback = reactor. add_callback ( output, |v| cb1. callback_called ( v) ) . unwrap ( ) ;
183
+ assert ! ( reactor. add_callback( output, |v| cb2. callback_called( v) ) . is_ok( ) ) ;
184
+
185
+ assert ! ( reactor. set_value( input, 31 ) . is_ok( ) ) ;
186
+ cb1. expect_to_have_been_called_with ( 32 ) ;
187
+ cb2. expect_to_have_been_called_with ( 32 ) ;
188
+
189
+ assert ! ( reactor. remove_callback( output, callback) . is_ok( ) ) ;
190
+ assert ! ( reactor. add_callback( output, |v| cb3. callback_called( v) ) . is_ok( ) ) ;
191
+
192
+ assert ! ( reactor. set_value( input, 41 ) . is_ok( ) ) ;
193
+ cb1. expect_not_to_have_been_called ( ) ;
194
+ cb2. expect_to_have_been_called_with ( 42 ) ;
195
+ cb3. expect_to_have_been_called_with ( 42 ) ;
162
196
}
163
197
164
198
#[ test]
165
199
#[ ignore]
166
200
fn removing_a_callback_multiple_times_doesnt_interfere_with_other_callbacks ( ) {
167
- let mut values1 = Vec :: new ( ) ;
168
- let mut values2 = Vec :: new ( ) ;
169
- {
170
- let mut reactor = Reactor :: new ( ) ;
171
- let input = reactor. create_input ( 1 ) ;
172
- let output = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
173
- let callback = reactor. add_callback ( output, |v| values1. push ( v) ) . unwrap ( ) ;
174
- assert ! ( reactor. add_callback( output, |v| values2. push( v) ) . is_ok( ) ) ;
175
- // We want the first remove to be Ok, but we don't care about the others.
176
- assert ! ( reactor. remove_callback( output, callback) . is_ok( ) ) ;
177
- for _ in 1 ..5 {
178
- assert ! ( reactor. remove_callback( output, callback) . is_err( ) ) ;
179
- }
180
- assert ! ( reactor. set_value( input, 2 ) . is_ok( ) ) ;
201
+ let cb1 = CallbackRecorder :: new ( ) ;
202
+ let cb2 = CallbackRecorder :: new ( ) ;
203
+
204
+ let mut reactor = Reactor :: new ( ) ;
205
+ let input = reactor. create_input ( 1 ) ;
206
+ let output = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
207
+ let callback = reactor. add_callback ( output, |v| cb1. callback_called ( v) ) . unwrap ( ) ;
208
+ assert ! ( reactor. add_callback( output, |v| cb2. callback_called( v) ) . is_ok( ) ) ;
209
+ // We want the first remove to be Ok, but we don't care about the others.
210
+ assert ! ( reactor. remove_callback( output, callback) . is_ok( ) ) ;
211
+ for _ in 1 ..5 {
212
+ assert ! ( reactor. remove_callback( output, callback) . is_err( ) ) ;
181
213
}
182
- assert_eq ! ( values1, Vec :: new( ) ) ;
183
- assert_eq ! ( values2, vec![ 3 ] ) ;
214
+
215
+ assert ! ( reactor. set_value( input, 2 ) . is_ok( ) ) ;
216
+ cb1. expect_not_to_have_been_called ( ) ;
217
+ cb2. expect_to_have_been_called_with ( 3 ) ;
184
218
}
185
219
186
220
#[ test]
187
221
#[ ignore]
188
222
fn callbacks_should_only_be_called_once_even_if_multiple_dependencies_change ( ) {
189
- let mut values = Vec :: new ( ) ;
190
- {
191
- let mut reactor = Reactor :: new ( ) ;
192
- let input = reactor. create_input ( 1 ) ;
193
- let plus_one = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
194
- let minus_one1 = reactor. create_compute ( & [ input] , |v| v[ 0 ] - 1 ) . unwrap ( ) ;
195
- let minus_one2 = reactor. create_compute ( & [ minus_one1] , |v| v[ 0 ] - 1 ) . unwrap ( ) ;
196
- let output = reactor. create_compute ( & [ plus_one, minus_one2] , |v| v[ 0 ] * v[ 1 ] ) . unwrap ( ) ;
197
- assert ! ( reactor. add_callback( output, |v| values. push( v) ) . is_ok( ) ) ;
198
- assert ! ( reactor. set_value( input, 4 ) . is_ok( ) ) ;
199
- }
200
- assert_eq ! ( values, vec![ 10 ] ) ;
223
+ let cb = CallbackRecorder :: new ( ) ;
224
+ let mut reactor = Reactor :: new ( ) ;
225
+ let input = reactor. create_input ( 1 ) ;
226
+ let plus_one = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
227
+ let minus_one1 = reactor. create_compute ( & [ input] , |v| v[ 0 ] - 1 ) . unwrap ( ) ;
228
+ let minus_one2 = reactor. create_compute ( & [ minus_one1] , |v| v[ 0 ] - 1 ) . unwrap ( ) ;
229
+ let output = reactor. create_compute ( & [ plus_one, minus_one2] , |v| v[ 0 ] * v[ 1 ] ) . unwrap ( ) ;
230
+ assert ! ( reactor. add_callback( output, |v| cb. callback_called( v) ) . is_ok( ) ) ;
231
+ assert ! ( reactor. set_value( input, 4 ) . is_ok( ) ) ;
232
+ cb. expect_to_have_been_called_with ( 10 ) ;
201
233
}
202
234
203
235
#[ test]
204
236
#[ ignore]
205
237
fn callbacks_should_not_be_called_if_dependencies_change_but_output_value_doesnt_change ( ) {
206
- let mut values = Vec :: new ( ) ;
207
- {
208
- let mut reactor = Reactor :: new ( ) ;
209
- let input = reactor. create_input ( 1 ) ;
210
- let plus_one = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
211
- let minus_one = reactor. create_compute ( & [ input] , |v| v[ 0 ] - 1 ) . unwrap ( ) ;
212
- let always_two = reactor. create_compute ( & [ plus_one, minus_one] , |v| v[ 0 ] - v[ 1 ] ) . unwrap ( ) ;
213
- assert ! ( reactor. add_callback( always_two, |v| values. push( v) ) . is_ok( ) ) ;
214
- for i in 2 ..5 {
215
- assert ! ( reactor. set_value( input, i) . is_ok( ) ) ;
216
- }
238
+ let cb = CallbackRecorder :: new ( ) ;
239
+ let mut reactor = Reactor :: new ( ) ;
240
+ let input = reactor. create_input ( 1 ) ;
241
+ let plus_one = reactor. create_compute ( & [ input] , |v| v[ 0 ] + 1 ) . unwrap ( ) ;
242
+ let minus_one = reactor. create_compute ( & [ input] , |v| v[ 0 ] - 1 ) . unwrap ( ) ;
243
+ let always_two = reactor. create_compute ( & [ plus_one, minus_one] , |v| v[ 0 ] - v[ 1 ] ) . unwrap ( ) ;
244
+ assert ! ( reactor. add_callback( always_two, |v| cb. callback_called( v) ) . is_ok( ) ) ;
245
+ for i in 2 ..5 {
246
+ assert ! ( reactor. set_value( input, i) . is_ok( ) ) ;
247
+ cb. expect_not_to_have_been_called ( ) ;
217
248
}
218
- assert_eq ! ( values, Vec :: new( ) ) ;
219
249
}
220
250
221
251
#[ test]
0 commit comments