add unit tests for quest dat loading from bad data
This commit is contained in:
parent
8e93f4a3a2
commit
8aa4fa7c2d
|
@ -118,11 +118,13 @@ impl From<&QuestDatTableType> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct QuestDatTableHeader {
|
pub struct QuestDatTableHeader {
|
||||||
pub table_type: QuestDatTableType,
|
pub table_type: QuestDatTableType,
|
||||||
pub area: u32,
|
pub area: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct QuestDatTable {
|
pub struct QuestDatTable {
|
||||||
pub header: QuestDatTableHeader,
|
pub header: QuestDatTableHeader,
|
||||||
pub bytes: Box<[u8]>,
|
pub bytes: Box<[u8]>,
|
||||||
|
@ -160,6 +162,7 @@ impl QuestDatTable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct QuestDat {
|
pub struct QuestDat {
|
||||||
pub tables: Box<[QuestDatTable]>,
|
pub tables: Box<[QuestDatTable]>,
|
||||||
}
|
}
|
||||||
|
@ -215,6 +218,18 @@ impl QuestDat {
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// i wrote this check thinking that an empty .dat file is the most useless thing ever,
|
||||||
|
// but maybe it is possible to exist in a legitimate quest for a totally script-driven
|
||||||
|
// "quest" ... e.g. some sort of "utility quest" that exists just for the purpose of letting
|
||||||
|
// a user interact with the script stored in the .bin? dunno really, but i guess i might
|
||||||
|
// as well disable this check ...
|
||||||
|
//
|
||||||
|
//if tables.len() == 0 {
|
||||||
|
// return Err(QuestDatError::DataFormatError(String::from(
|
||||||
|
// "no tables found, probably not a .dat file?",
|
||||||
|
// )));
|
||||||
|
//}
|
||||||
|
|
||||||
Ok(QuestDat {
|
Ok(QuestDat {
|
||||||
tables: tables.into_boxed_slice(),
|
tables: tables.into_boxed_slice(),
|
||||||
})
|
})
|
||||||
|
@ -292,6 +307,9 @@ impl QuestDat {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
|
use claim::*;
|
||||||
|
use rand::prelude::StdRng;
|
||||||
|
use rand::{Fill, SeedableRng};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -612,4 +630,79 @@ pub mod tests {
|
||||||
validate_quest_118_dat(&dat);
|
validate_quest_118_dat(&dat);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn bad_input_data_results_in_errors() -> Result<(), QuestDatError> {
|
||||||
|
let mut data: &[u8] = &[];
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_uncompressed_bytes(&mut data),
|
||||||
|
Err(QuestDatError::IoError(..))
|
||||||
|
);
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_compressed_bytes(&mut data),
|
||||||
|
Err(QuestDatError::PrsCompressionError(..))
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut data: &[u8] = b"This is definitely not a quest";
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_uncompressed_bytes(&mut data),
|
||||||
|
Err(QuestDatError::DataFormatError(..))
|
||||||
|
);
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_compressed_bytes(&mut data),
|
||||||
|
Err(QuestDatError::PrsCompressionError(..))
|
||||||
|
);
|
||||||
|
|
||||||
|
// dat table header with a table_size issue
|
||||||
|
let mut header: &[u8] = &[
|
||||||
|
0x01, 0x00, 0x00, 0x00, // table_type
|
||||||
|
0xD3, 0x08, 0x00, 0x00, // table_size
|
||||||
|
0x00, 0x00, 0x00, 0x00, // area
|
||||||
|
0xC4, 0x08, 0x00, 0x00, // table_body_size
|
||||||
|
];
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_uncompressed_bytes(&mut header),
|
||||||
|
Err(QuestDatError::DataFormatError(..))
|
||||||
|
);
|
||||||
|
|
||||||
|
// dat table header with a table_type issue
|
||||||
|
let mut header: &[u8] = &[
|
||||||
|
0x11, 0x00, 0x00, 0x00, // table_type
|
||||||
|
0xD4, 0x08, 0x00, 0x00, // table_size
|
||||||
|
0x00, 0x00, 0x00, 0x00, // area
|
||||||
|
0xC4, 0x08, 0x00, 0x00, // table_body_size
|
||||||
|
];
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_uncompressed_bytes(&mut header),
|
||||||
|
Err(QuestDatError::DataFormatError(..))
|
||||||
|
);
|
||||||
|
|
||||||
|
// a valid dat table header ...
|
||||||
|
let header: &[u8] = &[
|
||||||
|
0x01, 0x00, 0x00, 0x00, // table_type
|
||||||
|
0xD4, 0x08, 0x00, 0x00, // table_size
|
||||||
|
0x00, 0x00, 0x00, 0x00, // area
|
||||||
|
0xC4, 0x08, 0x00, 0x00, // table_body_size
|
||||||
|
];
|
||||||
|
// ... with not enough random garbage in the table body area
|
||||||
|
let mut random_garbage = [0u8; 256];
|
||||||
|
let mut rng = StdRng::seed_from_u64(76478964);
|
||||||
|
random_garbage.try_fill(&mut rng).unwrap();
|
||||||
|
let data = [header, &random_garbage].concat();
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_uncompressed_bytes(&mut data.as_slice()),
|
||||||
|
Err(QuestDatError::IoError(..))
|
||||||
|
);
|
||||||
|
|
||||||
|
// totally random data which should be interpreted as an invalid table header
|
||||||
|
let mut data = vec![0u8; 1024];
|
||||||
|
let mut rng = StdRng::seed_from_u64(15785357);
|
||||||
|
data.try_fill(&mut rng).unwrap();
|
||||||
|
assert_matches!(
|
||||||
|
QuestDat::from_uncompressed_bytes(&mut data.as_slice()),
|
||||||
|
Err(QuestDatError::DataFormatError(..))
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue