extern crate mozpdb;
use mozpdb as pdb;
use pdb::FallibleIterator;
use std::collections::HashMap;
fn setup<F>(func: F) where F: FnOnce(&pdb::TypeInformation) -> () {
let file = if let Ok(filename) = std::env::var("PDB_FILE") {
std::fs::File::open(filename)
} else {
std::fs::File::open("fixtures/self/foo.pdb")
}.expect("opening file");
let mut pdb = pdb::PDB::open(file).expect("opening pdb");
let type_information = pdb.type_information().expect("type information");
func(&type_information);
}
#[test]
fn iteration() {
setup(|type_information| {
let len = type_information.len();
let mut count: usize = 0;
let mut last_index: pdb::TypeIndex = 4095;
let mut iter = type_information.iter();
while let Some(typ) = iter.next().expect("next type") {
assert_eq!(typ.type_index(), last_index + 1);
last_index = typ.type_index();
count += 1;
}
assert_eq!(len, count);
});
}
#[test]
fn type_finder() {
setup(|type_information| {
let mut type_finder = type_information.new_type_finder();
let mut map: HashMap<pdb::TypeIndex, pdb::Type> = HashMap::new();
assert_eq!(type_finder.max_indexed_type() >> 3, 4096 >> 3);
let mut iter = type_information.iter();
while let Some(typ) = iter.next().expect("next type") {
assert_eq!(type_finder.max_indexed_type() >> 3, typ.type_index() >> 3);
type_finder.update(&iter);
map.insert(typ.type_index(), typ);
}
for (type_index, typ) in map.iter() {
let found = type_finder.find(*type_index).expect("find");
assert_eq!(*typ, found);
}
})
}
#[test]
fn find_classes() {
setup(|type_information| {
let mut type_finder = type_information.new_type_finder();
let mut iter = type_information.iter();
while let Some(typ) = iter.next().expect("next type") {
type_finder.update(&iter);
match typ.parse() {
Ok(pdb::TypeData::Class(pdb::ClassType { name, fields: Some(fields), ..})) => {
println!("class {} (type {}):", name, typ.type_index());
match type_finder.find(fields).expect("find fields").parse() {
Ok(pdb::TypeData::FieldList(list)) => {
for field in list.fields {
println!(" - {:?}", field);
}
if let Some(c) = list.continuation {
println!("TODO: follow to type {}", c);
}
}
Ok(value) => {
println!("expected a field list, got {:?}", value);
assert!(false);
},
Err(e) => {
println!("field parse error: {}", e);
}
}
},
Ok(pdb::TypeData::Enumeration(data)) => {
println!("enum {} (type {}):", data.name, data.fields);
match type_finder.find(data.fields).expect("find fields").parse() {
Ok(pdb::TypeData::FieldList(list)) => {
for field in list.fields {
println!(" - {:?}", field);
}
if let Some(c) = list.continuation {
println!("TODO: follow to type {}", c);
}
}
Ok(value) => {
println!("expected a field list, got {:?}", value);
assert!(false);
},
Err(e) => {
println!("field parse error: {}", e);
}
}
},
Ok(pdb::TypeData::FieldList(_)) => {
}
Ok(_) => {
},
Err(pdb::Error::UnimplementedTypeKind(kind)) => {
println!("unimplemented: 0x{:04x}", kind);
},
Err(e) => {
println!("other parse error on type {} (raw type {:04x}): {}", typ.type_index(), typ.raw_kind(), e);
panic!("dying due to parse error");
}
}
}
})
}