-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathunittests.ml
473 lines (424 loc) · 22.1 KB
/
unittests.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
(*******************************************************************************
* This file contains the unittests that define the interfaces used for the
* core objects in the Tetris game. They're all in one file because it makes
* managing tests easier for the time being. Once I get the hang of unit tests
* in ocaml, I'll probably do something more complicated.
*
* Author: Michael DiBernardo
******************************************************************************)
open OUnit
open TetrisModel
(*******************************************************************************
* Tetris piece unit tests.
******************************************************************************)
(* Construct a piece composed of only a single block and rotate it. Nothing
should change. *)
let test_single_block_piece _ =
let piece = new tetris_piece [ [0; 0] ] 0 in
let rec loop i = if i < 5 then (
assert_equal piece#get_width 1;
assert_equal piece#get_height 1;
assert_equal piece#get_skirt [ 0 ];
assert_equal piece#get_body [ [0; 0] ];
piece#rotate;
loop (i+1)
)
in
loop 0;;
(* Construct a two-block piece. Rotating should do stuff now. *)
let test_two_block_piece _ =
let piece = new tetris_piece [ [0; 0]; [0; 1] ] 0 in
assert_equal piece#get_width 1;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 0 ];
assert_equal piece#get_body [ [0; 0]; [0; 1] ];
piece#rotate;
assert_equal piece#get_width 2;
assert_equal piece#get_height 1;
assert_equal piece#get_skirt [ 0; 0 ];
assert_equal piece#get_body [ [0; 0]; [1; 0] ];
piece#rotate;
assert_equal piece#get_width 1;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 0 ];
assert_equal piece#get_body [ [0; 0]; [0; 1] ];
piece#rotate;
assert_equal piece#get_width 2;
assert_equal piece#get_height 1;
assert_equal piece#get_skirt [ 0; 0 ];
assert_equal piece#get_body [ [0; 0]; [1; 0] ];
piece#rotate;
assert_equal piece#get_width 1;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 0 ];
assert_equal piece#get_body [ [0; 0]; [0; 1] ]
(* Construct a square piece and test that it works. *)
let test_square_piece _ =
let piece = new tetris_piece [ [0; 0]; [1; 0]; [0; 1]; [1; 1] ] 0 in
let rec loop i = if i < 5 then (
assert_equal piece#get_width 2;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 0; 0 ];
assert_equal piece#get_body [ [0; 0]; [0; 1]; [1; 0]; [1; 1] ];
piece#rotate;
loop (i+1)
)
in
loop 0;;
(* Construct a left dog and test that it works. You know, this thing:
oo
oo *)
let test_left_dog_piece _ =
let piece = new tetris_piece [ [0; 1]; [1; 1]; [1; 0]; [2; 0] ] 0 in
assert_equal piece#get_width 3;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 1; 0; 0 ];
assert_equal piece#get_body [ [0; 1]; [1; 0]; [1; 1]; [2; 0] ];
piece#rotate;
assert_equal piece#get_width 2;
assert_equal piece#get_height 3;
assert_equal piece#get_skirt [ 0; 1 ];
assert_equal piece#get_body [ [0; 0]; [0; 1]; [1; 1]; [1; 2] ];
piece#rotate;
assert_equal piece#get_width 3;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 1; 0; 0 ];
assert_equal piece#get_body [ [0; 1]; [1; 0]; [1; 1]; [2; 0] ];
piece#rotate;
assert_equal piece#get_width 2;
assert_equal piece#get_height 3;
assert_equal piece#get_skirt [ 0; 1 ];
assert_equal piece#get_body [ [0; 0]; [0; 1]; [1; 1]; [1; 2] ];
piece#rotate;
assert_equal piece#get_width 3;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 1; 0; 0 ];
assert_equal piece#get_body [ [0; 1]; [1; 0]; [1; 1]; [2; 0] ]
(* Construct a T shape and test that it works. This is a good case because it
really has 4 unique conformations. *)
let test_t_piece _ =
let piece = new tetris_piece [ [0; 0]; [1; 0]; [2; 0]; [1; 1] ] 0 in
assert_equal piece#get_width 3;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 0; 0; 0 ];
assert_equal piece#get_body [ [0; 0]; [1; 0]; [1; 1]; [2; 0] ];
piece#rotate;
assert_equal piece#get_width 2;
assert_equal piece#get_height 3;
assert_equal piece#get_skirt [ 0; 1];
assert_equal piece#get_body [ [0; 0]; [0; 1]; [0; 2]; [1; 1] ];
piece#rotate;
assert_equal piece#get_width 3;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 1; 0; 1];
assert_equal piece#get_body [ [0; 1]; [1; 0]; [1; 1]; [2; 1] ];
piece#rotate;
assert_equal piece#get_width 2;
assert_equal piece#get_height 3;
assert_equal piece#get_skirt [ 1; 0];
assert_equal piece#get_body [ [0; 1]; [1; 0]; [1; 1]; [1; 2] ];
piece#rotate;
assert_equal piece#get_width 3;
assert_equal piece#get_height 2;
assert_equal piece#get_skirt [ 0; 0; 0 ];
assert_equal piece#get_body [ [0; 0]; [1; 0]; [1; 1]; [2; 0] ]
(* If you pass an empty body to a piece, it should throw an exception.
let test_empty_body =
try (new tetris_piece []) with
| Invalid_argument a -> assert_equal a "Can't init piece with an empty body!"
*)
(*******************************************************************************
* Tetris board unit tests.
******************************************************************************)
let repeat_mock_generator body_template =
fun () -> new tetris_piece body_template 0
let sequence_mock_generator sequence =
fun () -> new tetris_piece (Queue.take sequence) 0
let default_height = 4 and default_width = 6 and default_evo = 1;;
let default_test_board gen =
new tetris_board default_width default_height default_evo gen
type state_test = { t_in : board_input; expected_state : board_state; expected_pos : position };;
let test_state_sequence board set =
let checker x = (
let actual_state = board#evolve x.t_in in
(*
Printf.printf "***";
Printf.printf "%d, %d vs %d, %d\n" x.expected_pos.x x.expected_pos.y board#get_current_piece_position.x board#get_current_piece_position.y;
*)
assert_bool "Expected states not equal" (x.expected_state = actual_state);
assert_bool "Expected pos not equal: " (x.expected_pos = board#get_current_piece_position)
)
in
List.iter checker set
(* Test where the first piece starts out based on the piece height, board width
parity, and piece width parity. *)
let test_piece_position_init_even_piece_odd_board _ =
let height = 4 and width = 5 and evos_per_drop = 1 in
let board = new tetris_board width height evos_per_drop (repeat_mock_generator [ [0; 0]; [1; 0] ]) in
assert_equal board#get_current_piece_position { x=1; y=3 }
let test_piece_position_init_even_piece_even_board _ =
let height = 4 and width = 6 and evos_per_drop = 1 in
let board = new tetris_board width height evos_per_drop (repeat_mock_generator [ [0; 0]; [1; 0] ]) in
assert_equal board#get_current_piece_position { x=2; y=3 }
let test_piece_position_init_odd_piece_odd_board _ =
let height = 4 and width = 5 and evos_per_drop = 1 in
let board = new tetris_board width height evos_per_drop (repeat_mock_generator [ [0; 0]; [1; 0]; [1; 1]; [2; 0] ]) in
assert_equal board#get_current_piece_position { x=1; y=2 }
let test_piece_position_init_odd_piece_even_board _ =
let height = 4 and width = 6 and evos_per_drop = 1 in
let board = new tetris_board width height evos_per_drop (repeat_mock_generator [ [0; 0]; [1; 0]; [1; 1]; [2; 0] ]) in
assert_equal board#get_current_piece_position { x=1; y=2 }
(* Does the first piece get inited properly? *)
let test_first_piece_inited _ =
let piece = new tetris_piece [ [0; 0] ] 0 in
let test_generator = fun () -> piece in
let board = default_test_board test_generator in
assert_equal board#get_current_piece piece
(* Does the next piece get inited properly? *)
let test_next_piece_inited _ =
let count = ref 0 and
first = new tetris_piece [ [0; 0] ] 0 and
second = new tetris_piece [ [0; 0]; [0; 1] ] 0 in
let test_generator = fun () ->
if !count = 0 then (
incr count;
first
) else
second
in
let board = default_test_board test_generator in
assert_equal board#get_next_piece second
(* Test that a piece with no one 'controlling' it will fall and hit the floor
without producing any rows. Then, another piece should start falling.*)
let test_falls_and_hits_floor _ =
let board = default_test_board (repeat_mock_generator [ [0; 0] ]) in
let cx = board#get_current_piece_position.x and
input = { hor = LDNone; drop = false; rot = RNone } in
let sequence = [
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = cx; y = board#get_height - 2 } };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = cx; y = board#get_height - 3 } };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = cx; y = board#get_height - 4 } };
{ t_in = input; expected_state = Landed(0); expected_pos = { x = cx; y = board#get_height - 4} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = cx; y = board#get_height - 1} }
]
in
test_state_sequence board sequence
let test_down_ignores_input_until_fall _ =
let down_input = { hor = LDNone; drop = true; rot = RNone } and
left_input = { hor = Left; drop = false; rot = RNone } and
right_input = { hor = LDNone; drop = false; rot = Clockwise } in
let board = default_test_board (repeat_mock_generator [ [0; 0] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = down_input; expected_state = Falling(FreeFall); expected_pos = { x = original_x; y = board#get_height - 2} };
{ t_in = right_input; expected_state = Falling(FreeFall); expected_pos = { x = original_x; y = board#get_height - 3} };
{ t_in = left_input; expected_state = Falling(FreeFall); expected_pos = { x = original_x; y = board#get_height - 4} };
{ t_in = left_input; expected_state = Landed(0); expected_pos = { x = original_x; y = board#get_height - 4} }
]
in
test_state_sequence board sequence
let test_move_left_with_clipping _ =
let input = { hor = Left; drop = false; rot = RNone } and
board = default_test_board (repeat_mock_generator [ [0; 0] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x - 1; y = board#get_height - 2} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x - 2; y = board#get_height - 3} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x - 2; y = board#get_height - 4} }
]
in
test_state_sequence board sequence
let test_evo_rate _ =
let input = { hor = Left; drop = false; rot = RNone } and
board = new tetris_board default_width default_height 2 (repeat_mock_generator [ [0; 0] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x - 1; y = board#get_height - 1} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x - 2; y = board#get_height - 2} }
]
in
test_state_sequence board sequence
(* Drop a piece that is a single row in length and see that we register a 1-row landing. *)
let test_single_row_detected _ =
let input = { hor = LDNone; drop = false; rot = RNone } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [1; 0]; [2; 0]; [3; 0]; [4; 0]; [5; 0] ]) in
let sequence = [
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = board#get_height - 2} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = board#get_height - 3} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = board#get_height - 4} };
{ t_in = input; expected_state = Landed(1); expected_pos = { x = 0; y = board#get_height - 4} }
]
in
test_state_sequence board sequence
(* Test stacking two inverted Ts:
o
ooo
o
ooo *)
let test_stacking _ =
let input = { hor = LDNone; drop = false; rot = RNone } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [1; 0]; [2; 0]; [1; 1] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = board#get_height - 3} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = board#get_height - 4} };
{ t_in = input; expected_state = Landed(0); expected_pos = { x = original_x; y = board#get_height - 4} };
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = board#get_height - 2} };
{ t_in = input; expected_state = Landed(0); expected_pos = { x = original_x; y = board#get_height - 2} }
]
in
test_state_sequence board sequence
(* Test left/right clipping on other pieces. Do this by dropping one piece to
the left, then one to the right, and then 'wiggling' the third left and right
and seeing that it's stuck, like so:
3
1 3 2
1 3 2
1 2 *)
let test_left_right_piece_clipping _ =
let left_input = { hor = Left; drop = false; rot = RNone } and
right_input = { hor = Right; drop = false; rot = RNone } and
norm_input = { hor = LDNone; drop = false; rot = RNone } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [0; 1]; [0; 2] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x - 1; y = 0 } };
{ t_in = norm_input; expected_state = Landed(0); expected_pos = { x = original_x - 1; y = 0 } };
{ t_in = norm_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = 1 } };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x + 1; y = 0 } };
{ t_in = norm_input; expected_state = Landed(0); expected_pos = { x = original_x + 1; y = 0 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = 1} };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = 0} };
{ t_in = norm_input; expected_state = Landed(0); expected_pos = { x = original_x; y = 0 } }
]
in
test_state_sequence board sequence
let test_rotational_clockwise_recentering _ =
let rot_input = { hor = LDNone; drop = false; rot = Clockwise } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [0; 1]; [0; 2] ]) in
let sequence = [
{ t_in = rot_input; expected_state = Falling(NormalFall); expected_pos = { x = 1; y = 1 } };
]
in
test_state_sequence board sequence
let test_rotational_cclockwise_recentering _ =
let rot_input = { hor = LDNone; drop = false; rot = CounterClockwise } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [0; 1]; [0; 2] ]) in
let sequence = [
{ t_in = rot_input; expected_state = Falling(NormalFall); expected_pos = { x = 1; y = 1 } };
]
in
test_state_sequence board sequence
(* Test rotational clipping on the wall. *)
let test_rotational_wall_clipping _ =
let height = 6 and width = 4 and evos_per_drop = 10 in
let board = new tetris_board width height evos_per_drop (repeat_mock_generator [ [0; 0]; [0; 1]; [0; 2]; [0; 3] ]) and
right_input = { hor = Right; drop = false; rot = RNone } and
rot_input = { hor = LDNone; drop = false; rot = Clockwise } in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x + 1; y = 2 } };
{ t_in = rot_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x + 1; y = 2 } }
]
in
test_state_sequence board sequence
(* Test rotational clipping on other pieces. *)
let test_rotational_piece_clipping _ =
let right_input = { hor = Right; drop = false; rot = RNone } and
rot_input = { hor = LDNone; drop = false; rot = Clockwise } and
norm_input = { hor = LDNone; drop = false; rot = RNone } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [0; 1]; [0; 2] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x + 1; y = 0 } };
{ t_in = norm_input; expected_state = Landed(0); expected_pos = { x = original_x + 1; y = 0 } };
{ t_in = norm_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = 1} };
{ t_in = rot_input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = 0} }
]
in
test_state_sequence board sequence
(* Drop a piece that is a single row in length and see that we register a 1-row landing. *)
let test_complete_rows_are_removed _ =
let make_pieces_queue () =
let q = Queue.create () in
Queue.push [ [0; 0]; [1; 0]; [2; 0]; [0; 1]; [1; 1]; [2; 1] ] q;
Queue.push [ [0; 0] ] q;
Queue.push [ [0; 0]; [1; 0]; [2; 0]; [0; 1]; [1; 1]; [2; 1] ] q;
Queue.push [ [0; 0] ] q;
Queue.push [ [0; 0] ] q;
sequence_mock_generator q
in
let height = 6 and width = 6 and evos_per_drop = 1 in
let board = new tetris_board width height evos_per_drop (make_pieces_queue ()) and
left_input = { hor = Left; drop = false; rot = RNone } and
right_input = { hor = Right; drop = false; rot = RNone } in
let sequence = [
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 3 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 2 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 1 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 0 } };
{ t_in = left_input; expected_state = Landed(0); expected_pos = { x = 0; y = 0 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 2; y = 5 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 1; y = 4 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 3 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 2 } };
{ t_in = left_input; expected_state = Landed(0); expected_pos = { x = 0; y = 2 } };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = 1; y = 4 } };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = 2; y = 3 } };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = 3; y = 2 } };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = 3; y = 1 } };
{ t_in = right_input; expected_state = Falling(NormalFall); expected_pos = { x = 3; y = 0 } };
{ t_in = left_input; expected_state = Landed(2); expected_pos = { x = 3; y = 0 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 2; y = 5 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 1; y = 4 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 3 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 2 } };
{ t_in = left_input; expected_state = Falling(NormalFall); expected_pos = { x = 0; y = 1 } };
{ t_in = left_input; expected_state = Landed(0); expected_pos = { x = 0; y = 1 } }
]
in
test_state_sequence board sequence
let test_game_over _ =
let input = { hor = LDNone; drop = false; rot = RNone } and
board = default_test_board (repeat_mock_generator [ [0; 0]; [0; 1]; [0; 2] ]) in
let original_x = board#get_current_piece_position.x in
let sequence = [
{ t_in = input; expected_state = Falling(NormalFall); expected_pos = { x = original_x; y = 0 } };
{ t_in = input; expected_state = Landed(0); expected_pos = { x = original_x; y = 0 } };
{ t_in = input; expected_state = GameOver; expected_pos = { x = original_x; y = 1 } }
]
in
test_state_sequence board sequence
(*** BUILD TETRIS PIECE SUITE ***)
let piece_suite = "Tetris Piece Suite" >::: [
"Single block" >:: test_single_block_piece;
"Two blocks" >:: test_two_block_piece;
"Square piece" >:: test_square_piece;
"Left dog piece" >:: test_left_dog_piece;
"T piece" >:: test_t_piece
]
(*** BUILD TETRIS BOARD SUITE ***)
let board_suite = "Tetris Board Suite" >::: [
"Init piece pos epob" >:: test_piece_position_init_even_piece_odd_board;
"Init piece pos epeb" >:: test_piece_position_init_even_piece_even_board;
"Init piece pos opob" >:: test_piece_position_init_odd_piece_odd_board;
"Init piece pos opob" >:: test_piece_position_init_odd_piece_even_board;
"First piece inited" >:: test_first_piece_inited;
"Next piece inited" >:: test_next_piece_inited;
"Falling to floor" >:: test_falls_and_hits_floor;
"Down input cancels others" >:: test_down_ignores_input_until_fall;
"Evo rate works" >:: test_evo_rate;
"Single row detection" >:: test_single_row_detected;
"Simple stacking" >:: test_stacking;
"Move left with wall clipping" >:: test_move_left_with_clipping;
"Lateral piece clipping" >:: test_left_right_piece_clipping;
"Rotational recentering clockwise" >:: test_rotational_clockwise_recentering;
"Rotational recentering counterclockwise" >:: test_rotational_cclockwise_recentering;
"Rotational wall clipping" >:: test_rotational_wall_clipping;
"Rotational piece clipping" >:: test_rotational_wall_clipping;
"Nontrivial stacking and row removal" >:: test_complete_rows_are_removed;
"Game over" >:: test_game_over
]
let _ =
run_test_tt_main piece_suite;
run_test_tt_main board_suite