adding tests, fixing divsiion serialization

DTO changes are temp due to autogen
This commit is contained in:
Mingwei Samuel 2019-10-30 13:24:07 -07:00
parent f1c31a59fa
commit 15faf83241
10 changed files with 220 additions and 48 deletions

View file

@ -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()

View file

@ -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<MiniSeries>,
/// 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<MiniSeries>,
/// 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<MiniSeries>,
/// 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<Rune>,
pub runes: Option<std::vec::Vec<Rune>>,
/// 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<Mastery>,
pub masteries: Option<std::vec::Vec<Mastery>>,
/// 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.<br>
/// (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<crate::consts::Tier>,
/// 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<i32>,
/// 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<i32>,
#[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<i32>,
#[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<bool>,
#[serde(rename = "trueDamageTaken")]
pub true_damage_taken: i64,
#[serde(rename = "nodeNeutralize")]
pub node_neutralize: i32,
pub node_neutralize: Option<i32>,
#[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<i32>,
#[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<i32>,
#[serde(rename = "inhibitorKills")]
pub inhibitor_kills: i32,
#[serde(rename = "firstInhibitorAssist")]
pub first_inhibitor_assist: bool,
pub first_inhibitor_assist: Option<bool>,
/// 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<i32>,
#[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<String, f64>,
pub cs_diff_per_min_deltas: Option<std::collections::HashMap<String, f64>>,
/// Gold for a specified period.
#[serde(rename = "goldPerMinDeltas")]
pub gold_per_min_deltas: std::collections::HashMap<String, f64>,
/// Experience difference versus the calculated lane opponent(s) for a specified period.
#[serde(rename = "xpDiffPerMinDeltas")]
pub xp_diff_per_min_deltas: std::collections::HashMap<String, f64>,
pub xp_diff_per_min_deltas: Option<std::collections::HashMap<String, f64>>,
/// Creeps for a specified period.
#[serde(rename = "creepsPerMinDeltas")]
pub creeps_per_min_deltas: std::collections::HashMap<String, f64>,
@ -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<String, f64>,
pub damage_taken_diff_per_min_deltas: Option<std::collections::HashMap<String, f64>>,
/// Damage taken for a specified period.
#[serde(rename = "damageTakenPerMinDeltas")]
pub damage_taken_per_min_deltas: std::collections::HashMap<String, f64>,

View file

@ -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.");
}
}
}

9
tests/README.md Normal file
View file

@ -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.

View file

@ -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 )* )
};
}

5
tests/ids.rs Normal file
View file

@ -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";

38
tests/tests_euw.rs Normal file
View file

@ -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(())
},
}
}

32
tests/tests_jp.rs Normal file
View file

@ -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(())
},
}
}

81
tests/tests_na.rs Normal file
View file

@ -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(())
},
}
}

View file

@ -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(())
},
}