summaryrefslogtreecommitdiffstats
path: root/tests/server_core.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/server_core.rs')
-rw-r--r--tests/server_core.rs33
1 files changed, 20 insertions, 13 deletions
diff --git a/tests/server_core.rs b/tests/server_core.rs
index fe2b3d3..f3736e9 100644
--- a/tests/server_core.rs
+++ b/tests/server_core.rs
@@ -6,7 +6,7 @@ use zagan_bet::server::database;
6use zagan_bet::server::games::registry::GameRegistry; 6use zagan_bet::server::games::registry::GameRegistry;
7use zagan_bet::server::games::slots::SlotsGame; 7use zagan_bet::server::games::slots::SlotsGame;
8 8
9fn setup(name: &str, reels: &str) -> (ServerCore, String) { 9fn setup(name: &str, grid: &str) -> (ServerCore, String) {
10 let path = PathBuf::from(env!("CARGO_TARGET_TMPDIR")) 10 let path = PathBuf::from(env!("CARGO_TARGET_TMPDIR"))
11 .join(format!("server-core-{name}.db")) 11 .join(format!("server-core-{name}.db"))
12 .to_string_lossy() 12 .to_string_lossy()
@@ -17,12 +17,18 @@ fn setup(name: &str, reels: &str) -> (ServerCore, String) {
17 database::init_db(&conn); 17 database::init_db(&conn);
18 18
19 let registry = GameRegistry::new(); 19 let registry = GameRegistry::new();
20 registry.register_game(SlotsGame::with_reels(reels)); 20 registry.register_game(SlotsGame::with_grid(grid));
21 21
22 // Low bcrypt cost keeps the tests fast. 22 // Low bcrypt cost keeps the tests fast.
23 (ServerCore::with_registry(conn, registry, 4), path) 23 (ServerCore::with_registry(conn, registry, 4), path)
24} 24}
25 25
26/// Column-major 5x3 grid with no winning line.
27const LOSS: &str = "CLOOGDSLCDCOGLS";
28
29/// Top line is C C C D D; it pays 2x total bet.
30const WIN3: &str = "CCCCLLCLODGSDGS";
31
26fn register(core: &mut ServerCore, state: &mut ConnectionState, user: &str) { 32fn register(core: &mut ServerCore, state: &mut ConnectionState, user: &str) {
27 assert_eq!( 33 assert_eq!(
28 core.handle_message(state, &format!("REGISTER {user} credential")), 34 core.handle_message(state, &format!("REGISTER {user} credential")),
@@ -39,7 +45,7 @@ fn login(core: &mut ServerCore, state: &mut ConnectionState, user: &str) {
39 45
40#[test] 46#[test]
41fn register_stores_a_bcrypt_hash_and_auth_accepts_it() { 47fn register_stores_a_bcrypt_hash_and_auth_accepts_it() {
42 let (mut core, path) = setup("register", "CLO"); 48 let (mut core, path) = setup("register", LOSS);
43 let mut state = ConnectionState::default(); 49 let mut state = ConnectionState::default();
44 50
45 register(&mut core, &mut state, "alice"); 51 register(&mut core, &mut state, "alice");
@@ -59,7 +65,7 @@ fn register_stores_a_bcrypt_hash_and_auth_accepts_it() {
59 65
60#[test] 66#[test]
61fn the_same_credential_gets_a_different_salt() { 67fn the_same_credential_gets_a_different_salt() {
62 let (mut core, path) = setup("salt", "CLO"); 68 let (mut core, path) = setup("salt", LOSS);
63 let mut state = ConnectionState::default(); 69 let mut state = ConnectionState::default();
64 70
65 register(&mut core, &mut state, "alice"); 71 register(&mut core, &mut state, "alice");
@@ -73,7 +79,7 @@ fn the_same_credential_gets_a_different_salt() {
73 79
74#[test] 80#[test]
75fn legacy_sha256_rows_are_upgraded_on_login() { 81fn legacy_sha256_rows_are_upgraded_on_login() {
76 let (mut core, path) = setup("legacy", "CLO"); 82 let (mut core, path) = setup("legacy", LOSS);
77 let conn = Connection::open(&path).unwrap(); 83 let conn = Connection::open(&path).unwrap();
78 database::add_user(&conn, "legacy", "deadbeef").unwrap(); 84 database::add_user(&conn, "legacy", "deadbeef").unwrap();
79 85
@@ -96,7 +102,7 @@ fn legacy_sha256_rows_are_upgraded_on_login() {
96 102
97#[test] 103#[test]
98fn duplicate_registration_returns_an_error() { 104fn duplicate_registration_returns_an_error() {
99 let (mut core, _path) = setup("duplicate", "CLO"); 105 let (mut core, _path) = setup("duplicate", LOSS);
100 let mut state = ConnectionState::default(); 106 let mut state = ConnectionState::default();
101 107
102 register(&mut core, &mut state, "alice"); 108 register(&mut core, &mut state, "alice");
@@ -108,7 +114,7 @@ fn duplicate_registration_returns_an_error() {
108 114
109#[test] 115#[test]
110fn a_malicious_username_cannot_change_another_balance() { 116fn a_malicious_username_cannot_change_another_balance() {
111 let (mut core, _path) = setup("injection", "CLO"); 117 let (mut core, _path) = setup("injection", LOSS);
112 let mut admin = ConnectionState::default(); 118 let mut admin = ConnectionState::default();
113 register(&mut core, &mut admin, "victim"); 119 register(&mut core, &mut admin, "victim");
114 120
@@ -132,7 +138,7 @@ fn a_malicious_username_cannot_change_another_balance() {
132 138
133#[test] 139#[test]
134fn a_failed_audit_insert_rolls_back_the_balance_change() { 140fn a_failed_audit_insert_rolls_back_the_balance_change() {
135 let (mut core, path) = setup("rollback", "CLO"); 141 let (mut core, path) = setup("rollback", LOSS);
136 let mut state = ConnectionState::default(); 142 let mut state = ConnectionState::default();
137 register(&mut core, &mut state, "alice"); 143 register(&mut core, &mut state, "alice");
138 login(&mut core, &mut state, "alice"); 144 login(&mut core, &mut state, "alice");
@@ -155,7 +161,7 @@ fn a_failed_audit_insert_rolls_back_the_balance_change() {
155 161
156#[test] 162#[test]
157fn spins_write_audit_rows_and_leave_no_sessions() { 163fn spins_write_audit_rows_and_leave_no_sessions() {
158 let (mut core, _path) = setup("audit", "CLO"); 164 let (mut core, _path) = setup("audit", LOSS);
159 let mut state = ConnectionState::default(); 165 let mut state = ConnectionState::default();
160 register(&mut core, &mut state, "alice"); 166 register(&mut core, &mut state, "alice");
161 login(&mut core, &mut state, "alice"); 167 login(&mut core, &mut state, "alice");
@@ -175,7 +181,7 @@ fn spins_write_audit_rows_and_leave_no_sessions() {
175 181
176#[test] 182#[test]
177fn a_winning_spin_updates_the_balance_and_the_audit_row() { 183fn a_winning_spin_updates_the_balance_and_the_audit_row() {
178 let (mut core, _path) = setup("win", "CCC"); 184 let (mut core, _path) = setup("win", WIN3);
179 let mut state = ConnectionState::default(); 185 let mut state = ConnectionState::default();
180 register(&mut core, &mut state, "alice"); 186 register(&mut core, &mut state, "alice");
181 login(&mut core, &mut state, "alice"); 187 login(&mut core, &mut state, "alice");
@@ -183,6 +189,7 @@ fn a_winning_spin_updates_the_balance_and_the_audit_row() {
183 let response = core.handle_message(&mut state, "PLAY_START slots 10"); 189 let response = core.handle_message(&mut state, "PLAY_START slots 10");
184 assert!(response.starts_with("GAME_RESULT"), "spin failed: {response}"); 190 assert!(response.starts_with("GAME_RESULT"), "spin failed: {response}");
185 assert!(response.contains(" 20 10 1010 "), "response: {response}"); 191 assert!(response.contains(" 20 10 1010 "), "response: {response}");
192 assert!(response.ends_with(" win 1"), "response: {response}");
186 193
187 assert_eq!(core.balance("alice"), Some(1010)); 194 assert_eq!(core.balance("alice"), Some(1010));
188 assert_eq!(core.play_count("alice"), 1); 195 assert_eq!(core.play_count("alice"), 1);
@@ -191,7 +198,7 @@ fn a_winning_spin_updates_the_balance_and_the_audit_row() {
191 198
192#[test] 199#[test]
193fn insufficient_balance_does_not_write_an_audit_row() { 200fn insufficient_balance_does_not_write_an_audit_row() {
194 let (mut core, path) = setup("insufficient", "CLO"); 201 let (mut core, path) = setup("insufficient", LOSS);
195 let mut state = ConnectionState::default(); 202 let mut state = ConnectionState::default();
196 register(&mut core, &mut state, "alice"); 203 register(&mut core, &mut state, "alice");
197 login(&mut core, &mut state, "alice"); 204 login(&mut core, &mut state, "alice");
@@ -211,7 +218,7 @@ fn insufficient_balance_does_not_write_an_audit_row() {
211 218
212#[test] 219#[test]
213fn a_negative_balance_is_rejected_without_wrapping() { 220fn a_negative_balance_is_rejected_without_wrapping() {
214 let (mut core, path) = setup("negative", "CLO"); 221 let (mut core, path) = setup("negative", LOSS);
215 let mut state = ConnectionState::default(); 222 let mut state = ConnectionState::default();
216 register(&mut core, &mut state, "alice"); 223 register(&mut core, &mut state, "alice");
217 login(&mut core, &mut state, "alice"); 224 login(&mut core, &mut state, "alice");
@@ -233,7 +240,7 @@ fn a_negative_balance_is_rejected_without_wrapping() {
233 240
234#[test] 241#[test]
235fn unknown_games_are_rejected_before_a_session_is_created() { 242fn unknown_games_are_rejected_before_a_session_is_created() {
236 let (mut core, _path) = setup("unknown", "CLO"); 243 let (mut core, _path) = setup("unknown", LOSS);
237 let mut state = ConnectionState::default(); 244 let mut state = ConnectionState::default();
238 register(&mut core, &mut state, "alice"); 245 register(&mut core, &mut state, "alice");
239 login(&mut core, &mut state, "alice"); 246 login(&mut core, &mut state, "alice");