diff --git a/src/consts/division.rs b/src/consts/division.rs index 629f4c4..98d5fb1 100644 --- a/src/consts/division.rs +++ b/src/consts/division.rs @@ -1,7 +1,6 @@ use std::cmp::Ordering; use strum_macros::{ EnumString, Display, AsRefStr }; -use serde_repr::{ Serialize_repr, Deserialize_repr }; use num_enum::{ IntoPrimitive, TryFromPrimitive }; /// LoL and TFT rank divisions, I, II, III, IV, and (deprecated) V. @@ -12,7 +11,6 @@ use num_enum::{ IntoPrimitive, TryFromPrimitive }; #[derive(Debug, Copy, Clone)] #[derive(Eq, PartialEq, Hash)] #[derive(EnumString, Display, AsRefStr)] -#[derive(Serialize_repr, Deserialize_repr)] #[derive(IntoPrimitive, TryFromPrimitive)] #[repr(u8)] pub enum Division { @@ -24,6 +22,8 @@ pub enum Division { V = 5, } +serde_string!(Division); + impl Ord for Division { fn cmp(&self, other: &Self) -> Ordering { u8::from(*self).cmp(&u8::from(*other)).reverse() diff --git a/src/endpoints/dto.rs b/src/endpoints/dto.rs index 61e74f6..a0e39fb 100644 --- a/src/endpoints/dto.rs +++ b/src/endpoints/dto.rs @@ -1,9 +1,9 @@ -/////////////////////////////////////////////// -// // -// ! // -// This file is automatically generated! // -// Do not directly edit! // -// // +/////////////////////////////////////////////// +// // +// ! // +// This file is automatically generated! // +// Do not directly edit! // +// // /////////////////////////////////////////////// // http://www.mingweisamuel.com/riotapi-schema/tool/ @@ -78,7 +78,7 @@ pub mod league_exp_v4 { #[serde(rename = "hotStreak")] pub hot_streak: bool, #[serde(rename = "miniSeries")] - pub mini_series: MiniSeries, + pub mini_series: Option, /// Winning team on Summoners Rift. First placement in Teamfight Tactics. #[serde(rename = "wins")] pub wins: i32, @@ -145,7 +145,7 @@ pub mod league_v4 { #[serde(rename = "hotStreak")] pub hot_streak: bool, #[serde(rename = "miniSeries")] - pub mini_series: MiniSeries, + pub mini_series: Option, /// Winning team on Summoners Rift. First placement in Teamfight Tactics. #[serde(rename = "wins")] pub wins: i32, @@ -190,7 +190,7 @@ pub mod league_v4 { #[serde(rename = "hotStreak")] pub hot_streak: bool, #[serde(rename = "miniSeries")] - pub mini_series: MiniSeries, + pub mini_series: Option, /// Winning team on Summoners Rift. First placement in Teamfight Tactics. #[serde(rename = "wins")] pub wins: i32, @@ -452,7 +452,7 @@ pub mod match_v4 { pub participant_id: i32, /// List of legacy Rune information. Not included for matches played with Runes Reforged. #[serde(rename = "runes")] - pub runes: std::vec::Vec, + pub runes: Option>, /// Participant timeline data. #[serde(rename = "timeline")] pub timeline: ParticipantTimeline, @@ -464,11 +464,11 @@ pub mod match_v4 { pub spell2_id: i32, /// List of legacy Mastery information. Not included for matches played with Runes Reforged. #[serde(rename = "masteries")] - pub masteries: std::vec::Vec, + pub masteries: Option>, /// Highest ranked tier achieved for the previous season in a specific subset of queueIds, if any, otherwise null. Used to display border in game loading screen. Please refer to the Ranked Info documentation.
/// (Legal values: CHALLENGER, MASTER, DIAMOND, PLATINUM, GOLD, SILVER, BRONZE, UNRANKED) #[serde(rename = "highestAchievedSeasonTier")] - pub highest_achieved_season_tier: crate::consts::Tier, + pub highest_achieved_season_tier: Option, /// First Summoner Spell id. #[serde(rename = "spell1Id")] pub spell1_id: i32, @@ -506,7 +506,7 @@ pub mod match_v4 { #[serde(rename = "perk3Var3")] pub perk3_var3: i32, #[serde(rename = "nodeNeutralizeAssist")] - pub node_neutralize_assist: i32, + pub node_neutralize_assist: Option, /// Post game rune stats. #[serde(rename = "perk3Var2")] pub perk3_var2: i32, @@ -550,7 +550,7 @@ pub mod match_v4 { #[serde(rename = "physicalDamageDealtToChampions")] pub physical_damage_dealt_to_champions: i64, #[serde(rename = "nodeCapture")] - pub node_capture: i32, + pub node_capture: Option, #[serde(rename = "largestMultiKill")] pub largest_multi_kill: i32, /// Post game rune stats. @@ -582,7 +582,7 @@ pub mod match_v4 { #[serde(rename = "quadraKills")] pub quadra_kills: i32, #[serde(rename = "teamObjective")] - pub team_objective: i32, + pub team_objective: Option, #[serde(rename = "magicDamageDealt")] pub magic_damage_dealt: i64, #[serde(rename = "item2")] @@ -625,11 +625,11 @@ pub mod match_v4 { #[serde(rename = "magicalDamageTaken")] pub magical_damage_taken: i64, #[serde(rename = "firstInhibitorKill")] - pub first_inhibitor_kill: bool, + pub first_inhibitor_kill: Option, #[serde(rename = "trueDamageTaken")] pub true_damage_taken: i64, #[serde(rename = "nodeNeutralize")] - pub node_neutralize: i32, + pub node_neutralize: Option, #[serde(rename = "assists")] pub assists: i32, #[serde(rename = "combatPlayerScore")] @@ -685,7 +685,7 @@ pub mod match_v4 { #[serde(rename = "unrealKills")] pub unreal_kills: i32, #[serde(rename = "altarsCaptured")] - pub altars_captured: i32, + pub altars_captured: Option, #[serde(rename = "firstTowerAssist")] pub first_tower_assist: bool, #[serde(rename = "firstTowerKill")] @@ -695,11 +695,11 @@ pub mod match_v4 { #[serde(rename = "doubleKills")] pub double_kills: i32, #[serde(rename = "nodeCaptureAssist")] - pub node_capture_assist: i32, + pub node_capture_assist: Option, #[serde(rename = "inhibitorKills")] pub inhibitor_kills: i32, #[serde(rename = "firstInhibitorAssist")] - pub first_inhibitor_assist: bool, + pub first_inhibitor_assist: Option, /// Post game rune stats. #[serde(rename = "perk0Var1")] pub perk0_var1: i32, @@ -712,7 +712,7 @@ pub mod match_v4 { #[serde(rename = "visionWardsBoughtInGame")] pub vision_wards_bought_in_game: i32, #[serde(rename = "altarsNeutralized")] - pub altars_neutralized: i32, + pub altars_neutralized: Option, #[serde(rename = "pentaKills")] pub penta_kills: i32, #[serde(rename = "totalHeal")] @@ -743,13 +743,13 @@ pub mod match_v4 { pub participant_id: i32, /// Creep score difference versus the calculated lane opponent(s) for a specified period. #[serde(rename = "csDiffPerMinDeltas")] - pub cs_diff_per_min_deltas: std::collections::HashMap, + pub cs_diff_per_min_deltas: Option>, /// Gold for a specified period. #[serde(rename = "goldPerMinDeltas")] pub gold_per_min_deltas: std::collections::HashMap, /// Experience difference versus the calculated lane opponent(s) for a specified period. #[serde(rename = "xpDiffPerMinDeltas")] - pub xp_diff_per_min_deltas: std::collections::HashMap, + pub xp_diff_per_min_deltas: Option>, /// Creeps for a specified period. #[serde(rename = "creepsPerMinDeltas")] pub creeps_per_min_deltas: std::collections::HashMap, @@ -762,7 +762,7 @@ pub mod match_v4 { pub role: String, /// Damage taken difference versus the calculated lane opponent(s) for a specified period. #[serde(rename = "damageTakenDiffPerMinDeltas")] - pub damage_taken_diff_per_min_deltas: std::collections::HashMap, + pub damage_taken_diff_per_min_deltas: Option>, /// Damage taken for a specified period. #[serde(rename = "damageTakenPerMinDeltas")] pub damage_taken_per_min_deltas: std::collections::HashMap, diff --git a/src/req/token_bucket.test.rs b/src/req/token_bucket.test.rs index fa0009b..ad5c968 100644 --- a/src/req/token_bucket.test.rs +++ b/src/req/token_bucket.test.rs @@ -33,11 +33,11 @@ mod token_bucket { Instant::set_time(50_000); assert!(bucket.get_tokens(100), "All tokens should be immediately available."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(1001); // Extra buffer for Duration(0). assert!(bucket.get_tokens(100), "All tokens should be available after a bucket duration."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); } #[test] @@ -46,22 +46,22 @@ mod token_bucket { Instant::set_time(50_000); assert!(bucket.get_tokens(95), "95 tokens should be immediately available."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(475); // Total 951. - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(476); // Extra buffer for Duration(0). assert!(bucket.get_tokens(5), "Last 5 tokens should be available."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(51); assert!(bucket.get_tokens(95), "95 tokens should be available."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(951); - assert!(bucket.get_tokens(5)); - assert!(None != bucket.get_delay()); + assert!(bucket.get_tokens(5), "Last 5 tokens should be available."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); } #[test] @@ -70,19 +70,19 @@ mod token_bucket { Instant::set_time(50_000); assert!(bucket.get_tokens(50), "Half the tokens should be immediately available."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(501); // Extra buffer for Duration(0). assert!(bucket.get_tokens(50), "Half the tokens should be available after a half bucket duration."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(501); assert!(bucket.get_tokens(50), "Half the tokens should be available after a full bucket duration."); - assert!(None != bucket.get_delay(), "Bucket should have delay."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(501); assert!(bucket.get_tokens(50)); - assert!(None != bucket.get_delay()); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); } #[test] @@ -94,11 +94,12 @@ mod token_bucket { for _ in 0..20_000 { Instant::advance_time(501); assert!(bucket.get_tokens(50), "Should have not violated limit."); - assert!(None != bucket.get_delay(), "Should be blocked."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); Instant::advance_time(501); assert!(bucket.get_tokens(50), "Should have not violated limit."); - assert!(None != bucket.get_delay(), "Should be blocked."); + assert_ne!(None, bucket.get_delay(), "Bucket should have delay."); } + assert!(bucket.timestamps.lock().len() < 110, "Check memory leak."); } } } diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..8289ac8 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,9 @@ +Tests are divided up by region. This is because tests cannot share state, and therefore +cannot share the rate limiting done within a `RiotApi` instance. However, rate limiting +is separate for each region, so it is safe to send requests to different regions from +different instances. + +The tests within an individual file do share their `RiotApi` instance thanks to custom +test runners and some macros I hacked together which are located in `async_tests.rs`. +They are set up in a way to look like normal test output for fun and probably to +confuse people. diff --git a/tests/async_tests.rs b/tests/async_tests.rs index 50b1568..901d220 100644 --- a/tests/async_tests.rs +++ b/tests/async_tests.rs @@ -69,4 +69,7 @@ macro_rules! rassert { #[macro_export] macro_rules! rassert_eq { ( $a:expr, $b:expr ) => { rassert!($a == $b) }; + ( $a:expr, $b:expr, $format:expr $(, $arg:expr)* ) => { + rassert!($a == $b, $format, $( $arg )* ) + }; } diff --git a/tests/ids.rs b/tests/ids.rs new file mode 100644 index 0000000..94f262a --- /dev/null +++ b/tests/ids.rs @@ -0,0 +1,5 @@ +pub const SUMMONER_ID_LUGNUTSK: &'static str = "SBM8Ubipo4ge2yj7bhEzL7yvV0C9Oc1XA2l6v5okGMA_nCw"; +pub const SUMMONER_ID_MA5TERY: &'static str = "IbC4uyFEEW3ZkZw6FZF4bViw3P1EynclAcI6-p-vCpI99Ec"; +pub const SUMMONER_ID_C9SNEAKY: &'static str = "ghHSdADqgxKwcRl_vWndx6wKiyZx0xKQv-LOhOcU5LU"; +pub const ACCOUNT_ID_C9SNEAKY: &'static str = "ML_CcLT94UUHp1iDvXOXCidfmzzPrk_Jbub1f_INhw"; +pub const ACCOUNT_ID_LUGNUTSK: &'static str = "iheZF2uJ50S84Hfq6Ob8GNlJAUmBmac-EsEEWBJjD01q1jQ"; diff --git a/tests/tests_euw.rs b/tests/tests_euw.rs new file mode 100644 index 0000000..0cfffae --- /dev/null +++ b/tests/tests_euw.rs @@ -0,0 +1,38 @@ +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] + +mod async_tests; +mod ids; + +use colored::*; +use lazy_static::lazy_static; +use tokio::runtime::current_thread::Runtime; + +use riven::RiotApi; +use riven::consts::*; + + +lazy_static! { + static ref RIOT_API: RiotApi = { + let api_key = std::fs::read_to_string("apikey.txt").unwrap(); + RiotApi::with_key(api_key.trim()) + }; +} + +async_tests!{ + my_runner { + // Champion Mastery tests. + championmastery_getscore_ma5tery: async { + let p = RIOT_API.champion_mastery_v4().get_champion_mastery_score(Region::EUW, ids::SUMMONER_ID_MA5TERY); + let s = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get ma5tery".to_owned())?; + rassert!(969 <= s && s <= 1000, "Unexpected ma5tery score: {}.", s); + Ok(()) + }, + championmastery_getall_ma5tery: async { + let p = RIOT_API.champion_mastery_v4().get_all_champion_masteries(Region::EUW, ids::SUMMONER_ID_MA5TERY); + let s = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get ma5tery".to_owned())?; + rassert!(s.len() >= 142, "Expected masteries: {}.", s.len()); + Ok(()) + }, + } +} diff --git a/tests/tests_jp.rs b/tests/tests_jp.rs new file mode 100644 index 0000000..4930a19 --- /dev/null +++ b/tests/tests_jp.rs @@ -0,0 +1,32 @@ +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] + +mod async_tests; +mod ids; + +use colored::*; +use lazy_static::lazy_static; +use tokio::runtime::current_thread::Runtime; + +use riven::RiotApi; +use riven::consts::*; + + +lazy_static! { + static ref RIOT_API: RiotApi = { + let api_key = std::fs::read_to_string("apikey.txt").unwrap(); + RiotApi::with_key(api_key.trim()) + }; +} + +async_tests!{ + my_runner { + // Summoner tests. + summoner_get_kanjikana: async { + let p = RIOT_API.summoner_v4().get_by_summoner_name(Region::JP, "私の 頭が かたい"); + let s = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get myheadhard".to_owned())?; + rassert_eq!("私の頭がかたい", s.name); + Ok(()) + }, + } +} diff --git a/tests/tests_na.rs b/tests/tests_na.rs new file mode 100644 index 0000000..7e11d90 --- /dev/null +++ b/tests/tests_na.rs @@ -0,0 +1,81 @@ +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] + +mod async_tests; +mod ids; + +use colored::*; +use lazy_static::lazy_static; +use tokio::runtime::current_thread::Runtime; + +use riven::RiotApi; +use riven::consts::*; +use riven::endpoints::summoner_v4::*; + + +lazy_static! { + static ref RIOT_API: RiotApi = { + let api_key = std::fs::read_to_string("apikey.txt").unwrap(); + RiotApi::with_key(api_key.trim()) + }; +} + +fn validate_lugnutsk(s: Summoner, tag: &str) -> Result<(), String> { + rassert_eq!("LugnutsK", s.name, + "LugnutsK name didn't match {}.", tag); + rassert_eq!(ids::SUMMONER_ID_LUGNUTSK, s.id, + "LugnutsK summonerId didn't match {}.", tag); + rassert_eq!(ids::ACCOUNT_ID_LUGNUTSK, s.account_id, + "LugnutsK accountId didn't match {}.", tag); + Ok(()) +} + +async_tests!{ + my_runner { + // Summoner tests. + summoner_double: async { + let l1p = RIOT_API.summoner_v4().get_by_summoner_name(Region::NA, "lug nuts k"); + let l2p = RIOT_API.summoner_v4().get_by_summoner_name(Region::NA, "lugnuts k"); + let l1 = l1p.await.map_err(|e| e.to_string())?.ok_or("Failed to get l1".to_owned())?; + let l2 = l2p.await.map_err(|e| e.to_string())?.ok_or("Failed to get l2".to_owned())?; + validate_lugnutsk(l1, "l1")?; + validate_lugnutsk(l2, "l2")?; + Ok(()) + }, + champion_getrotation: async { + let p = RIOT_API.champion_v3().get_champion_info(Region::NA); + let d = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get champ info.".to_owned())?; + let new_len = d.free_champion_ids_for_new_players.len(); + let free_len = d.free_champion_ids.len(); + let level = d.max_new_player_level; + rassert!(new_len >= 10, "New len: {}", new_len); + rassert!(free_len >= 15, "Free len: {}", free_len); + rassert_eq!(10, level, "New player level: {}", level); + Ok(()) + }, + match_get: async { + let p = RIOT_API.match_v4().get_match(Region::NA, 3190191338); + let m = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get match.".to_owned())?; + // TODO. + Ok(()) + }, + // match_get_old: async { + // let p = RIOT_API.match_v4().get_match(Region::NA, 2632789562); + // let m = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get match.".to_owned())?; + // // TODO. + // Ok(()) + // }, + match_get_aram: async { + let p = RIOT_API.match_v4().get_match(Region::NA, 2961635718); + let m = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get match.".to_owned())?; + // TODO. + Ok(()) + }, + match_get_urf900: async { + let p = RIOT_API.match_v4().get_match(Region::NA, 2963663381); + let m = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get match.".to_owned())?; + // TODO. + Ok(()) + }, + } +} diff --git a/tests/tests2.rs b/tests/tests_tr.rs similarity index 52% rename from tests/tests2.rs rename to tests/tests_tr.rs index 2084cf8..355c92f 100644 --- a/tests/tests2.rs +++ b/tests/tests_tr.rs @@ -2,27 +2,30 @@ #![test_runner(my_runner)] mod async_tests; +mod ids; use colored::*; use lazy_static::lazy_static; -use riven::RiotApi; use tokio::runtime::current_thread::Runtime; +use riven::RiotApi; +use riven::consts::*; + + lazy_static! { static ref RIOT_API: RiotApi = { - let api_key = std::fs::read_to_string("apikey.txt").unwrap(); // TODO don't use unwrap. + let api_key = std::fs::read_to_string("apikey.txt").unwrap(); RiotApi::with_key(api_key.trim()) }; } async_tests!{ my_runner { - test_1: async { - rassert_eq!("world", "world"); - Ok(()) - }, - test_2: async { - rassert_eq!("hello", "hello"); + league_summoner_bulk_test: async { + let p = RIOT_API.league_v4().get_challenger_league(Region::TR, QueueType::RANKED_SOLO_5x5); + let ll = p.await.map_err(|e| e.to_string())?.ok_or("Failed to get challenger league".to_owned())?; + // println!("{:#?}", ll); + // TODO!!! Ok(()) }, }