use crate::{error, qmap};
use qmap::parser::parse;
use qmap::EntityKind;
use std::ffi::CString;
use std::io;
struct ErroringReader {}
impl ErroringReader {
fn new() -> Self {
Self {}
}
}
impl io::Read for ErroringReader {
fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
Err(io::Error::new(io::ErrorKind::Other, "Generic test error"))
}
}
fn panic_expected_point() {
panic!("Expected point entity, found brush entity");
}
fn panic_unexpected_variant<T: std::fmt::Display>(err: T) {
panic!("Unexpected error variant for {}", err);
}
#[test]
fn parse_empty_map() {
let map = parse(&mut &b""[..]).unwrap();
assert_eq!(map.entities.len(), 0);
}
#[test]
fn parse_empty_point_entity() {
let map = parse(&mut &b"{ }"[..]).unwrap();
assert_eq!(map.entities.len(), 1);
let ent = &map.entities[0];
assert_eq!(ent.edict.len(), 0);
if ent.kind() != EntityKind::Point {
panic_expected_point();
}
}
#[test]
fn parse_point_entity_with_key_value() {
let map = parse(
&mut &br#"
{
"classname" "light"
}
"#[..],
)
.unwrap();
assert_eq!(map.entities.len(), 1);
let ent = &map.entities[0];
let edict = &ent.edict;
assert_eq!(edict.len(), 1);
assert_eq!(
edict.iter().next().unwrap(),
&(
CString::new("classname").unwrap(),
CString::new("light").unwrap()
)
);
}
#[test]
fn parse_standard_brush_entity() {
let map = parse(
&mut &b"
{
{
( 1 2 3 ) ( 4 5 6 ) ( 7 8 9 ) TEXTURE1 0 0 0 1 1
}
}
"[..],
)
.unwrap();
assert_eq!(map.entities.len(), 1);
let ent = &map.entities[0];
assert_eq!(ent.brushes.len(), 1);
let brush = &ent.brushes[0];
assert_eq!(brush.len(), 1);
let surface = &brush[0];
assert_eq!(
surface.half_space,
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]
);
assert_eq!(surface.texture, CString::new("TEXTURE1").unwrap());
assert_eq!(surface.alignment.offset, [0.0, 0.0]);
assert_eq!(surface.alignment.rotation, 0.0);
assert_eq!(surface.alignment.scale, [1.0, 1.0]);
assert!(surface.q2ext.is_zeroed());
}
#[test]
fn parse_valve_brush_entity() {
let map = parse(
&mut &b"
{
{
( 1 2 3 ) ( 4 5 6 ) ( 7 8 9 ) TEX2 [ 1 0 0 0 ] [ 0 1 0 0 ] 0 1 1
}
}
"[..],
)
.unwrap();
assert_eq!(map.entities.len(), 1);
let ent = &map.entities[0];
assert_eq!(ent.edict.len(), 0);
assert_eq!(ent.brushes.len(), 1);
let brush = &ent.brushes[0];
assert_eq!(brush.len(), 1);
let surface = &brush[0];
assert_eq!(
surface.half_space,
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]
);
assert_eq!(surface.texture, CString::new("TEX2").unwrap());
assert_eq!(surface.alignment.offset, [0.0, 0.0]);
assert_eq!(surface.alignment.rotation, 0.0);
assert_eq!(surface.alignment.scale, [1.0, 1.0]);
assert_eq!(
surface.alignment.axes,
Some([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]),
);
assert!(surface.q2ext.is_zeroed());
}
#[test]
fn parse_weird_numbers() {
let map = parse(
&mut &b"
{ {
( 9E99 1E-9 -1.37e9 ) ( 12 -0 -100.7 ) ( 0e8 0E8 1.2e34 )
T 0.25 0.25 45 2.0001 2.002
} }
"[..],
)
.unwrap();
let brushes = &map.entities[0].brushes;
let brush = &brushes[0];
let surface = &brush[0];
assert_eq!(
surface.half_space,
[
[9E99, 1E-9, -1.37e9],
[12.0, 0.0, -100.7],
[0.0, 0.0, 1.2e34]
]
);
assert_eq!(surface.alignment.offset, [0.25, 0.25]);
assert_eq!(surface.alignment.rotation, 45.0);
assert_eq!(surface.alignment.scale, [2.0001, 2.002]);
}
#[test]
fn parse_weird_textures() {
let map = parse(
&mut &br#"
{ {
( 1 2 3 ) ( 4 5 6 ) ( 7 8 9 )
{FENCE
0 0 0 1 1
( 9 8 7 ) ( 6 5 4 ) ( 9 8 7 )
"spaced out"
0 0 0 1 1
( 11 12 13 ) ( 23 24 25 ) ( 35 36 37 )
silly"example
0 0 0 1 1
} }
"#[..],
)
.unwrap();
let brushes = &map.entities[0].brushes;
let surface1 = &(brushes[0])[0];
let surface2 = &(brushes[0])[1];
let surface3 = &(brushes[0])[2];
assert_eq!(surface1.texture, CString::new("{FENCE").unwrap());
assert_eq!(surface2.texture, CString::new("spaced out").unwrap());
assert_eq!(surface3.texture, CString::new(r#"silly"example"#).unwrap());
}
#[test]
fn parse_q2_surface() {
let map = parse(
&mut &br#"
{ {
( 1 2 3 ) ( 4 5 6 ) ( 7 8 9 )
T
0 0 0 1 1 -97 9 255
( 2 5 7 ) ( 8 9 7 ) ( 4 3 6 )
T
0 0 0 1 1 0 -9 -13.7
} }
"#[..],
)
.unwrap();
let std_ext = &map.entities[0].brushes[0][0].q2ext;
let valve_ext = &map.entities[0].brushes[0][1].q2ext;
assert!(!std_ext.is_zeroed());
assert_eq!(std_ext.content_flags, -97);
assert_eq!(std_ext.surface_flags, 9);
assert_eq!(std_ext.surface_value, 255.0);
assert!(!valve_ext.is_zeroed());
assert_eq!(valve_ext.content_flags, 0);
assert_eq!(valve_ext.surface_flags, -9);
assert_eq!(valve_ext.surface_value, -13.7);
}
#[test]
fn parse_token_error() {
let err = parse(&mut &b"\""[..]).err().unwrap();
if let error::TextParse::Lexer(line_err) = err {
assert_eq!(u64::from(line_err.line_number.unwrap()), 1u64);
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_io_error() {
let mut reader = ErroringReader::new();
let err = parse(&mut reader).err().unwrap();
if let error::TextParse::Io(_) = err {
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_eof_error() {
let err = parse(&mut &b"{"[..]).err().unwrap();
if let error::TextParse::Parser(line_err) = err {
assert_eq!(line_err.line_number, None);
assert!(line_err.message.contains("end-of-file"));
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_closing_brace_error() {
let err = parse(&mut &b"}"[..]).err().unwrap();
if let error::TextParse::Parser(line_err) = err {
assert_eq!(u64::from(line_err.line_number.unwrap()), 1u64);
assert!(line_err.message.contains('}'));
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_missing_value() {
let err = parse(&mut &b"{\n \"classname\"\n }"[..]).err().unwrap();
if let error::TextParse::Parser(line_err) = err {
assert_eq!(u64::from(line_err.line_number.unwrap()), 3u64);
assert!(line_err.message.contains('}'));
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_bad_texture_name() {
let map_text = br#"
{ {
( 1 2 3 ) ( 2 3 1 ) ( 3 1 2 ) "bad"tex" 0 0 0 1 1
} }
"#;
let err = parse(&mut &map_text[..]).err().unwrap();
if let error::TextParse::Parser(line_err) = err {
assert!(line_err.message.contains("tex\""));
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_unclosed_surface() {
let map_text = br#"
{
"classname" "world"
{
( 1 2 3 ) ( 2 3 1 ) ( 3 1 2 ) tex 0 0 0 1 1
{
"#;
let err = parse(&mut &map_text[..]).err().unwrap();
if let error::TextParse::Parser(ref line_err) = err {
assert!(line_err.message.contains("`}`"));
assert!(line_err.message.contains("`(`"));
} else {
panic_unexpected_variant(err);
}
}
#[test]
fn parse_incomplete_q2_extension() {
let map_text = br#"
{ {
( 1 2 3 ) ( 4 5 6 ) ( 7 8 9 ) t 0 0 0 1 1 -2
} }
"#;
let err = parse(&mut &map_text[..]).err().unwrap();
if let error::TextParse::Parser(ref line_err) = err {
assert!(line_err.message.contains("integer"));
assert!(line_err.message.contains("`}`"));
} else {
panic_unexpected_variant(err);
}
}