2D Run-and-gun shooter inspired by One Man's Doomsday, Counter-Strike, and Metal Slug.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

712 lines
19 KiB

  1. #include "../../../__mocks__/SDL_keyboard.mock.h"
  2. #include "../../../__mocks__/SDL_joystick.mock.h"
  3. #include "../../../__mocks__/SDL_stdinc.mock.h"
  4. #include "../../../__mocks__/minIni.mock.h"
  5. #include "../../../__mocks__/portmidi.mock.h"
  6. #include "IZ_keyboard.h"
  7. #include "IZ_joystick.h"
  8. #include "IZ_midi.h"
  9. i16 GenerateAxisValueWithinThreshold(u16 threshold) {
  10. return rand() % threshold;
  11. }
  12. i16 GenerateAxisValueOutsideThreshold(u16 threshold) {
  13. return threshold + (rand() % (RAND_MAX - threshold - 1)) + 1;
  14. }
  15. spec("input") {
  16. describe("joystick") {
  17. describe("Initialize") {
  18. static IZ_JoystickState state[IZ_PLAYERS];
  19. after_each() {
  20. mock_reset(SDL_memcpy);
  21. }
  22. after_each() {
  23. mock_reset(SDL_NumJoysticks);
  24. }
  25. after_each() {
  26. mock_reset(SDL_JoystickOpen);
  27. }
  28. after_each() {
  29. mock_reset(ini_putl);
  30. }
  31. after_each() {
  32. mock_reset(ini_getl);
  33. }
  34. it("sets initial state") {
  35. IZ_JoystickInitialize(&state, "config.ini", 0, NULL);
  36. check(mock_is_called(SDL_memcpy), "Initial state not loaded.");
  37. check(mock_is_called(SDL_NumJoysticks), "Connected joysticks not checked.");
  38. }
  39. it("calls load method") {
  40. mock_set_expected_calls(ini_getl, ((CONTROLS - 4) + 2) * IZ_PLAYERS);
  41. IZ_JoystickInitialize(&state, "config.ini", 0, NULL);
  42. check(
  43. mock_get_expected_calls(ini_getl) == mock_get_actual_calls(ini_getl),
  44. "Call count mismatch for ini_getl() (expected %u, received %u).",
  45. mock_get_expected_calls(ini_getl),
  46. mock_get_actual_calls(ini_getl)
  47. );
  48. }
  49. it("calls save method") {
  50. mock_set_expected_calls(ini_putl, ((CONTROLS - 4) + 2) * IZ_PLAYERS);
  51. IZ_JoystickInitialize(&state, "config.ini", 0, NULL);
  52. check(
  53. mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl),
  54. "Call count mismatch for ini_putl() (expected %u, received %u).",
  55. mock_get_expected_calls(ini_putl),
  56. mock_get_actual_calls(ini_putl)
  57. );
  58. }
  59. it("opens device handles") {
  60. mock_set_expected_calls(SDL_JoystickOpen, MOCK_OPEN_JOYSTICKS);
  61. IZ_JoystickInitialize(&state, "config.ini", 0, NULL);
  62. check(
  63. mock_get_expected_calls(SDL_JoystickOpen) == mock_get_actual_calls(SDL_JoystickOpen),
  64. "Call count mismatch for SDL_JoystickOpen() (expected %u, received %u).",
  65. mock_get_expected_calls(SDL_JoystickOpen),
  66. mock_get_actual_calls(SDL_JoystickOpen)
  67. );
  68. }
  69. }
  70. describe("HandleEvents") {
  71. static SDL_Event e;
  72. static IZ_JoystickState state[IZ_PLAYERS] = {};
  73. static IZ_Action action[IZ_PLAYERS] = {};
  74. u8 p;
  75. for (p = 0; p < IZ_PLAYERS; p += 1) {
  76. describe("on player %u", p) {
  77. describe("on axis motion events") {
  78. before_each() {
  79. e.type = SDL_JOYAXISMOTION;
  80. state[p].config.axis_threshold = 8000u;
  81. }
  82. describe("on primary horizontal direction") {
  83. before_each() {
  84. e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_HORIZONTAL1;
  85. }
  86. it("handles positive motion") {
  87. e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  88. action[p] = 0;
  89. printf("(axis value: %d) ", e.jaxis.value);
  90. IZ_JoystickHandleEvents(&state, &action, e);
  91. check(
  92. action[p] == (0x1 << IZ_ACTION_INDEX_RIGHT),
  93. "Action not set."
  94. );
  95. }
  96. it("handles negative motion") {
  97. e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  98. action[p] = 0;
  99. printf("(axis value: %d) ", e.jaxis.value);
  100. IZ_JoystickHandleEvents(&state, &action, e);
  101. check(
  102. action[p] == (0x1 << IZ_ACTION_INDEX_LEFT),
  103. "Action not set."
  104. );
  105. }
  106. it("handles neutral motion") {
  107. e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);
  108. action[p] = 0;
  109. printf("(axis value: %d) ", e.jaxis.value);
  110. IZ_JoystickHandleEvents(&state, &action, e);
  111. check(
  112. action[p] == 0,
  113. "Action not set."
  114. );
  115. }
  116. }
  117. describe("on secondary horizontal direction") {
  118. before_each() {
  119. e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_HORIZONTAL2;
  120. }
  121. it("handles positive motion") {
  122. e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  123. action[p] = 0;
  124. printf("(axis value: %d) ", e.jaxis.value);
  125. IZ_JoystickHandleEvents(&state, &action, e);
  126. check(
  127. action[p] == (0x1 << IZ_ACTION_INDEX_RIGHT),
  128. "Action not set."
  129. );
  130. }
  131. it("handles negative motion") {
  132. e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  133. action[p] = 0;
  134. printf("(axis value: %d) ", e.jaxis.value);
  135. IZ_JoystickHandleEvents(&state, &action, e);
  136. check(
  137. action[p] == (0x1 << IZ_ACTION_INDEX_LEFT),
  138. "Action not set."
  139. );
  140. }
  141. it("handles neutral motion") {
  142. e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);;
  143. action[p] = 0;
  144. printf("(axis value: %d) ", e.jaxis.value);
  145. IZ_JoystickHandleEvents(&state, &action, e);
  146. check(
  147. action[p] == 0,
  148. "Action not set."
  149. );
  150. }
  151. }
  152. describe("on primary vertical direction") {
  153. before_each() {
  154. e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_VERTICAL1;
  155. }
  156. it("handles positive motion") {
  157. e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  158. action[p] = 0;
  159. printf("(axis value: %d) ", e.jaxis.value);
  160. IZ_JoystickHandleEvents(&state, &action, e);
  161. check(
  162. action[p] == (0x1 << IZ_ACTION_INDEX_DOWN),
  163. "Action not set."
  164. );
  165. }
  166. it("handles negative motion") {
  167. e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  168. action[p] = 0;
  169. printf("(axis value: %d) ", e.jaxis.value);
  170. IZ_JoystickHandleEvents(&state, &action, e);
  171. check(
  172. action[p] == (0x1 << IZ_ACTION_INDEX_UP),
  173. "Action not set."
  174. );
  175. }
  176. it("handles neutral motion") {
  177. e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);;
  178. action[p] = 0;
  179. printf("(axis value: %d) ", e.jaxis.value);
  180. IZ_JoystickHandleEvents(&state, &action, e);
  181. check(
  182. action[p] == 0,
  183. "Action not set."
  184. );
  185. }
  186. }
  187. describe("on secondary vertical direction") {
  188. before_each() {
  189. e.jaxis.axis = IZ_JOY_AXIS_DIRECTION_VERTICAL2;
  190. }
  191. it("handles positive motion") {
  192. e.jaxis.value = GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  193. action[p] = 0;
  194. printf("(axis value: %d) ", e.jaxis.value);
  195. IZ_JoystickHandleEvents(&state, &action, e);
  196. check(
  197. action[p] == (0x1 << IZ_ACTION_INDEX_DOWN),
  198. "Action not set."
  199. );
  200. }
  201. it("handles negative motion") {
  202. e.jaxis.value = -GenerateAxisValueOutsideThreshold(state[p].config.axis_threshold);
  203. action[p] = 0;
  204. printf("(axis value: %d) ", e.jaxis.value);
  205. IZ_JoystickHandleEvents(&state, &action, e);
  206. check(
  207. action[p] == (0x1 << IZ_ACTION_INDEX_UP),
  208. "Action not set."
  209. );
  210. }
  211. it("handles neutral motion") {
  212. e.jaxis.value = GenerateAxisValueWithinThreshold(state[p].config.axis_threshold);;
  213. action[p] = 0;
  214. printf("(axis value: %d) ", e.jaxis.value);
  215. IZ_JoystickHandleEvents(&state, &action, e);
  216. check(
  217. action[p] == 0,
  218. "Action not set."
  219. );
  220. }
  221. }
  222. }
  223. describe("on hat motion events") {
  224. before_each() {
  225. e.type = SDL_JOYHATMOTION;
  226. }
  227. for (u8 i = 0; i < 4; i += 1) {
  228. it("handles motion for %s action", ACTION_NAMES[i]) {
  229. e.jhat.value = (0x1u << i);
  230. action[p] = 0;
  231. IZ_JoystickHandleEvents(&state, &action, e);
  232. check(
  233. action[p] == (0x1u << i),
  234. "Action not set."
  235. );
  236. }
  237. it("handles motion for %s deactivation", ACTION_NAMES[i]) {
  238. e.jhat.value = 0;
  239. action[p] = ~0;
  240. IZ_JoystickHandleEvents(&state, &action, e);
  241. check(
  242. !(action[p] & (0x1 << i)),
  243. "Action not unset."
  244. );
  245. }
  246. }
  247. }
  248. describe("on button events") {
  249. for (u8 i = 4; i < CONTROLS; i += 1) {
  250. it("handles %s action activation", ACTION_NAMES[i]) {
  251. e.type = SDL_JOYBUTTONDOWN;
  252. e.jbutton.button = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
  253. state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
  254. action[p] = 0;
  255. IZ_JoystickHandleEvents(&state, &action, e);
  256. check(
  257. action[p] == (0x1u << i),
  258. "Action not set."
  259. );
  260. }
  261. it("handles %s action deactivation", ACTION_NAMES[i]) {
  262. e.type = SDL_JOYBUTTONUP;
  263. e.jbutton.button = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
  264. state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
  265. action[p] = ~0;
  266. IZ_JoystickHandleEvents(&state, &action, e);
  267. check(
  268. !(action[p] & (0x1 << i)),
  269. "Action not unset."
  270. );
  271. }
  272. }
  273. }
  274. }
  275. }
  276. }
  277. describe("SaveConfig") {
  278. static IZ_JoystickState state[IZ_PLAYERS];
  279. after_each() {
  280. mock_reset(ini_putl);
  281. }
  282. before_each() {
  283. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  284. for (u8 i = 0; i < CONTROLS; i += 1) {
  285. state[p].config.control_mapping[i] = IZ_JOYSTICK_DEFAULT_STATE[p].config.control_mapping[i];
  286. }
  287. }
  288. }
  289. it("calls save method") {
  290. mock_set_expected_calls(ini_putl, ((CONTROLS - 4) + 2) * IZ_PLAYERS);
  291. IZ_JoystickSaveConfig(&state, "config.ini");
  292. check(
  293. mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl),
  294. "Call count mismatch for ini_putl() (expected %u, received %u).",
  295. mock_get_expected_calls(ini_putl),
  296. mock_get_actual_calls(ini_putl)
  297. );
  298. }
  299. }
  300. describe("Teardown") {
  301. static SDL_Joystick device;
  302. static IZ_JoystickState state[IZ_PLAYERS] = {};
  303. before_each() {
  304. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  305. state[p].device = &device;
  306. }
  307. }
  308. after_each() {
  309. mock_reset(SDL_JoystickClose);
  310. }
  311. it("closes opened devices") {
  312. mock_set_expected_calls(SDL_JoystickClose, IZ_PLAYERS);
  313. IZ_JoystickTeardown(&state);
  314. check(
  315. mock_get_expected_calls(SDL_JoystickClose) == mock_get_actual_calls(SDL_JoystickClose),
  316. "Call count mismatch for SDL_JoystickClose() (expected %u, received %u).",
  317. mock_get_expected_calls(SDL_JoystickClose),
  318. mock_get_actual_calls(SDL_JoystickClose)
  319. );
  320. }
  321. }
  322. }
  323. describe("keyboard") {
  324. describe("Initialize") {
  325. static IZ_KeyboardState state[IZ_PLAYERS] = {};
  326. after_each() {
  327. mock_reset(SDL_memcpy);
  328. }
  329. after_each() {
  330. mock_reset(ini_gets);
  331. }
  332. after_each() {
  333. mock_reset(ini_puts);
  334. }
  335. before_each() {
  336. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  337. for (u8 i = 0; i < CONTROLS; i += 1) {
  338. state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i];
  339. }
  340. }
  341. }
  342. it("sets initial state") {
  343. IZ_KeyboardInitialize(&state, "config.ini", 0, NULL);
  344. check(mock_is_called(SDL_memcpy), "Initial state not loaded.");
  345. }
  346. it("calls load method") {
  347. mock_set_expected_calls(ini_gets, CONTROLS * IZ_PLAYERS);
  348. IZ_KeyboardInitialize(&state, "config.ini", 0, NULL);
  349. check(
  350. mock_get_expected_calls(ini_gets) == mock_get_actual_calls(ini_gets),
  351. "Call count mismatch for ini_gets() (expected %u, received %u).",
  352. mock_get_expected_calls(ini_gets),
  353. mock_get_actual_calls(ini_gets)
  354. );
  355. }
  356. it("calls save method") {
  357. mock_set_expected_calls(ini_puts, CONTROLS * IZ_PLAYERS);
  358. IZ_KeyboardInitialize(&state, "config.ini", 0, NULL);
  359. check(
  360. mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts),
  361. "Call count mismatch for ini_puts() (expected %u, received %u).",
  362. mock_get_expected_calls(ini_puts),
  363. mock_get_actual_calls(ini_puts)
  364. );
  365. }
  366. }
  367. describe("HandleEvents") {
  368. static SDL_Event e;
  369. static IZ_KeyboardState state[IZ_PLAYERS] = {};
  370. static IZ_Action action[IZ_PLAYERS] = {};
  371. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  372. describe("on player %u", p) {
  373. for (u8 i = 0; i < CONTROLS; i += 1) {
  374. it("handles %s action activation", ACTION_NAMES[i]) {
  375. e.type = SDL_KEYDOWN;
  376. e.key.keysym.sym = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i];
  377. state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i];
  378. action[p] = 0;
  379. IZ_KeyboardHandleEvents(&state, &action, e);
  380. check(
  381. action[p] == (0x1 << i),
  382. "Action not set."
  383. );
  384. }
  385. it("handles %s action deactivation", ACTION_NAMES[i]) {
  386. e.type = SDL_KEYUP;
  387. e.key.keysym.sym = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i];
  388. state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i];
  389. action[p] = ~0;
  390. IZ_KeyboardHandleEvents(&state, &action, e);
  391. check(
  392. !(action[p] & (0x1 << i)),
  393. "Action not unset."
  394. );
  395. }
  396. }
  397. }
  398. }
  399. }
  400. describe("SaveConfig") {
  401. static IZ_KeyboardState state[IZ_PLAYERS] = {};
  402. after_each() {
  403. mock_reset(ini_puts);
  404. }
  405. before_each() {
  406. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  407. for (u8 i = 0; i < CONTROLS; i += 1) {
  408. state[p].config.control_mapping[i] = IZ_KEYBOARD_DEFAULT_STATE[p].config.control_mapping[i];
  409. }
  410. }
  411. }
  412. it("calls save method") {
  413. mock_set_expected_calls(ini_puts, CONTROLS * IZ_PLAYERS);
  414. IZ_KeyboardSaveConfig("config.ini", &state);
  415. check(
  416. mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts),
  417. "Call count mismatch for ini_puts() (expected %u, received %u).",
  418. mock_get_expected_calls(ini_puts),
  419. mock_get_actual_calls(ini_puts)
  420. );
  421. }
  422. }
  423. }
  424. describe("midi") {
  425. describe("Initialize") {
  426. static IZ_MIDIInputState state[IZ_PLAYERS];
  427. after_each() {
  428. mock_reset(SDL_memcpy);
  429. }
  430. after_each() {
  431. mock_reset(Pm_CountDevices);
  432. }
  433. after_each() {
  434. mock_reset(Pm_OpenInput);
  435. }
  436. after_each() {
  437. mock_reset(ini_puts);
  438. }
  439. after_each() {
  440. mock_reset(ini_gets);
  441. }
  442. after_each() {
  443. mock_reset(ini_putl);
  444. }
  445. after_each() {
  446. mock_reset(ini_getl);
  447. }
  448. it("sets initial state") {
  449. IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL);
  450. check(mock_is_called(SDL_memcpy), "Initial state not loaded.");
  451. check(mock_is_called(Pm_CountDevices), "Connected MIDI devices not checked.");
  452. }
  453. it("calls load method") {
  454. mock_set_expected_calls(ini_gets, CONTROLS * IZ_PLAYERS);
  455. mock_set_expected_calls(ini_getl, 2 * IZ_PLAYERS);
  456. IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL);
  457. check(
  458. mock_get_expected_calls(ini_gets) == mock_get_actual_calls(ini_gets),
  459. "Call count mismatch for ini_gets() (expected %u, received %u).",
  460. mock_get_expected_calls(ini_gets),
  461. mock_get_actual_calls(ini_gets)
  462. );
  463. check(
  464. mock_get_expected_calls(ini_getl) == mock_get_actual_calls(ini_getl),
  465. "Call count mismatch for ini_getl() (expected %u, received %u).",
  466. mock_get_expected_calls(ini_getl),
  467. mock_get_actual_calls(ini_getl)
  468. );
  469. }
  470. it("calls save method") {
  471. mock_set_expected_calls(ini_puts, CONTROLS * IZ_PLAYERS);
  472. mock_set_expected_calls(ini_putl, 2 * IZ_PLAYERS);
  473. IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL);
  474. check(
  475. mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts),
  476. "Call count mismatch for ini_puts() (expected %u, received %u).",
  477. mock_get_expected_calls(ini_puts),
  478. mock_get_actual_calls(ini_puts)
  479. );
  480. check(
  481. mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl),
  482. "Call count mismatch for ini_putl() (expected %u, received %u).",
  483. mock_get_expected_calls(ini_putl),
  484. mock_get_actual_calls(ini_putl)
  485. );
  486. }
  487. it("opens device handles") {
  488. mock_set_expected_calls(Pm_OpenInput, MOCK_OPEN_JOYSTICKS);
  489. IZ_MIDIInputInitialize(&state, "config.ini", 0, NULL);
  490. check(
  491. mock_get_expected_calls(Pm_OpenInput) == mock_get_actual_calls(Pm_OpenInput),
  492. "Call count mismatch for Pm_OpenInput() (expected %u, received %u).",
  493. mock_get_expected_calls(Pm_OpenInput),
  494. mock_get_actual_calls(Pm_OpenInput)
  495. );
  496. }
  497. }
  498. describe("SaveConfig") {
  499. static IZ_MIDIInputState state[IZ_PLAYERS];
  500. after_each() {
  501. mock_reset(ini_puts);
  502. }
  503. after_each() {
  504. mock_reset(ini_putl);
  505. }
  506. it("calls save method") {
  507. mock_set_expected_calls(ini_puts, CONTROLS * IZ_PLAYERS);
  508. mock_set_expected_calls(ini_putl, 2 * IZ_PLAYERS);
  509. IZ_MIDIInputSaveConfig("config.ini", &state);
  510. check(
  511. mock_get_expected_calls(ini_puts) == mock_get_actual_calls(ini_puts),
  512. "Call count mismatch for ini_puts() (expected %u, received %u).",
  513. mock_get_expected_calls(ini_puts),
  514. mock_get_actual_calls(ini_puts)
  515. );
  516. check(
  517. mock_get_expected_calls(ini_putl) == mock_get_actual_calls(ini_putl),
  518. "Call count mismatch for ini_putl() (expected %u, received %u).",
  519. mock_get_expected_calls(ini_putl),
  520. mock_get_actual_calls(ini_putl)
  521. );
  522. }
  523. }
  524. describe("HandleEvents") {
  525. static PmEvent e;
  526. static IZ_MIDIInputState state[IZ_PLAYERS] = {};
  527. static IZ_Action action[IZ_PLAYERS] = {};
  528. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  529. describe("on player %u", p) {
  530. for (u8 i = 0; i < CONTROLS; i += 1) {
  531. it("handles %s action activation", ACTION_NAMES[i]) {
  532. e.message = IZ_MIDI_NOTE_ON | (IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i] << 8);
  533. state[p].config.control_mapping[i] = IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i];
  534. action[p] = 0;
  535. IZ_MIDIInputHandleEvents(&state, &action, e);
  536. check(
  537. action[p] == (0x1 << i),
  538. "Action not set."
  539. );
  540. }
  541. it("handles %s action deactivation", ACTION_NAMES[i]) {
  542. e.message = IZ_MIDI_NOTE_OFF | (IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i] << 8);
  543. state[p].config.control_mapping[i] = IZ_MIDI_INPUT_DEFAULT_STATE[p].config.control_mapping[i];
  544. action[p] = ~0;
  545. IZ_MIDIInputHandleEvents(&state, &action, e);
  546. check(
  547. !(action[p] & (0x1 << i)),
  548. "Action not unset."
  549. );
  550. }
  551. }
  552. }
  553. }
  554. }
  555. describe("Teardown") {
  556. static PmStream* stream;
  557. static IZ_MIDIInputState state[IZ_PLAYERS] = {};
  558. before_each() {
  559. for (u8 p = 0; p < IZ_PLAYERS; p += 1) {
  560. state[p].stream = &stream;
  561. }
  562. }
  563. after_each() {
  564. mock_reset(Pm_Close);
  565. }
  566. it("closes opened devices") {
  567. mock_set_expected_calls(Pm_Close, IZ_PLAYERS);
  568. IZ_MIDIInputTeardown(&state);
  569. check(
  570. mock_get_expected_calls(Pm_Close) == mock_get_actual_calls(Pm_Close),
  571. "Call count mismatch for Pm_Close() (expected %u, received %u).",
  572. mock_get_expected_calls(Pm_Close),
  573. mock_get_actual_calls(Pm_Close)
  574. );
  575. }
  576. }
  577. }
  578. }