#![feature(custom_test_frameworks)] #![feature(lazy_cell)] #![allow(clippy::borrowed_box)] #![allow(clippy::arc_with_non_send_sync)] use std::sync::{Arc, LazyLock}; use pkmn_lib::dynamic_data::{ Battle, BattleParty, DamageSource, DynamicLibrary, ExecutingMove, MoveChoice, PassChoice, PokemonBuilder, PokemonParty, ScriptCategory, ScriptContainer, ScriptOwnerData, TurnChoice, VolatileScriptsOwner, }; use crate::common::library_loader; pub mod common; pub mod datatests; static LIBRARY: LazyLock> = LazyLock::new(|| library_loader::load_library().library); fn get_library() -> Arc { LIBRARY.clone() } #[test] fn validate_library_load() { let start_time = chrono::Utc::now(); let result = library_loader::load_library(); let end_time = chrono::Utc::now(); println!( "Built library in {} ms\ \n\t- Types load time: {} ms\ \n\t- Natures load time: {} ms\ \n\t- Items load time: {} ms\ \n\t- Growth Rate load time: {} ms\ \n\t- Abilities load time: {} ms\ \n\t- Moves load time: {} ms\ \n\t- Species load time: {} ms\ \n\t- Script load time: {} ms\ ", (end_time - start_time).num_milliseconds(), result.types_load_time.num_milliseconds(), result.natures_load_time.num_milliseconds(), result.items_load_time.num_milliseconds(), result.growth_rate_load_time.num_milliseconds(), result.abilities_load_time.num_milliseconds(), result.moves_load_time.num_milliseconds(), result.species_load_time.num_milliseconds(), result.wasm_load_time.num_milliseconds(), ); } #[test] fn rune_test() { let result = library_loader::load_library(); let library = result.library; let p1 = PokemonBuilder::new(library.clone(), "charizard".into(), 100) .build() .unwrap(); let script = library .load_script( ScriptOwnerData::Pokemon(p1.weak()), ScriptCategory::Move, &"TestMove".into(), ) .unwrap() .unwrap(); assert_eq!(script.name().unwrap().str(), "TestMove"); let p1 = PokemonBuilder::new(library.clone(), "charizard".into(), 100) .build() .unwrap(); let turn_choice = Arc::new(TurnChoice::Pass(PassChoice::new(p1))); let mut speed = 0; script.change_speed(&turn_choice, &mut speed).unwrap(); assert_eq!(speed, 100); } #[test] fn load_non_existing_wasm_script() { let start_time = chrono::Utc::now(); let result = library_loader::load_library(); let end_time = chrono::Utc::now(); println!( "Built library in {} ms\ \n\t- Types load time: {} ms\ \n\t- Natures load time: {} ms\ \n\t- Items load time: {} ms\ \n\t- Growth Rate load time: {} ms\ \n\t- Abilities load time: {} ms\ \n\t- Moves load time: {} ms\ \n\t- Species load time: {} ms\ \n\t- Script load time: {} ms\ ", (end_time - start_time).num_milliseconds(), result.types_load_time.num_milliseconds(), result.natures_load_time.num_milliseconds(), result.items_load_time.num_milliseconds(), result.growth_rate_load_time.num_milliseconds(), result.abilities_load_time.num_milliseconds(), result.moves_load_time.num_milliseconds(), result.species_load_time.num_milliseconds(), result.wasm_load_time.num_milliseconds(), ); let script = result .library .load_script(ScriptOwnerData::None, ScriptCategory::Move, &"_____non_existing".into()) .unwrap(); assert!(script.is_none()); } /// Assurance has the interesting properties that it creates a special data script internally, and /// deletes that data script through the get_owner functionality. #[test] fn validate_assurance() { let lib = get_library(); let p1 = PokemonBuilder::new(lib.clone(), "charizard".into(), 100) .learn_move("assurance".into()) .build() .unwrap(); let p2 = PokemonBuilder::new(lib.clone(), "venusaur".into(), 100) .build() .unwrap(); let party1 = Arc::new( BattleParty::new( Arc::new(PokemonParty::new_from_vec(vec![Some(p1.clone())])), vec![(0, 0)], ) .unwrap(), ); let party2 = Arc::new( BattleParty::new( Arc::new(PokemonParty::new_from_vec(vec![Some(p2.clone())])), vec![(1, 0)], ) .unwrap(), ); let battle = Battle::new(lib.clone(), vec![party1, party2], false, 2, 1, None); battle.sides()[0].set_pokemon(0, Some(p1.clone())).unwrap(); battle.sides()[1].set_pokemon(0, Some(p2.clone())).unwrap(); let script = lib .load_script( ScriptOwnerData::None, ScriptCategory::Move, &"double_power_if_target_damaged_in_turn".into(), ) .unwrap() .unwrap(); let mv = p1.learned_moves().read()[0].as_ref().unwrap().clone(); let choice = Arc::new(TurnChoice::Move(MoveChoice::new(p1.clone(), mv.clone(), 1, 0))); script.on_before_turn(&choice).unwrap(); assert!(battle.sides()[1].has_volatile_script(&"double_power_if_target_damaged_in_turn_data".into())); let executing_move = Arc::new(ExecutingMove::new( vec![], 1, p1, mv.clone(), mv.move_data().clone(), ScriptContainer::default(), )); let mut v = 20_u8; script.change_base_power(&executing_move, &p2, 0, &mut v).unwrap(); assert_eq!(v, 20_u8); let s = battle.sides()[1].get_volatile_script(&"double_power_if_target_damaged_in_turn_data".into()); let binding = s.as_ref().unwrap().get().unwrap().read(); let data_script = binding.as_ref().unwrap(); data_script.on_damage(&p2, DamageSource::Misc, 100, 50).unwrap(); let mut v = 20_u8; script.change_base_power(&executing_move, &p2, 0, &mut v).unwrap(); assert_eq!(v, 40_u8); data_script.on_end_turn().unwrap(); assert!(!battle.sides()[1].has_volatile_script(&"double_power_if_target_damaged_in_turn_data".into())); }