gemba 0.1.1 → 0.2.0

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.
Files changed (285) hide show
  1. checksums.yaml +4 -4
  2. data/THIRD_PARTY_NOTICES +37 -2
  3. data/assets/placeholder_boxart.png +0 -0
  4. data/bin/gemba +2 -2
  5. data/ext/gemba/extconf.rb +23 -1
  6. data/ext/gemba/gemba_ext.c +436 -2
  7. data/ext/gemba/gemba_ext.h +2 -0
  8. data/gemba.gemspec +5 -3
  9. data/lib/gemba/achievements/achievement.rb +23 -0
  10. data/lib/gemba/achievements/backend.rb +186 -0
  11. data/lib/gemba/achievements/cache.rb +70 -0
  12. data/lib/gemba/achievements/credentials_presenter.rb +142 -0
  13. data/lib/gemba/achievements/fake_backend.rb +205 -0
  14. data/lib/gemba/achievements/null_backend.rb +11 -0
  15. data/lib/gemba/achievements/offline_backend.rb +168 -0
  16. data/lib/gemba/achievements/retro_achievements/backend.rb +453 -0
  17. data/lib/gemba/achievements/retro_achievements/cli_sync_requester.rb +64 -0
  18. data/lib/gemba/achievements/retro_achievements/ping_worker.rb +27 -0
  19. data/lib/gemba/achievements.rb +19 -0
  20. data/lib/gemba/achievements_window.rb +556 -0
  21. data/lib/gemba/app_controller.rb +1015 -0
  22. data/lib/gemba/bios.rb +54 -0
  23. data/lib/gemba/boxart_fetcher/libretro_backend.rb +39 -0
  24. data/lib/gemba/boxart_fetcher/null_backend.rb +12 -0
  25. data/lib/gemba/boxart_fetcher.rb +79 -0
  26. data/lib/gemba/bus_emitter.rb +13 -0
  27. data/lib/gemba/child_window.rb +24 -1
  28. data/lib/gemba/cli/commands/config_cmd.rb +83 -0
  29. data/lib/gemba/cli/commands/decode.rb +154 -0
  30. data/lib/gemba/cli/commands/patch.rb +78 -0
  31. data/lib/gemba/cli/commands/play.rb +78 -0
  32. data/lib/gemba/cli/commands/record.rb +114 -0
  33. data/lib/gemba/cli/commands/replay.rb +161 -0
  34. data/lib/gemba/cli/commands/retro_achievements.rb +213 -0
  35. data/lib/gemba/cli/commands/version.rb +22 -0
  36. data/lib/gemba/cli.rb +52 -364
  37. data/lib/gemba/config.rb +134 -1
  38. data/lib/gemba/data/gb_games.json +1 -0
  39. data/lib/gemba/data/gb_md5.json +1 -0
  40. data/lib/gemba/data/gba_games.json +1 -0
  41. data/lib/gemba/data/gba_md5.json +1 -0
  42. data/lib/gemba/data/gbc_games.json +1 -0
  43. data/lib/gemba/data/gbc_md5.json +1 -0
  44. data/lib/gemba/emulator_frame.rb +1060 -0
  45. data/lib/gemba/event_bus.rb +48 -0
  46. data/lib/gemba/frame_stack.rb +60 -0
  47. data/lib/gemba/game_index.rb +84 -0
  48. data/lib/gemba/game_picker_frame.rb +268 -0
  49. data/lib/gemba/gamepad_map.rb +103 -0
  50. data/lib/gemba/headless.rb +6 -5
  51. data/lib/gemba/headless_player.rb +33 -3
  52. data/lib/gemba/help_window.rb +61 -0
  53. data/lib/gemba/hotkey_map.rb +3 -1
  54. data/lib/gemba/input_recorder.rb +107 -0
  55. data/lib/gemba/input_replayer.rb +119 -0
  56. data/lib/gemba/keyboard_map.rb +90 -0
  57. data/lib/gemba/locales/en.yml +97 -5
  58. data/lib/gemba/locales/ja.yml +97 -5
  59. data/lib/gemba/main_window.rb +56 -0
  60. data/lib/gemba/modal_stack.rb +81 -0
  61. data/lib/gemba/patcher_window.rb +223 -0
  62. data/lib/gemba/platform/gb.rb +21 -0
  63. data/lib/gemba/platform/gba.rb +21 -0
  64. data/lib/gemba/platform/gbc.rb +23 -0
  65. data/lib/gemba/platform.rb +20 -0
  66. data/lib/gemba/platform_open.rb +19 -0
  67. data/lib/gemba/recorder.rb +4 -3
  68. data/lib/gemba/replay_player.rb +691 -0
  69. data/lib/gemba/rom_info.rb +57 -0
  70. data/lib/gemba/rom_info_window.rb +16 -3
  71. data/lib/gemba/rom_library.rb +106 -0
  72. data/lib/gemba/rom_overrides.rb +47 -0
  73. data/lib/gemba/rom_patcher/bps.rb +161 -0
  74. data/lib/gemba/rom_patcher/ips.rb +101 -0
  75. data/lib/gemba/rom_patcher/ups.rb +118 -0
  76. data/lib/gemba/rom_patcher.rb +109 -0
  77. data/lib/gemba/{rom_loader.rb → rom_resolver.rb} +7 -6
  78. data/lib/gemba/runtime.rb +59 -26
  79. data/lib/gemba/save_state_manager.rb +4 -7
  80. data/lib/gemba/save_state_picker.rb +17 -4
  81. data/lib/gemba/session_logger.rb +64 -0
  82. data/lib/gemba/settings/audio_tab.rb +77 -0
  83. data/lib/gemba/settings/gamepad_tab.rb +351 -0
  84. data/lib/gemba/settings/hotkeys_tab.rb +259 -0
  85. data/lib/gemba/settings/paths.rb +11 -0
  86. data/lib/gemba/settings/recording_tab.rb +83 -0
  87. data/lib/gemba/settings/save_states_tab.rb +91 -0
  88. data/lib/gemba/settings/system_tab.rb +362 -0
  89. data/lib/gemba/settings/video_tab.rb +318 -0
  90. data/lib/gemba/settings_window.rb +162 -1036
  91. data/lib/gemba/version.rb +1 -1
  92. data/lib/gemba/virtual_keyboard.rb +19 -0
  93. data/lib/gemba.rb +2 -12
  94. data/test/achievements_window/test_bulk_sync.rb +218 -0
  95. data/test/achievements_window/test_bus_events.rb +125 -0
  96. data/test/achievements_window/test_close_confirmation.rb +201 -0
  97. data/test/achievements_window/test_initial_state.rb +164 -0
  98. data/test/achievements_window/test_sorting.rb +227 -0
  99. data/test/achievements_window/test_tree_rendering.rb +133 -0
  100. data/test/fixtures/fake_bios.bin +0 -0
  101. data/test/fixtures/pong.gba +0 -0
  102. data/test/fixtures/test.gb +0 -0
  103. data/test/fixtures/test.gbc +0 -0
  104. data/test/fixtures/test_quicksave.ss +0 -0
  105. data/test/screenshots/no_focus.png +0 -0
  106. data/test/shared/teek_test_worker.rb +17 -1
  107. data/test/shared/tk_test_helper.rb +91 -4
  108. data/test/support/achievements_window_helpers.rb +18 -0
  109. data/test/support/fake_core.rb +25 -0
  110. data/test/support/fake_ra_runtime.rb +74 -0
  111. data/test/support/fake_requester.rb +68 -0
  112. data/test/support/player_helpers.rb +20 -5
  113. data/test/test_achievement.rb +32 -0
  114. data/test/{test_player.rb → test_app_controller.rb} +353 -85
  115. data/test/test_bios.rb +123 -0
  116. data/test/test_boxart_fetcher.rb +150 -0
  117. data/test/test_cli.rb +17 -265
  118. data/test/test_cli_config.rb +64 -0
  119. data/test/test_cli_decode.rb +97 -0
  120. data/test/test_cli_patch.rb +58 -0
  121. data/test/test_cli_play.rb +213 -0
  122. data/test/test_cli_ra.rb +175 -0
  123. data/test/test_cli_record.rb +69 -0
  124. data/test/test_cli_replay.rb +72 -0
  125. data/test/test_cli_sync_requester.rb +152 -0
  126. data/test/test_cli_version.rb +27 -0
  127. data/test/test_config.rb +2 -3
  128. data/test/test_config_ra.rb +69 -0
  129. data/test/test_core.rb +62 -1
  130. data/test/test_credentials_presenter.rb +192 -0
  131. data/test/test_event_bus.rb +100 -0
  132. data/test/test_fake_backend_achievements.rb +130 -0
  133. data/test/test_fake_backend_auth.rb +68 -0
  134. data/test/test_game_index.rb +77 -0
  135. data/test/test_game_picker_frame.rb +310 -0
  136. data/test/test_gamepad_map.rb +1 -3
  137. data/test/test_headless_player.rb +17 -3
  138. data/test/test_help_window.rb +82 -0
  139. data/test/test_hotkey_map.rb +22 -1
  140. data/test/test_input_recorder.rb +179 -0
  141. data/test/test_input_replay_determinism.rb +113 -0
  142. data/test/test_input_replayer.rb +162 -0
  143. data/test/test_keyboard_map.rb +1 -3
  144. data/test/test_libretro_backend.rb +41 -0
  145. data/test/test_locale.rb +1 -1
  146. data/test/test_logging.rb +123 -0
  147. data/test/test_null_backend.rb +42 -0
  148. data/test/test_offline_backend.rb +116 -0
  149. data/test/test_overlay_renderer.rb +1 -1
  150. data/test/test_platform.rb +149 -0
  151. data/test/test_ra_backend.rb +313 -0
  152. data/test/test_ra_backend_unlock_gate.rb +56 -0
  153. data/test/test_recorder.rb +0 -3
  154. data/test/test_replay_player.rb +316 -0
  155. data/test/test_rom_info.rb +149 -0
  156. data/test/test_rom_overrides.rb +86 -0
  157. data/test/test_rom_patcher.rb +382 -0
  158. data/test/{test_rom_loader.rb → test_rom_resolver.rb} +25 -26
  159. data/test/test_save_state_manager.rb +2 -4
  160. data/test/test_settings_audio.rb +107 -0
  161. data/test/test_settings_hotkeys.rb +83 -66
  162. data/test/test_settings_recording.rb +49 -0
  163. data/test/test_settings_save_states.rb +97 -0
  164. data/test/test_settings_system.rb +133 -0
  165. data/test/test_settings_video.rb +450 -0
  166. data/test/test_settings_window.rb +76 -507
  167. data/test/test_tip_service.rb +6 -6
  168. data/test/test_toast_overlay.rb +1 -1
  169. data/test/test_virtual_events.rb +156 -0
  170. data/test/test_virtual_keyboard.rb +1 -1
  171. data/vendor/rcheevos/CHANGELOG.md +495 -0
  172. data/vendor/rcheevos/LICENSE +21 -0
  173. data/vendor/rcheevos/Package.swift +33 -0
  174. data/vendor/rcheevos/README.md +67 -0
  175. data/vendor/rcheevos/include/module.modulemap +70 -0
  176. data/vendor/rcheevos/include/rc_api_editor.h +296 -0
  177. data/vendor/rcheevos/include/rc_api_info.h +280 -0
  178. data/vendor/rcheevos/include/rc_api_request.h +77 -0
  179. data/vendor/rcheevos/include/rc_api_runtime.h +417 -0
  180. data/vendor/rcheevos/include/rc_api_user.h +262 -0
  181. data/vendor/rcheevos/include/rc_client.h +877 -0
  182. data/vendor/rcheevos/include/rc_client_raintegration.h +101 -0
  183. data/vendor/rcheevos/include/rc_consoles.h +138 -0
  184. data/vendor/rcheevos/include/rc_error.h +59 -0
  185. data/vendor/rcheevos/include/rc_export.h +100 -0
  186. data/vendor/rcheevos/include/rc_hash.h +200 -0
  187. data/vendor/rcheevos/include/rc_runtime.h +148 -0
  188. data/vendor/rcheevos/include/rc_runtime_types.h +452 -0
  189. data/vendor/rcheevos/include/rc_util.h +51 -0
  190. data/vendor/rcheevos/include/rcheevos.h +8 -0
  191. data/vendor/rcheevos/src/rapi/rc_api_common.c +1379 -0
  192. data/vendor/rcheevos/src/rapi/rc_api_common.h +88 -0
  193. data/vendor/rcheevos/src/rapi/rc_api_editor.c +625 -0
  194. data/vendor/rcheevos/src/rapi/rc_api_info.c +587 -0
  195. data/vendor/rcheevos/src/rapi/rc_api_runtime.c +901 -0
  196. data/vendor/rcheevos/src/rapi/rc_api_user.c +483 -0
  197. data/vendor/rcheevos/src/rc_client.c +6941 -0
  198. data/vendor/rcheevos/src/rc_client_external.c +281 -0
  199. data/vendor/rcheevos/src/rc_client_external.h +177 -0
  200. data/vendor/rcheevos/src/rc_client_external_versions.h +171 -0
  201. data/vendor/rcheevos/src/rc_client_internal.h +409 -0
  202. data/vendor/rcheevos/src/rc_client_raintegration.c +566 -0
  203. data/vendor/rcheevos/src/rc_client_raintegration_internal.h +61 -0
  204. data/vendor/rcheevos/src/rc_client_types.natvis +396 -0
  205. data/vendor/rcheevos/src/rc_compat.c +251 -0
  206. data/vendor/rcheevos/src/rc_compat.h +121 -0
  207. data/vendor/rcheevos/src/rc_libretro.c +915 -0
  208. data/vendor/rcheevos/src/rc_libretro.h +98 -0
  209. data/vendor/rcheevos/src/rc_util.c +199 -0
  210. data/vendor/rcheevos/src/rc_version.c +11 -0
  211. data/vendor/rcheevos/src/rc_version.h +32 -0
  212. data/vendor/rcheevos/src/rcheevos/alloc.c +312 -0
  213. data/vendor/rcheevos/src/rcheevos/condition.c +754 -0
  214. data/vendor/rcheevos/src/rcheevos/condset.c +777 -0
  215. data/vendor/rcheevos/src/rcheevos/consoleinfo.c +1215 -0
  216. data/vendor/rcheevos/src/rcheevos/format.c +330 -0
  217. data/vendor/rcheevos/src/rcheevos/lboard.c +287 -0
  218. data/vendor/rcheevos/src/rcheevos/memref.c +805 -0
  219. data/vendor/rcheevos/src/rcheevos/operand.c +607 -0
  220. data/vendor/rcheevos/src/rcheevos/rc_internal.h +390 -0
  221. data/vendor/rcheevos/src/rcheevos/rc_runtime_types.natvis +541 -0
  222. data/vendor/rcheevos/src/rcheevos/rc_validate.c +1406 -0
  223. data/vendor/rcheevos/src/rcheevos/rc_validate.h +18 -0
  224. data/vendor/rcheevos/src/rcheevos/richpresence.c +922 -0
  225. data/vendor/rcheevos/src/rcheevos/runtime.c +852 -0
  226. data/vendor/rcheevos/src/rcheevos/runtime_progress.c +1073 -0
  227. data/vendor/rcheevos/src/rcheevos/trigger.c +344 -0
  228. data/vendor/rcheevos/src/rcheevos/value.c +935 -0
  229. data/vendor/rcheevos/src/rhash/aes.c +480 -0
  230. data/vendor/rcheevos/src/rhash/aes.h +49 -0
  231. data/vendor/rcheevos/src/rhash/cdreader.c +838 -0
  232. data/vendor/rcheevos/src/rhash/hash.c +1402 -0
  233. data/vendor/rcheevos/src/rhash/hash_disc.c +1340 -0
  234. data/vendor/rcheevos/src/rhash/hash_encrypted.c +566 -0
  235. data/vendor/rcheevos/src/rhash/hash_rom.c +426 -0
  236. data/vendor/rcheevos/src/rhash/hash_zip.c +460 -0
  237. data/vendor/rcheevos/src/rhash/md5.c +382 -0
  238. data/vendor/rcheevos/src/rhash/md5.h +91 -0
  239. data/vendor/rcheevos/src/rhash/rc_hash_internal.h +116 -0
  240. data/vendor/rcheevos/test/libretro.h +205 -0
  241. data/vendor/rcheevos/test/rapi/test_rc_api_common.c +941 -0
  242. data/vendor/rcheevos/test/rapi/test_rc_api_editor.c +931 -0
  243. data/vendor/rcheevos/test/rapi/test_rc_api_info.c +545 -0
  244. data/vendor/rcheevos/test/rapi/test_rc_api_runtime.c +2213 -0
  245. data/vendor/rcheevos/test/rapi/test_rc_api_user.c +998 -0
  246. data/vendor/rcheevos/test/rcheevos/mock_memory.h +32 -0
  247. data/vendor/rcheevos/test/rcheevos/test_condition.c +570 -0
  248. data/vendor/rcheevos/test/rcheevos/test_condset.c +5170 -0
  249. data/vendor/rcheevos/test/rcheevos/test_consoleinfo.c +203 -0
  250. data/vendor/rcheevos/test/rcheevos/test_format.c +112 -0
  251. data/vendor/rcheevos/test/rcheevos/test_lboard.c +746 -0
  252. data/vendor/rcheevos/test/rcheevos/test_memref.c +520 -0
  253. data/vendor/rcheevos/test/rcheevos/test_operand.c +692 -0
  254. data/vendor/rcheevos/test/rcheevos/test_rc_validate.c +502 -0
  255. data/vendor/rcheevos/test/rcheevos/test_richpresence.c +1564 -0
  256. data/vendor/rcheevos/test/rcheevos/test_runtime.c +1667 -0
  257. data/vendor/rcheevos/test/rcheevos/test_runtime_progress.c +1821 -0
  258. data/vendor/rcheevos/test/rcheevos/test_timing.c +166 -0
  259. data/vendor/rcheevos/test/rcheevos/test_trigger.c +2521 -0
  260. data/vendor/rcheevos/test/rcheevos/test_value.c +870 -0
  261. data/vendor/rcheevos/test/rcheevos-test.sln +46 -0
  262. data/vendor/rcheevos/test/rcheevos-test.vcxproj +239 -0
  263. data/vendor/rcheevos/test/rcheevos-test.vcxproj.filters +335 -0
  264. data/vendor/rcheevos/test/rhash/data.c +657 -0
  265. data/vendor/rcheevos/test/rhash/data.h +32 -0
  266. data/vendor/rcheevos/test/rhash/mock_filereader.c +236 -0
  267. data/vendor/rcheevos/test/rhash/mock_filereader.h +31 -0
  268. data/vendor/rcheevos/test/rhash/test_cdreader.c +920 -0
  269. data/vendor/rcheevos/test/rhash/test_hash.c +310 -0
  270. data/vendor/rcheevos/test/rhash/test_hash_disc.c +1450 -0
  271. data/vendor/rcheevos/test/rhash/test_hash_rom.c +899 -0
  272. data/vendor/rcheevos/test/rhash/test_hash_zip.c +551 -0
  273. data/vendor/rcheevos/test/test.c +113 -0
  274. data/vendor/rcheevos/test/test_framework.h +205 -0
  275. data/vendor/rcheevos/test/test_rc_client.c +10509 -0
  276. data/vendor/rcheevos/test/test_rc_client_external.c +2197 -0
  277. data/vendor/rcheevos/test/test_rc_client_raintegration.c +441 -0
  278. data/vendor/rcheevos/test/test_rc_libretro.c +952 -0
  279. data/vendor/rcheevos/test/test_types.natvis +9 -0
  280. data/vendor/rcheevos/validator/validator.c +658 -0
  281. data/vendor/rcheevos/validator/validator.vcxproj +152 -0
  282. data/vendor/rcheevos/validator/validator.vcxproj.filters +82 -0
  283. metadata +274 -11
  284. data/lib/gemba/input_mappings.rb +0 -214
  285. data/lib/gemba/player.rb +0 -1525
@@ -0,0 +1,998 @@
1
+ #include "rc_api_user.h"
2
+
3
+ #include "../src/rapi/rc_api_common.h"
4
+ #include "../test_framework.h"
5
+ #include "../rc_compat.h"
6
+ #include "../rc_version.h"
7
+
8
+ #define DOREQUEST_URL "https://retroachievements.org/dorequest.php"
9
+
10
+ static void test_init_start_session_request()
11
+ {
12
+ rc_api_start_session_request_t start_session_request;
13
+ rc_api_request_t request;
14
+
15
+ memset(&start_session_request, 0, sizeof(start_session_request));
16
+ start_session_request.username = "Username";
17
+ start_session_request.api_token = "API_TOKEN";
18
+ start_session_request.game_id = 1234;
19
+
20
+ ASSERT_NUM_EQUALS(rc_api_init_start_session_request(&request, &start_session_request), RC_OK);
21
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
22
+ ASSERT_STR_EQUALS(request.post_data, "r=startsession&u=Username&t=API_TOKEN&g=1234&l=" RCHEEVOS_VERSION_STRING);
23
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
24
+
25
+ rc_api_destroy_request(&request);
26
+ }
27
+
28
+ static void test_init_start_session_request_no_game()
29
+ {
30
+ rc_api_start_session_request_t start_session_request;
31
+ rc_api_request_t request;
32
+
33
+ memset(&start_session_request, 0, sizeof(start_session_request));
34
+ start_session_request.username = "Username";
35
+ start_session_request.api_token = "API_TOKEN";
36
+
37
+ ASSERT_NUM_EQUALS(rc_api_init_start_session_request(&request, &start_session_request), RC_INVALID_STATE);
38
+
39
+ rc_api_destroy_request(&request);
40
+ }
41
+
42
+ static void test_init_start_session_request_game_hash_softcore()
43
+ {
44
+ rc_api_start_session_request_t start_session_request;
45
+ rc_api_request_t request;
46
+
47
+ memset(&start_session_request, 0, sizeof(start_session_request));
48
+ start_session_request.username = "Username";
49
+ start_session_request.api_token = "API_TOKEN";
50
+ start_session_request.game_id = 1234;
51
+ start_session_request.game_hash = "ABCDEF0123456789";
52
+
53
+ ASSERT_NUM_EQUALS(rc_api_init_start_session_request(&request, &start_session_request), RC_OK);
54
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
55
+ ASSERT_STR_EQUALS(request.post_data, "r=startsession&u=Username&t=API_TOKEN&g=1234&h=0&m=ABCDEF0123456789&l=" RCHEEVOS_VERSION_STRING);
56
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
57
+
58
+ rc_api_destroy_request(&request);
59
+ }
60
+
61
+ static void test_init_start_session_request_game_hash_hardcore()
62
+ {
63
+ rc_api_start_session_request_t start_session_request;
64
+ rc_api_request_t request;
65
+
66
+ memset(&start_session_request, 0, sizeof(start_session_request));
67
+ start_session_request.username = "Username";
68
+ start_session_request.api_token = "API_TOKEN";
69
+ start_session_request.game_id = 1234;
70
+ start_session_request.hardcore = 1;
71
+ start_session_request.game_hash = "ABCDEF0123456789";
72
+
73
+ ASSERT_NUM_EQUALS(rc_api_init_start_session_request(&request, &start_session_request), RC_OK);
74
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
75
+ ASSERT_STR_EQUALS(request.post_data, "r=startsession&u=Username&t=API_TOKEN&g=1234&h=1&m=ABCDEF0123456789&l=" RCHEEVOS_VERSION_STRING);
76
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
77
+
78
+ rc_api_destroy_request(&request);
79
+ }
80
+
81
+ static void test_process_start_session_response_legacy()
82
+ {
83
+ rc_api_start_session_response_t start_session_response;
84
+ const char* server_response = "{\"Success\":true}";
85
+
86
+ memset(&start_session_response, 0, sizeof(start_session_response));
87
+
88
+ ASSERT_NUM_EQUALS(rc_api_process_start_session_response(&start_session_response, server_response), RC_OK);
89
+ ASSERT_NUM_EQUALS(start_session_response.response.succeeded, 1);
90
+ ASSERT_PTR_NULL(start_session_response.response.error_message);
91
+ ASSERT_NUM_EQUALS(start_session_response.num_unlocks, 0);
92
+ ASSERT_NUM_EQUALS(start_session_response.num_hardcore_unlocks, 0);
93
+ ASSERT_NUM_EQUALS(start_session_response.server_now, 0);
94
+
95
+ rc_api_destroy_start_session_response(&start_session_response);
96
+ }
97
+
98
+ static void test_process_start_session_response()
99
+ {
100
+ rc_api_start_session_response_t start_session_response;
101
+ /* startsession API only returns HardcoreUnlocks if an achievement has been earned in hardcore,
102
+ * even if the softcore unlock has a different timestamp. Unlocks are only returned for things
103
+ * only unlocked in softcore. */
104
+ const char* server_response = "{\"Success\":true,\"HardcoreUnlocks\":["
105
+ "{\"ID\":111,\"When\":1234567890},"
106
+ "{\"ID\":112,\"When\":1234567891},"
107
+ "{\"ID\":113,\"When\":1234567860}"
108
+ "],\"Unlocks\":["
109
+ "{\"ID\":114,\"When\":1234567840}"
110
+ "],\"ServerNow\":1234577777}";
111
+
112
+ memset(&start_session_response, 0, sizeof(start_session_response));
113
+
114
+ ASSERT_NUM_EQUALS(rc_api_process_start_session_response(&start_session_response, server_response), RC_OK);
115
+ ASSERT_NUM_EQUALS(start_session_response.response.succeeded, 1);
116
+ ASSERT_PTR_NULL(start_session_response.response.error_message);
117
+ ASSERT_NUM_EQUALS(start_session_response.num_unlocks, 1);
118
+ ASSERT_NUM_EQUALS(start_session_response.unlocks[0].achievement_id, 114);
119
+ ASSERT_NUM_EQUALS(start_session_response.unlocks[0].when, 1234567840);
120
+ ASSERT_NUM_EQUALS(start_session_response.num_hardcore_unlocks, 3);
121
+ ASSERT_NUM_EQUALS(start_session_response.hardcore_unlocks[0].achievement_id, 111);
122
+ ASSERT_NUM_EQUALS(start_session_response.hardcore_unlocks[0].when, 1234567890);
123
+ ASSERT_NUM_EQUALS(start_session_response.hardcore_unlocks[1].achievement_id, 112);
124
+ ASSERT_NUM_EQUALS(start_session_response.hardcore_unlocks[1].when, 1234567891);
125
+ ASSERT_NUM_EQUALS(start_session_response.hardcore_unlocks[2].achievement_id, 113);
126
+ ASSERT_NUM_EQUALS(start_session_response.hardcore_unlocks[2].when, 1234567860);
127
+ ASSERT_NUM_EQUALS(start_session_response.server_now, 1234577777);
128
+
129
+ rc_api_destroy_start_session_response(&start_session_response);
130
+ }
131
+
132
+ static void test_process_start_session_response_invalid_credentials()
133
+ {
134
+ rc_api_start_session_response_t start_session_response;
135
+ const char* server_response = "{\"Success\":false,\"Error\":\"Credentials invalid (0)\"}";
136
+
137
+ memset(&start_session_response, 0, sizeof(start_session_response));
138
+
139
+ ASSERT_NUM_EQUALS(rc_api_process_start_session_response(&start_session_response, server_response), RC_OK);
140
+ ASSERT_NUM_EQUALS(start_session_response.response.succeeded, 0);
141
+ ASSERT_STR_EQUALS(start_session_response.response.error_message, "Credentials invalid (0)");
142
+
143
+ rc_api_destroy_start_session_response(&start_session_response);
144
+ }
145
+
146
+ static void test_init_login_request_password()
147
+ {
148
+ rc_api_login_request_t login_request;
149
+ rc_api_request_t request;
150
+
151
+ memset(&login_request, 0, sizeof(login_request));
152
+ login_request.username = "Username";
153
+ login_request.password = "Pa$$w0rd!";
154
+
155
+ ASSERT_NUM_EQUALS(rc_api_init_login_request(&request, &login_request), RC_OK);
156
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
157
+ ASSERT_STR_EQUALS(request.post_data, "r=login2&u=Username&p=Pa%24%24w0rd%21");
158
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
159
+
160
+ rc_api_destroy_request(&request);
161
+ }
162
+
163
+ static void test_init_login_request_password_long()
164
+ {
165
+ char buffer[1024], *ptr, *password_start;
166
+ rc_api_login_request_t login_request;
167
+ rc_api_request_t request;
168
+ int i;
169
+
170
+ /* this generates a password that's 830 characters long */
171
+ ptr = password_start = buffer + snprintf(buffer, sizeof(buffer), "r=login2&u=ThisUsernameIsAlsoReallyLongAtRoughlyFiftyCharacters&p=");
172
+ for (i = 0; i < 30; i++)
173
+ ptr += snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%dABCDEFGHIJKLMNOPQRSTUVWXYZ", i);
174
+
175
+ memset(&login_request, 0, sizeof(login_request));
176
+ login_request.username = "ThisUsernameIsAlsoReallyLongAtRoughlyFiftyCharacters";
177
+ login_request.password = password_start;
178
+
179
+ ASSERT_NUM_EQUALS(rc_api_init_login_request(&request, &login_request), RC_OK);
180
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
181
+ ASSERT_STR_EQUALS(request.post_data, buffer);
182
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
183
+
184
+ rc_api_destroy_request(&request);
185
+ }
186
+
187
+ static void test_init_login_request_token()
188
+ {
189
+ rc_api_login_request_t login_request;
190
+ rc_api_request_t request;
191
+
192
+ memset(&login_request, 0, sizeof(login_request));
193
+ login_request.username = "Username";
194
+ login_request.api_token = "ABCDEFGHIJKLMNOP";
195
+
196
+ ASSERT_NUM_EQUALS(rc_api_init_login_request(&request, &login_request), RC_OK);
197
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
198
+ ASSERT_STR_EQUALS(request.post_data, "r=login2&u=Username&t=ABCDEFGHIJKLMNOP");
199
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
200
+
201
+ rc_api_destroy_request(&request);
202
+ }
203
+
204
+ static void test_init_login_request_password_and_token()
205
+ {
206
+ rc_api_login_request_t login_request;
207
+ rc_api_request_t request;
208
+
209
+ memset(&login_request, 0, sizeof(login_request));
210
+ login_request.username = "Username";
211
+ login_request.password = "Pa$$w0rd!";
212
+ login_request.api_token = "ABCDEFGHIJKLMNOP";
213
+
214
+ ASSERT_NUM_EQUALS(rc_api_init_login_request(&request, &login_request), RC_OK);
215
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
216
+ ASSERT_STR_EQUALS(request.post_data, "r=login2&u=Username&p=Pa%24%24w0rd%21");
217
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
218
+
219
+ rc_api_destroy_request(&request);
220
+ }
221
+
222
+ static void test_init_login_request_no_password_or_token()
223
+ {
224
+ rc_api_login_request_t login_request;
225
+ rc_api_request_t request;
226
+
227
+ memset(&login_request, 0, sizeof(login_request));
228
+ login_request.username = "Username";
229
+
230
+ ASSERT_NUM_EQUALS(rc_api_init_login_request(&request, &login_request), RC_INVALID_STATE);
231
+
232
+ rc_api_destroy_request(&request);
233
+ }
234
+
235
+ static void test_init_login_request_alternate_host()
236
+ {
237
+ rc_api_login_request_t login_request;
238
+ rc_api_request_t request;
239
+
240
+ memset(&login_request, 0, sizeof(login_request));
241
+ login_request.username = "Username";
242
+ login_request.password = "Pa$$w0rd!";
243
+
244
+ rc_api_set_host("localhost");
245
+ ASSERT_NUM_EQUALS(rc_api_init_login_request(&request, &login_request), RC_OK);
246
+ ASSERT_STR_EQUALS(request.url, "http://localhost/dorequest.php");
247
+ ASSERT_STR_EQUALS(request.post_data, "r=login2&u=Username&p=Pa%24%24w0rd%21");
248
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
249
+
250
+ rc_api_set_host(NULL);
251
+ rc_api_destroy_request(&request);
252
+ }
253
+
254
+ static void test_process_login_response_success()
255
+ {
256
+ rc_api_login_response_t login_response;
257
+ rc_api_server_response_t response_obj;
258
+ const char* server_response = "{\"Success\":true,\"User\":\"USER\",\"Token\":\"ApiTOKEN\",\"Score\":1234,\"SoftcoreScore\":789,\"Messages\":2}";
259
+
260
+ memset(&login_response, 0, sizeof(login_response));
261
+
262
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_OK);
263
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 1);
264
+ ASSERT_PTR_NULL(login_response.response.error_message);
265
+ ASSERT_STR_EQUALS(login_response.username, "USER");
266
+ ASSERT_STR_EQUALS(login_response.api_token, "ApiTOKEN");
267
+ ASSERT_NUM_EQUALS(login_response.score, 1234);
268
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 789);
269
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 2);
270
+ ASSERT_STR_EQUALS(login_response.display_name, "USER");
271
+
272
+ rc_api_destroy_login_response(&login_response);
273
+
274
+ memset(&response_obj, 0, sizeof(response_obj));
275
+ response_obj.body = server_response;
276
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
277
+ response_obj.http_status_code = 200;
278
+
279
+ memset(&login_response, 0, sizeof(login_response));
280
+
281
+ ASSERT_NUM_EQUALS(rc_api_process_login_server_response(&login_response, &response_obj), RC_OK);
282
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 1);
283
+ ASSERT_PTR_NULL(login_response.response.error_message);
284
+ ASSERT_STR_EQUALS(login_response.username, "USER");
285
+ ASSERT_STR_EQUALS(login_response.api_token, "ApiTOKEN");
286
+ ASSERT_NUM_EQUALS(login_response.score, 1234);
287
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 789);
288
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 2);
289
+ ASSERT_STR_EQUALS(login_response.display_name, "USER");
290
+
291
+ rc_api_destroy_login_response(&login_response);
292
+ }
293
+
294
+ static void test_process_login_response_unique_display_name()
295
+ {
296
+ rc_api_login_response_t login_response;
297
+ const char* server_response = "{\"Success\":true,\"User\":\"GamingHero\",\"AvatarUrl\":\"http://host/UserPic/USER.png\",\"Token\":\"ApiTOKEN\",\"Score\":1234,\"SoftcoreScore\":789,\"Messages\":2}";
298
+
299
+ memset(&login_response, 0, sizeof(login_response));
300
+
301
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_OK);
302
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 1);
303
+ ASSERT_PTR_NULL(login_response.response.error_message);
304
+ ASSERT_STR_EQUALS(login_response.username, "GamingHero");
305
+ ASSERT_STR_EQUALS(login_response.api_token, "ApiTOKEN");
306
+ ASSERT_NUM_EQUALS(login_response.score, 1234);
307
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 789);
308
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 2);
309
+ ASSERT_STR_EQUALS(login_response.display_name, "GamingHero");
310
+ ASSERT_STR_EQUALS(login_response.avatar_url, "http://host/UserPic/USER.png");
311
+
312
+ rc_api_destroy_login_response(&login_response);
313
+ }
314
+
315
+ static void test_process_login_response_invalid_credentials()
316
+ {
317
+ rc_api_login_response_t login_response;
318
+ rc_api_server_response_t response_obj;
319
+ const char* server_response = "{\"Success\":false,\"Error\":\"Invalid User/Password combination. Please try again\", \"Code\":\"invalid_credentials\"}";
320
+
321
+ memset(&login_response, 0, sizeof(login_response));
322
+
323
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_INVALID_CREDENTIALS);
324
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
325
+ ASSERT_STR_EQUALS(login_response.response.error_message, "Invalid User/Password combination. Please try again");
326
+ ASSERT_PTR_NULL(login_response.username);
327
+ ASSERT_PTR_NULL(login_response.api_token);
328
+ ASSERT_NUM_EQUALS(login_response.score, 0);
329
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
330
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
331
+ ASSERT_PTR_NULL(login_response.display_name);
332
+
333
+ rc_api_destroy_login_response(&login_response);
334
+
335
+ memset(&response_obj, 0, sizeof(response_obj));
336
+ response_obj.body = server_response;
337
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
338
+ response_obj.http_status_code = 401;
339
+
340
+ memset(&login_response, 0, sizeof(login_response));
341
+
342
+ ASSERT_NUM_EQUALS(rc_api_process_login_server_response(&login_response, &response_obj), RC_INVALID_CREDENTIALS);
343
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
344
+ ASSERT_STR_EQUALS(login_response.response.error_message, "Invalid User/Password combination. Please try again");
345
+ ASSERT_PTR_NULL(login_response.username);
346
+ ASSERT_PTR_NULL(login_response.api_token);
347
+ ASSERT_NUM_EQUALS(login_response.score, 0);
348
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
349
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
350
+ ASSERT_PTR_NULL(login_response.display_name);
351
+
352
+ rc_api_destroy_login_response(&login_response);
353
+ }
354
+
355
+ static void test_process_login_response_access_denied()
356
+ {
357
+ rc_api_login_response_t login_response;
358
+ rc_api_server_response_t response_obj;
359
+ const char* server_response = "{\"Success\":false,\"Error\":\"Access denied.\",\"Code\":\"access_denied\"}";
360
+
361
+ memset(&login_response, 0, sizeof(login_response));
362
+
363
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_ACCESS_DENIED);
364
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
365
+ ASSERT_STR_EQUALS(login_response.response.error_message, "Access denied.");
366
+ ASSERT_PTR_NULL(login_response.username);
367
+ ASSERT_PTR_NULL(login_response.api_token);
368
+ ASSERT_NUM_EQUALS(login_response.score, 0);
369
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
370
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
371
+ ASSERT_PTR_NULL(login_response.display_name);
372
+
373
+ rc_api_destroy_login_response(&login_response);
374
+
375
+ memset(&response_obj, 0, sizeof(response_obj));
376
+ response_obj.body = server_response;
377
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
378
+ response_obj.http_status_code = 403;
379
+
380
+ memset(&login_response, 0, sizeof(login_response));
381
+
382
+ ASSERT_NUM_EQUALS(rc_api_process_login_server_response(&login_response, &response_obj), RC_ACCESS_DENIED);
383
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
384
+ ASSERT_STR_EQUALS(login_response.response.error_message, "Access denied.");
385
+ ASSERT_PTR_NULL(login_response.username);
386
+ ASSERT_PTR_NULL(login_response.api_token);
387
+ ASSERT_NUM_EQUALS(login_response.score, 0);
388
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
389
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
390
+ ASSERT_PTR_NULL(login_response.display_name);
391
+
392
+ rc_api_destroy_login_response(&login_response);
393
+ }
394
+
395
+ static void test_process_login_response_expired_token()
396
+ {
397
+ rc_api_login_response_t login_response;
398
+ rc_api_server_response_t response_obj;
399
+ const char* server_response = "{\"Success\":false,\"Error\":\"The access token has expired. Please log in again.\",\"Code\":\"expired_token\"}";
400
+
401
+ memset(&login_response, 0, sizeof(login_response));
402
+
403
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_EXPIRED_TOKEN);
404
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
405
+ ASSERT_STR_EQUALS(login_response.response.error_message, "The access token has expired. Please log in again.");
406
+ ASSERT_PTR_NULL(login_response.username);
407
+ ASSERT_PTR_NULL(login_response.api_token);
408
+ ASSERT_NUM_EQUALS(login_response.score, 0);
409
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
410
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
411
+ ASSERT_PTR_NULL(login_response.display_name);
412
+
413
+ rc_api_destroy_login_response(&login_response);
414
+
415
+ memset(&response_obj, 0, sizeof(response_obj));
416
+ response_obj.body = server_response;
417
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
418
+ response_obj.http_status_code = 401;
419
+
420
+ memset(&login_response, 0, sizeof(login_response));
421
+
422
+ ASSERT_NUM_EQUALS(rc_api_process_login_server_response(&login_response, &response_obj), RC_EXPIRED_TOKEN);
423
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
424
+ ASSERT_STR_EQUALS(login_response.response.error_message, "The access token has expired. Please log in again.");
425
+ ASSERT_PTR_NULL(login_response.username);
426
+ ASSERT_PTR_NULL(login_response.api_token);
427
+ ASSERT_NUM_EQUALS(login_response.score, 0);
428
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
429
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
430
+ ASSERT_PTR_NULL(login_response.display_name);
431
+
432
+ rc_api_destroy_login_response(&login_response);
433
+ }
434
+
435
+ static void test_process_login_response_generic_failure()
436
+ {
437
+ rc_api_login_response_t login_response;
438
+ const char* server_response = "{\"Success\":false}";
439
+
440
+ memset(&login_response, 0, sizeof(login_response));
441
+
442
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_OK);
443
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
444
+ ASSERT_PTR_NULL(login_response.response.error_message);
445
+ ASSERT_PTR_NULL(login_response.username);
446
+ ASSERT_PTR_NULL(login_response.api_token);
447
+ ASSERT_NUM_EQUALS(login_response.score, 0);
448
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
449
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
450
+ ASSERT_PTR_NULL(login_response.display_name);
451
+
452
+ rc_api_destroy_login_response(&login_response);
453
+ }
454
+
455
+ static void test_process_login_response_empty()
456
+ {
457
+ rc_api_login_response_t login_response;
458
+ const char* server_response = "";
459
+
460
+ memset(&login_response, 0, sizeof(login_response));
461
+
462
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_NO_RESPONSE);
463
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
464
+ ASSERT_PTR_NULL(login_response.response.error_message);
465
+ ASSERT_PTR_NULL(login_response.username);
466
+ ASSERT_PTR_NULL(login_response.api_token);
467
+ ASSERT_NUM_EQUALS(login_response.score, 0);
468
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
469
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
470
+ ASSERT_PTR_NULL(login_response.display_name);
471
+
472
+ rc_api_destroy_login_response(&login_response);
473
+ }
474
+
475
+ static void test_process_login_response_text()
476
+ {
477
+ rc_api_login_response_t login_response;
478
+ const char* server_response = "You do not have access to that resource";
479
+
480
+ memset(&login_response, 0, sizeof(login_response));
481
+
482
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_INVALID_JSON);
483
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
484
+ ASSERT_STR_EQUALS(login_response.response.error_message, "You do not have access to that resource");
485
+ ASSERT_PTR_NULL(login_response.username);
486
+ ASSERT_PTR_NULL(login_response.api_token);
487
+ ASSERT_NUM_EQUALS(login_response.score, 0);
488
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
489
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
490
+ ASSERT_PTR_NULL(login_response.display_name);
491
+
492
+ rc_api_destroy_login_response(&login_response);
493
+ }
494
+
495
+ static void test_process_login_response_html()
496
+ {
497
+ rc_api_login_response_t login_response;
498
+ const char* server_response = "<b>You do not have access to that resource</b>";
499
+
500
+ memset(&login_response, 0, sizeof(login_response));
501
+
502
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_INVALID_JSON);
503
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
504
+ ASSERT_STR_EQUALS(login_response.response.error_message, "<b>You do not have access to that resource</b>");
505
+ ASSERT_PTR_NULL(login_response.username);
506
+ ASSERT_PTR_NULL(login_response.api_token);
507
+ ASSERT_NUM_EQUALS(login_response.score, 0);
508
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
509
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
510
+ ASSERT_PTR_NULL(login_response.display_name);
511
+
512
+ rc_api_destroy_login_response(&login_response);
513
+ }
514
+
515
+ static void test_process_login_response_no_required_fields()
516
+ {
517
+ rc_api_login_response_t login_response;
518
+ const char* server_response = "{\"Success\":true}";
519
+
520
+ memset(&login_response, 0, sizeof(login_response));
521
+
522
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_MISSING_VALUE);
523
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
524
+ ASSERT_STR_EQUALS(login_response.response.error_message, "User not found in response");
525
+ ASSERT_PTR_NULL(login_response.username);
526
+ ASSERT_PTR_NULL(login_response.api_token);
527
+ ASSERT_NUM_EQUALS(login_response.score, 0);
528
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
529
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
530
+ ASSERT_PTR_NULL(login_response.display_name);
531
+
532
+ rc_api_destroy_login_response(&login_response);
533
+ }
534
+
535
+ static void test_process_login_response_no_token()
536
+ {
537
+ rc_api_login_response_t login_response;
538
+ const char* server_response = "{\"Success\":true,\"User\":\"Username\"}";
539
+
540
+ memset(&login_response, 0, sizeof(login_response));
541
+
542
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_MISSING_VALUE);
543
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 0);
544
+ ASSERT_STR_EQUALS(login_response.response.error_message, "Token not found in response");
545
+ ASSERT_STR_EQUALS(login_response.username, "Username");
546
+ ASSERT_PTR_NULL(login_response.api_token);
547
+ ASSERT_NUM_EQUALS(login_response.score, 0);
548
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
549
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
550
+ ASSERT_PTR_NULL(login_response.display_name);
551
+
552
+ rc_api_destroy_login_response(&login_response);
553
+ }
554
+
555
+ static void test_process_login_response_no_optional_fields()
556
+ {
557
+ rc_api_login_response_t login_response;
558
+ const char* server_response = "{\"Success\":true,\"User\":\"USER\",\"Token\":\"ApiTOKEN\"}";
559
+
560
+ memset(&login_response, 0, sizeof(login_response));
561
+
562
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_OK);
563
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 1);
564
+ ASSERT_PTR_NULL(login_response.response.error_message);
565
+ ASSERT_STR_EQUALS(login_response.username, "USER");
566
+ ASSERT_STR_EQUALS(login_response.api_token, "ApiTOKEN");
567
+ ASSERT_NUM_EQUALS(login_response.score, 0);
568
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
569
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
570
+ ASSERT_STR_EQUALS(login_response.display_name, "USER");
571
+
572
+ rc_api_destroy_login_response(&login_response);
573
+ }
574
+
575
+ static void test_process_login_response_null_score()
576
+ {
577
+ rc_api_login_response_t login_response;
578
+ const char* server_response = "{\"Success\":true,\"User\":\"USER\",\"Token\":\"ApiTOKEN\",\"Score\":null,\"SoftcoreScore\":null}";
579
+
580
+ memset(&login_response, 0, sizeof(login_response));
581
+
582
+ ASSERT_NUM_EQUALS(rc_api_process_login_response(&login_response, server_response), RC_OK);
583
+ ASSERT_NUM_EQUALS(login_response.response.succeeded, 1);
584
+ ASSERT_PTR_NULL(login_response.response.error_message);
585
+ ASSERT_STR_EQUALS(login_response.username, "USER");
586
+ ASSERT_STR_EQUALS(login_response.api_token, "ApiTOKEN");
587
+ ASSERT_NUM_EQUALS(login_response.score, 0);
588
+ ASSERT_NUM_EQUALS(login_response.score_softcore, 0);
589
+ ASSERT_NUM_EQUALS(login_response.num_unread_messages, 0);
590
+ ASSERT_STR_EQUALS(login_response.display_name, "USER");
591
+
592
+ rc_api_destroy_login_response(&login_response);
593
+ }
594
+
595
+ static void test_init_fetch_user_unlocks_request_non_hardcore()
596
+ {
597
+ rc_api_fetch_user_unlocks_request_t fetch_user_unlocks_request;
598
+ rc_api_request_t request;
599
+
600
+ memset(&fetch_user_unlocks_request, 0, sizeof(fetch_user_unlocks_request));
601
+ fetch_user_unlocks_request.username = "Username";
602
+ fetch_user_unlocks_request.api_token = "API_TOKEN";
603
+ fetch_user_unlocks_request.game_id = 1234;
604
+ fetch_user_unlocks_request.hardcore = 0;
605
+
606
+ ASSERT_NUM_EQUALS(rc_api_init_fetch_user_unlocks_request(&request, &fetch_user_unlocks_request), RC_OK);
607
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
608
+ ASSERT_STR_EQUALS(request.post_data, "r=unlocks&u=Username&t=API_TOKEN&g=1234&h=0");
609
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
610
+
611
+ rc_api_destroy_request(&request);
612
+ }
613
+
614
+ static void test_init_fetch_user_unlocks_request_hardcore()
615
+ {
616
+ rc_api_fetch_user_unlocks_request_t fetch_user_unlocks_request;
617
+ rc_api_request_t request;
618
+
619
+ memset(&fetch_user_unlocks_request, 0, sizeof(fetch_user_unlocks_request));
620
+ fetch_user_unlocks_request.username = "Username";
621
+ fetch_user_unlocks_request.api_token = "API_TOKEN";
622
+ fetch_user_unlocks_request.game_id = 2345;
623
+ fetch_user_unlocks_request.hardcore = 1;
624
+
625
+ ASSERT_NUM_EQUALS(rc_api_init_fetch_user_unlocks_request(&request, &fetch_user_unlocks_request), RC_OK);
626
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
627
+ ASSERT_STR_EQUALS(request.post_data, "r=unlocks&u=Username&t=API_TOKEN&g=2345&h=1");
628
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
629
+
630
+ rc_api_destroy_request(&request);
631
+ }
632
+
633
+ static void test_init_fetch_user_unlocks_response_empty_array()
634
+ {
635
+ rc_api_fetch_user_unlocks_response_t fetch_user_unlocks_response;
636
+ const char* server_response = "{\"Success\":true,\"UserUnlocks\":[],\"GameID\":11277,\"HardcoreMode\":false}";
637
+ memset(&fetch_user_unlocks_response, 0, sizeof(fetch_user_unlocks_response));
638
+
639
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_user_unlocks_response(&fetch_user_unlocks_response, server_response), RC_OK);
640
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.response.succeeded, 1);
641
+ ASSERT_PTR_NULL(fetch_user_unlocks_response.response.error_message);
642
+ ASSERT_PTR_NULL(fetch_user_unlocks_response.achievement_ids);
643
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.num_achievement_ids, 0);
644
+
645
+ rc_api_destroy_fetch_user_unlocks_response(&fetch_user_unlocks_response);
646
+ }
647
+
648
+ static void test_init_fetch_user_unlocks_response_invalid_credentials()
649
+ {
650
+ rc_api_fetch_user_unlocks_response_t fetch_user_unlocks_response;
651
+ const char* server_response = "{\"Success\":false,\"Error\":\"Credentials invalid (0)\"}";
652
+ memset(&fetch_user_unlocks_response, 0, sizeof(fetch_user_unlocks_response));
653
+
654
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_user_unlocks_response(&fetch_user_unlocks_response, server_response), RC_OK);
655
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.response.succeeded, 0);
656
+ ASSERT_STR_EQUALS(fetch_user_unlocks_response.response.error_message, "Credentials invalid (0)");
657
+ ASSERT_PTR_NULL(fetch_user_unlocks_response.achievement_ids);
658
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.num_achievement_ids, 0);
659
+
660
+ rc_api_destroy_fetch_user_unlocks_response(&fetch_user_unlocks_response);
661
+ }
662
+
663
+ static void test_init_fetch_user_unlocks_response_one_item()
664
+ {
665
+ rc_api_fetch_user_unlocks_response_t fetch_user_unlocks_response;
666
+ const char* server_response = "{\"Success\":true,\"UserUnlocks\":[1234],\"GameID\":11277,\"HardcoreMode\":false}";
667
+ memset(&fetch_user_unlocks_response, 0, sizeof(fetch_user_unlocks_response));
668
+
669
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_user_unlocks_response(&fetch_user_unlocks_response, server_response), RC_OK);
670
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.response.succeeded, 1);
671
+ ASSERT_PTR_NULL(fetch_user_unlocks_response.response.error_message);
672
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.num_achievement_ids, 1);
673
+ ASSERT_PTR_NOT_NULL(fetch_user_unlocks_response.achievement_ids);
674
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.achievement_ids[0], 1234);
675
+
676
+ rc_api_destroy_fetch_user_unlocks_response(&fetch_user_unlocks_response);
677
+ }
678
+
679
+ static void test_init_fetch_user_unlocks_response_several_items()
680
+ {
681
+ rc_api_fetch_user_unlocks_response_t fetch_user_unlocks_response;
682
+ const char* server_response = "{\"Success\":true,\"UserUnlocks\":[1,2,3,4],\"GameID\":11277,\"HardcoreMode\":false}";
683
+ memset(&fetch_user_unlocks_response, 0, sizeof(fetch_user_unlocks_response));
684
+
685
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_user_unlocks_response(&fetch_user_unlocks_response, server_response), RC_OK);
686
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.response.succeeded, 1);
687
+ ASSERT_PTR_NULL(fetch_user_unlocks_response.response.error_message);
688
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.num_achievement_ids, 4);
689
+ ASSERT_PTR_NOT_NULL(fetch_user_unlocks_response.achievement_ids);
690
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.achievement_ids[0], 1);
691
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.achievement_ids[1], 2);
692
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.achievement_ids[2], 3);
693
+ ASSERT_NUM_EQUALS(fetch_user_unlocks_response.achievement_ids[3], 4);
694
+
695
+ rc_api_destroy_fetch_user_unlocks_response(&fetch_user_unlocks_response);
696
+ }
697
+
698
+ static void test_init_fetch_followed_users_request()
699
+ {
700
+ rc_api_fetch_followed_users_request_t fetch_followed_users_request;
701
+ rc_api_request_t request;
702
+
703
+ memset(&fetch_followed_users_request, 0, sizeof(fetch_followed_users_request));
704
+ fetch_followed_users_request.username = "Username";
705
+ fetch_followed_users_request.api_token = "API_TOKEN";
706
+
707
+ ASSERT_NUM_EQUALS(rc_api_init_fetch_followed_users_request(&request, &fetch_followed_users_request), RC_OK);
708
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
709
+ ASSERT_STR_EQUALS(request.post_data, "r=getfriendlist&u=Username&t=API_TOKEN");
710
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
711
+
712
+ rc_api_destroy_request(&request);
713
+ }
714
+
715
+ static void test_init_fetch_followed_users_response_empty_array()
716
+ {
717
+ rc_api_fetch_followed_users_response_t fetch_followed_users_response;
718
+ rc_api_server_response_t server_response;
719
+ memset(&fetch_followed_users_response, 0, sizeof(fetch_followed_users_response));
720
+
721
+ memset(&server_response, 0, sizeof(server_response));
722
+ server_response.body = "{\"Success\":true,\"Friends\":[]}";
723
+ server_response.body_length = strlen(server_response.body);
724
+
725
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_followed_users_server_response(&fetch_followed_users_response, &server_response), RC_OK);
726
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.response.succeeded, 1);
727
+ ASSERT_PTR_NULL(fetch_followed_users_response.response.error_message);
728
+ ASSERT_PTR_NULL(fetch_followed_users_response.users);
729
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.num_users, 0);
730
+
731
+ rc_api_destroy_fetch_followed_users_response(&fetch_followed_users_response);
732
+ }
733
+
734
+ static void test_init_fetch_followed_users_response_invalid_credentials()
735
+ {
736
+ rc_api_fetch_followed_users_response_t fetch_followed_users_response;
737
+ rc_api_server_response_t server_response;
738
+ memset(&fetch_followed_users_response, 0, sizeof(fetch_followed_users_response));
739
+
740
+ memset(&server_response, 0, sizeof(server_response));
741
+ server_response.body = "{\"Success\":false,\"Error\":\"Credentials invalid (0)\"}";
742
+ server_response.body_length = strlen(server_response.body);
743
+
744
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_followed_users_server_response(&fetch_followed_users_response, &server_response), RC_OK);
745
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.response.succeeded, 0);
746
+ ASSERT_STR_EQUALS(fetch_followed_users_response.response.error_message, "Credentials invalid (0)");
747
+ ASSERT_PTR_NULL(fetch_followed_users_response.users);
748
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.num_users, 0);
749
+
750
+ rc_api_destroy_fetch_followed_users_response(&fetch_followed_users_response);
751
+ }
752
+
753
+ static void test_init_fetch_followed_users_response_several_items()
754
+ {
755
+ rc_api_fetch_followed_users_response_t fetch_followed_users_response;
756
+ rc_api_server_response_t server_response;
757
+ memset(&fetch_followed_users_response, 0, sizeof(fetch_followed_users_response));
758
+
759
+ memset(&server_response, 0, sizeof(server_response));
760
+ server_response.body = "{\"Success\":true,\"Friends\":["
761
+ "{\"Friend\":\"Bob\",\"AvatarUrl\":\"/User/Bob.png\",\"RAPoints\":1234,\"LastSeen\":\"Doing stuff\"}," /* legacy format */
762
+ "{\"Friend\":\"Jane\",\"AvatarUrl\":\"/User/Jane.png\",\"RAPoints\":5,\"LastSeen\":\"Winning\","
763
+ "\"LastSeenTime\":1234567890,\"LastGameId\":6,\"LastGameTitle\":\"The Game\",\"LastGameIconUrl\":\"/Badges/000006.png\"},"
764
+ "{\"Friend\":\"Bill\",\"AvatarUrl\":\"/User/Bill.png\",\"RAPoints\":0,\"LastSeen\":\"Unknown\","
765
+ "\"LastSeenTime\":1234567800,\"LastGameId\":null,\"LastGameTitle\":null,\"LastGameIconUrl\":null}"
766
+ "]}";
767
+ server_response.body_length = strlen(server_response.body);
768
+
769
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_followed_users_server_response(&fetch_followed_users_response, &server_response), RC_OK);
770
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.response.succeeded, 1);
771
+ ASSERT_PTR_NULL(fetch_followed_users_response.response.error_message);
772
+ ASSERT_PTR_NOT_NULL(fetch_followed_users_response.users);
773
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.num_users, 3);
774
+
775
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[0].display_name, "Bob");
776
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[0].avatar_url, "/User/Bob.png");
777
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[0].score, 1234);
778
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[0].recent_activity.description, "Doing stuff");
779
+ ASSERT_PTR_NULL(fetch_followed_users_response.users[0].recent_activity.context);
780
+ ASSERT_PTR_NULL(fetch_followed_users_response.users[0].recent_activity.context_image_url);
781
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[0].recent_activity.context_id, 0);
782
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[0].recent_activity.when, 0);
783
+
784
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[1].display_name, "Jane");
785
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[1].avatar_url, "/User/Jane.png");
786
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[1].score, 5);
787
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[1].recent_activity.description, "Winning");
788
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[1].recent_activity.context, "The Game");
789
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[1].recent_activity.context_image_url, "/Badges/000006.png");
790
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[1].recent_activity.context_id, 6);
791
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[1].recent_activity.when, 1234567890);
792
+
793
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[2].display_name, "Bill");
794
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[2].avatar_url, "/User/Bill.png");
795
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[2].score, 0);
796
+ ASSERT_STR_EQUALS(fetch_followed_users_response.users[2].recent_activity.description, "Unknown");
797
+ ASSERT_PTR_NULL(fetch_followed_users_response.users[2].recent_activity.context);
798
+ ASSERT_PTR_NULL(fetch_followed_users_response.users[2].recent_activity.context_image_url);
799
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[2].recent_activity.context_id, 0);
800
+ ASSERT_NUM_EQUALS(fetch_followed_users_response.users[2].recent_activity.when, 1234567800);
801
+
802
+ rc_api_destroy_fetch_followed_users_response(&fetch_followed_users_response);
803
+ }
804
+
805
+ static void test_init_fetch_all_user_progress_request()
806
+ {
807
+ rc_api_fetch_all_user_progress_request_t fetch_all_user_progress_request;
808
+ rc_api_request_t request;
809
+
810
+ memset(&fetch_all_user_progress_request, 0, sizeof(fetch_all_user_progress_request));
811
+ fetch_all_user_progress_request.username = "Username";
812
+ fetch_all_user_progress_request.api_token = "API_TOKEN";
813
+ fetch_all_user_progress_request.console_id = 1;
814
+
815
+ ASSERT_NUM_EQUALS(rc_api_init_fetch_all_user_progress_request(&request, &fetch_all_user_progress_request), RC_OK);
816
+ ASSERT_STR_EQUALS(request.url, DOREQUEST_URL);
817
+ ASSERT_STR_EQUALS(request.post_data, "r=allprogress&u=Username&t=API_TOKEN&c=1");
818
+ ASSERT_STR_EQUALS(request.content_type, RC_CONTENT_TYPE_URLENCODED);
819
+
820
+ rc_api_destroy_request(&request);
821
+ }
822
+
823
+ static void test_init_fetch_all_user_progress_response_empty_array()
824
+ {
825
+ rc_api_fetch_all_user_progress_response_t fetch_all_user_progress_response;
826
+ rc_api_server_response_t response_obj;
827
+ const char* server_response = "{\"Success\":true,\"Response\":[]}";
828
+
829
+ memset(&response_obj, 0, sizeof(response_obj));
830
+ response_obj.body = server_response;
831
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
832
+ response_obj.http_status_code = 200;
833
+
834
+ memset(&fetch_all_user_progress_response, 0, sizeof(fetch_all_user_progress_response));
835
+
836
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_all_user_progress_server_response(&fetch_all_user_progress_response, &response_obj), RC_OK);
837
+
838
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.response.succeeded, 1);
839
+ ASSERT_PTR_NULL(fetch_all_user_progress_response.response.error_message);
840
+ ASSERT_PTR_NULL(fetch_all_user_progress_response.entries);
841
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.num_entries, 0);
842
+
843
+ rc_api_destroy_fetch_all_user_progress_response(&fetch_all_user_progress_response);
844
+ }
845
+
846
+ static void test_init_fetch_all_user_progress_response_invalid_credentials()
847
+ {
848
+ rc_api_fetch_all_user_progress_response_t fetch_all_user_progress_response;
849
+ rc_api_server_response_t response_obj;
850
+ const char* server_response = "{\"Success\":false,\"Error\":\"Credentials invalid (0)\"}";
851
+ memset(&fetch_all_user_progress_response, 0, sizeof(fetch_all_user_progress_response));
852
+
853
+ memset(&response_obj, 0, sizeof(response_obj));
854
+ response_obj.body = server_response;
855
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
856
+ response_obj.http_status_code = 200;
857
+
858
+ memset(&fetch_all_user_progress_response, 0, sizeof(fetch_all_user_progress_response));
859
+
860
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_all_user_progress_server_response(&fetch_all_user_progress_response, &response_obj), RC_OK);
861
+
862
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.response.succeeded, 0);
863
+ ASSERT_STR_EQUALS(fetch_all_user_progress_response.response.error_message, "Credentials invalid (0)");
864
+ ASSERT_PTR_NULL(fetch_all_user_progress_response.entries);
865
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.num_entries, 0);
866
+
867
+ rc_api_destroy_fetch_all_user_progress_response(&fetch_all_user_progress_response);
868
+ }
869
+
870
+ static void test_init_fetch_all_user_progress_response_one_item()
871
+ {
872
+ rc_api_fetch_all_user_progress_response_t fetch_all_user_progress_response;
873
+ rc_api_server_response_t response_obj;
874
+ const char* server_response = "{\"Success\":true,\"Response\":{\"10\":{\"Achievements\":11}}}";
875
+
876
+ memset(&response_obj, 0, sizeof(response_obj));
877
+ response_obj.body = server_response;
878
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
879
+ response_obj.http_status_code = 200;
880
+
881
+ memset(&fetch_all_user_progress_response, 0, sizeof(fetch_all_user_progress_response));
882
+
883
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_all_user_progress_server_response(&fetch_all_user_progress_response, &response_obj), RC_OK);
884
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.response.succeeded, 1);
885
+ ASSERT_PTR_NULL(fetch_all_user_progress_response.response.error_message);
886
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.num_entries, 1);
887
+ ASSERT_PTR_NOT_NULL(fetch_all_user_progress_response.entries);
888
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].game_id, 10);
889
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].num_achievements, 11);
890
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].num_unlocked_achievements, 0);
891
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].num_unlocked_achievements_hardcore, 0);
892
+
893
+ rc_api_destroy_fetch_all_user_progress_response(&fetch_all_user_progress_response);
894
+ }
895
+
896
+ static void test_init_fetch_all_user_progress_response_several_items()
897
+ {
898
+ rc_api_fetch_all_user_progress_response_t fetch_all_user_progress_response;
899
+ rc_api_server_response_t response_obj;
900
+
901
+ const char* server_response = "{\"Success\":true,\"Response\":{\"10\":{\"Achievements\":11},"
902
+ "\"20\":{\"Achievements\":21,\"Unlocked\":22},"
903
+ "\"30\":{\"Achievements\":31,\"Unlocked\":32,\"UnlockedHardcore\":33},"
904
+ "\"40\":{\"Achievements\":41,\"UnlockedHardcore\":43}}}";
905
+
906
+ memset(&response_obj, 0, sizeof(response_obj));
907
+ response_obj.body = server_response;
908
+ response_obj.body_length = rc_json_get_object_string_length(server_response);
909
+ response_obj.http_status_code = 200;
910
+
911
+ memset(&fetch_all_user_progress_response, 0, sizeof(fetch_all_user_progress_response));
912
+
913
+ ASSERT_NUM_EQUALS(rc_api_process_fetch_all_user_progress_server_response(&fetch_all_user_progress_response, &response_obj), RC_OK);
914
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.response.succeeded, 1);
915
+ ASSERT_PTR_NULL(fetch_all_user_progress_response.response.error_message);
916
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.num_entries, 4);
917
+ ASSERT_PTR_NOT_NULL(fetch_all_user_progress_response.entries);
918
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].game_id, 10);
919
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].num_achievements, 11);
920
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].num_unlocked_achievements, 0);
921
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[0].num_unlocked_achievements_hardcore, 0);
922
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[1].game_id, 20);
923
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[1].num_achievements, 21);
924
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[1].num_unlocked_achievements, 22);
925
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[1].num_unlocked_achievements_hardcore, 0);
926
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[2].game_id, 30);
927
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[2].num_achievements, 31);
928
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[2].num_unlocked_achievements, 32);
929
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[2].num_unlocked_achievements_hardcore, 33);
930
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[3].game_id, 40);
931
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[3].num_achievements, 41);
932
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[3].num_unlocked_achievements, 0);
933
+ ASSERT_NUM_EQUALS(fetch_all_user_progress_response.entries[3].num_unlocked_achievements_hardcore, 43);
934
+
935
+ rc_api_destroy_fetch_all_user_progress_response(&fetch_all_user_progress_response);
936
+ }
937
+
938
+ void test_rapi_user(void) {
939
+ TEST_SUITE_BEGIN();
940
+
941
+ /* start session */
942
+ TEST(test_init_start_session_request);
943
+ TEST(test_init_start_session_request_no_game);
944
+ TEST(test_init_start_session_request_game_hash_softcore);
945
+ TEST(test_init_start_session_request_game_hash_hardcore);
946
+
947
+ TEST(test_process_start_session_response_legacy);
948
+ TEST(test_process_start_session_response);
949
+ TEST(test_process_start_session_response_invalid_credentials);
950
+
951
+ /* login */
952
+ TEST(test_init_login_request_password);
953
+ TEST(test_init_login_request_password_long);
954
+ TEST(test_init_login_request_token);
955
+ TEST(test_init_login_request_password_and_token);
956
+ TEST(test_init_login_request_no_password_or_token);
957
+ TEST(test_init_login_request_alternate_host);
958
+
959
+ TEST(test_process_login_response_success);
960
+ TEST(test_process_login_response_unique_display_name);
961
+ TEST(test_process_login_response_invalid_credentials);
962
+ TEST(test_process_login_response_access_denied);
963
+ TEST(test_process_login_response_generic_failure);
964
+ TEST(test_process_login_response_expired_token);
965
+ TEST(test_process_login_response_empty);
966
+ TEST(test_process_login_response_text);
967
+ TEST(test_process_login_response_html);
968
+ TEST(test_process_login_response_no_required_fields);
969
+ TEST(test_process_login_response_no_token);
970
+ TEST(test_process_login_response_no_optional_fields);
971
+ TEST(test_process_login_response_null_score);
972
+
973
+ /* unlocks */
974
+ TEST(test_init_fetch_user_unlocks_request_non_hardcore);
975
+ TEST(test_init_fetch_user_unlocks_request_hardcore);
976
+
977
+ TEST(test_init_fetch_user_unlocks_response_empty_array);
978
+ TEST(test_init_fetch_user_unlocks_response_invalid_credentials);
979
+ TEST(test_init_fetch_user_unlocks_response_one_item);
980
+ TEST(test_init_fetch_user_unlocks_response_several_items);
981
+
982
+ /* followed users */
983
+ TEST(test_init_fetch_followed_users_request);
984
+
985
+ TEST(test_init_fetch_followed_users_response_empty_array);
986
+ TEST(test_init_fetch_followed_users_response_invalid_credentials);
987
+ TEST(test_init_fetch_followed_users_response_several_items);
988
+
989
+ /* all user progress */
990
+ TEST(test_init_fetch_all_user_progress_request);
991
+
992
+ TEST(test_init_fetch_all_user_progress_response_empty_array);
993
+ TEST(test_init_fetch_all_user_progress_response_invalid_credentials);
994
+ TEST(test_init_fetch_all_user_progress_response_one_item);
995
+ TEST(test_init_fetch_all_user_progress_response_several_items);
996
+
997
+ TEST_SUITE_END();
998
+ }