use super::*; use serde_json::json; use std::fs; use std::path; const TEST_DB_PATH: &str = "./fixtures/database"; const TEST_DB_MOVED_PATH: &str = "./fixtures/moved"; const NO_DB_MESSAGE: &str = "Can not find/load test database"; struct TestCleanup { path: String, clear_moved: bool, } impl Drop for TestCleanup { fn drop(&mut self) { let _ = fs::remove_dir_all(&self.path); if self.clear_moved { let _ = fs::remove_dir_all(TEST_DB_MOVED_PATH); } } } fn prepare_db_copy(copy_id: &str, clear_moved: bool) -> (String, TestCleanup) { let path = format!("{}_{}", TEST_DB_PATH, copy_id); let original_db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); original_db .write_copy(path::Path::new(&path)) .expect("Should be able to create a new copy of the fixture database."); ( path.clone(), TestCleanup { path: path.to_owned(), clear_moved: clear_moved, }, ) } #[test] fn db_path() { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); assert!(db.path() == path::Path::new(TEST_DB_PATH)); } #[test] fn db_clear() { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); db.clear(); assert!(!db.contains_group("game")); assert!(!db.contains_file("administration", "registered")); let names = db.group_names(); assert_eq!(names.len(), 0); } #[test] fn db_group_names() { let db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let names = db.group_names(); assert!(names.contains(&"administration".to_owned())); assert!(names.contains(&"game".to_owned())); assert_eq!(names.len(), 2); } #[test] fn db_file_names() { let db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let names_admin = db.file_names_in("administration"); let names_game = db.file_names_in("game"); assert!(names_admin.contains(&"registered".to_owned())); assert!(names_game.contains(&"general".to_owned())); assert!(names_game.contains(&"perks".to_owned())); assert_eq!(names_admin.len(), 1); assert_eq!(names_game.len(), 2); } #[test] fn db_group_check() { let db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); assert!(db.contains_group("game")); assert!(db.contains_group("administration")); assert!(!db.contains_group("perks")); assert!(!db.contains_group("7random7")); assert!(!db.contains_group("")); } #[test] fn db_group_remove() -> Result<(), Box> { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); // Success db.remove_group("administration")?; db.remove_group("game")?; assert!(!db.contains_group("administration")); assert!(!db.contains_group("game")); // Failure db.remove_group("test") .expect_err("Testing whether removing non-existent groups with incorrect ASCII characters causes errors."); db.remove_group("administration") .expect_err("Testing whether removing non-existent groups with incorrect ASCII characters causes errors."); db.remove_group("game group").expect_err( "Testing whether removing non-existent groups with whitespace characters causes errors.", ); Ok(()) } #[test] fn db_group_create() -> Result<(), Box> { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); // Success db.create_group("7random7")?; assert!(db.contains_group("7random7")); assert!(db.contains_group("game")); // Failure db.create_group("my_group").expect_err( "Testing whether creating groups with incorrect ASCII characters causes errors.", ); db.create_group("my group") .expect_err("Testing whether creating groups with whitespace characters causes errors."); db.create_group("Š–group") .expect_err("Testing whether creating groups with non-ASCII characters causes errors."); // Create after removal db.remove_group("game")?; assert!(!db.contains_group("game")); db.create_group("game")?; assert!(db.contains_group("game")); assert!(db.file_names_in("game").is_empty()); Ok(()) } #[test] fn db_file_check() { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); // Success assert!(db.contains_file("administration", "registered")); assert!(db.file("game", "general").is_some()); assert!(db.file_mut("game", "perks").is_some()); // Failure assert!(!db.contains_file("game", "perk")); assert!(db.file("games", "perks").is_none()); assert!(db.file_mut("random", "rnd_file").is_none()); } #[test] fn db_file_create() -> Result<(), Box> { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); // Success let file = db.create_file("administration", "secrets")?; assert_eq!(file.to_string(), "{}"); assert!(db.contains_file("administration", "secrets")); assert!(db.contains_file("game", "perks")); // Failure db.create_file("administration", "secrets") .expect_err("Testing whether creating existing file causes errors."); db.create_file("none", "secrets") .expect_err("Testing whether creating existing file in non-existent group causes errors."); db.create_file("game", "sec_rets") .expect_err("Testing whether creating existing file with invalid name causes errors."); Ok(()) } #[test] fn db_file_remove() -> Result<(), Box> { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); // Success db.remove_file("administration", "registered")?; assert!(!db.contains_file("administration", "registered")); assert!(db.contains_group("administration")); db.remove_file("game", "perks")?; assert_eq!(db.file_names_in("game").len(), 1); // Failure db.remove_file("administration", "registered") .expect_err("Testing whether removing non-existent files causes errors."); db.remove_file("administration", "never") .expect_err("Testing whether removing non-existent files causes errors."); db.remove_file("never", "file") .expect_err("Testing whether removing non-existent files causes errors."); Ok(()) } #[test] fn file_json_contents() { let db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let registered = db.file("administration", "registered").unwrap().root(); let user_map = registered .as_object() .expect("Read value is not an object."); assert_eq!(user_map.len(), 2); assert!(user_map.contains_key("76561198025127722")); let user_record = user_map .get("76561198044316328") .unwrap() .as_object() .unwrap(); assert_eq!(user_record.len(), 3); assert_eq!(user_record.get("ip_lock").unwrap().as_bool(), Some(false)); assert_eq!( user_record.get("password_hash").unwrap().as_str(), Some("fce798e0804dfb217f929bdba26745024f37f6b6ba7406f3775176e20dd5089d") ); let groups_arrays = user_record.get("groups").unwrap().as_array().unwrap(); assert_eq!(groups_arrays.len(), 1); assert_eq!(groups_arrays[0], "admin"); } #[test] fn file_json_get() { let db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); // Test empty path let file = db.file("administration", "registered").unwrap(); assert_eq!(file.root(), file.get("").unwrap()); // Test complex path let expected = file.get("/76561198025127722/allowed_ips/1").unwrap(); assert_eq!(expected.as_str().unwrap(), "192.168.0.100"); // Test bad paths assert!(file.get("/777") == None); assert!(file.get("/76561198025127722/allowed_ips/2") == None); } #[test] fn file_contains_check() { let db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let registered_file = db.file("administration", "registered").unwrap(); let perks_file = db.file("game", "perks").unwrap(); // These exist assert!(registered_file.contains("/76561198025127722/password_hash")); assert!(registered_file.contains("/76561198044316328/groups/0")); assert!(perks_file.contains("/76561198025127722/headshots")); assert!(perks_file.contains("/76561198044316328")); // These do not exist assert!(!registered_file.contains("/76561198025127722/password/")); assert!(!registered_file.contains("/76561198044316328/groups/2")); assert!(!perks_file.contains("/76561198025127722/assault_rifle_damage/9067")); assert!(!perks_file.contains("/76561198044316328/headshots")); } #[test] fn db_insert_success() -> Result<(), Box> { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let registered_file = db.file_mut("administration", "registered").unwrap(); // Modify existing registered_file.insert("/76561198025127722/ip_lock", json!(false))?; assert_eq!( registered_file .get("/76561198025127722/ip_lock") .unwrap() .to_string(), "false" ); registered_file.insert("/76561198044316328/password_hash", json!({"var":13524}))?; assert_eq!( registered_file .get("/76561198044316328/password_hash") .unwrap() .to_string(), r#"{"var":13524}"# ); // Reset whole file registered_file.insert("", json!({}))?; assert_eq!(registered_file.root().to_string(), "{}"); // Add new values registered_file.insert("/new_var", json!([42, {"word":"life"}, null]))?; assert_eq!( registered_file.root().to_string(), r#"{"new_var":[42,{"word":"life"},null]}"# ); let general_file = db.file_mut("game", "general").unwrap(); general_file.insert("/76561198025127722/achievements/5", json!("kf:bugged"))?; assert_eq!( general_file .get("/76561198025127722/achievements") .unwrap() .to_string(), r#"["kf:LabCleaner","kf:ChickenFarmer","scrn:playedscrn",null,null,"kf:bugged"]"# ); Ok(()) } #[test] fn db_set_failure() { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let file = db.file_mut("administration", "registered").unwrap(); file.insert("/76561198025127722/dir/var", json!(null)) .expect_err("Testing panic at trying to set a value in non-existing object/array."); file.insert("/76561198044316328/groups/d", json!(null)) .expect_err("Testing panic at trying to set a value at non-numeric index in an array."); file.insert("/76561198044316328/groups/-1", json!(null)) .expect_err("Testing panic at trying to set a value at negative index in an array."); } #[test] fn db_remove_value() { let mut db = Database::load(path::Path::new(TEST_DB_PATH)).expect(NO_DB_MESSAGE); let file = db.file_mut("administration", "registered").unwrap(); // Removing non-existent value assert_eq!(file.remove("/76561198025127722/something"), None); // Remove simple value assert_eq!( file.remove("/76561198025127722/password_hash").unwrap(), json!("fce798e0804dfb217f929bdba26745024f37f6b6ba7406f3775176e20dd5089d") ); assert!(!file.contains("/76561198025127722/password_hash")); // Remove complex value (array) assert_eq!( file.remove("/76561198044316328/groups").unwrap(), json!(["admin"]) ); assert!(!file.contains("/76561198044316328/groups/0")); assert!(!file.contains("/76561198044316328/groups")); // Remove array elements assert_eq!( file.remove("/76561198025127722/allowed_ips/0").unwrap(), json!("127.0.0.1") ); assert!(file.contains("/76561198025127722/allowed_ips/0")); assert!(!file.contains("/76561198025127722/allowed_ips/1")); assert_eq!( file.remove("/76561198025127722/allowed_ips/0").unwrap(), json!("192.168.0.100") ); assert!(file.contains("/76561198025127722/allowed_ips")); assert!(!file.contains("/76561198025127722/allowed_ips/0")); } #[test] fn db_save() { let (path, _cleanup) = prepare_db_copy("db_save", false); // Change something up and save let mut db = Database::load(path::Path::new(&path)).expect(NO_DB_MESSAGE); db.remove_group("administration") .expect(r#"Should be able to remove "administration" group"#); db.save() .expect("Should be able to save copy of the database."); // Reload and check changes let db = Database::load(path::Path::new(&path)).expect(NO_DB_MESSAGE); assert_eq!(db.group_names().len(), 1); assert_eq!(db.group_names().get(0), Some(&"game".to_owned())); assert_eq!(db.file_names_in("game").len(), 2); assert!(db.contains_file("game", "general")); assert!(db.contains_file("game", "perks")); } #[test] fn db_change_path() { let (path, _cleanup) = prepare_db_copy("db_change_path", true); // Change something up and move let mut db = Database::load(path::Path::new(&path)).expect(NO_DB_MESSAGE); db.remove_group("administration") .expect(r#"Should be able to remove "administration" group"#); db.file_mut("game", "perks") .unwrap() .insert("", json!({"var":7})) .expect("Should be able to insert into root."); db.change_path(path::Path::new(TEST_DB_MOVED_PATH)) .expect("Should be able to change database's path."); assert!(!path::Path::new(&path).exists()); assert!(path::Path::new(TEST_DB_MOVED_PATH).exists()); // Reload and check the changes let db = Database::load(path::Path::new(TEST_DB_MOVED_PATH)).expect(NO_DB_MESSAGE); assert_eq!(db.group_names().len(), 1); assert_eq!(db.group_names().get(0), Some(&"game".to_owned())); assert_eq!(db.file_names_in("game").len(), 2); assert!(db.contains_file("game", "general")); assert!(db.contains_file("game", "perks")); assert_eq!( db.file("game", "perks").unwrap().root().to_string(), r#"{"var":7}"#.to_owned() ); } #[test] fn db_erase() { let (path, _cleanup) = prepare_db_copy("db_erase", false); let db = Database::load(path::Path::new(&path)).expect(NO_DB_MESSAGE); db.erase().expect("Should be able to erase data."); assert!(!path::Path::new(&path).exists()); }