From d4724b4734776d32fb86cd3c932e18fc41b68316 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Thu, 11 Nov 2021 20:29:55 -0300 Subject: Start porting Brigadier to Rust --- tests/common/errorfunc.rs | 89 +++++++ tests/common/errorpanic.rs | 114 +++++++++ tests/common/mod.rs | 12 + tests/strcursor.rs | 592 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 807 insertions(+) create mode 100644 tests/common/errorfunc.rs create mode 100644 tests/common/errorpanic.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/strcursor.rs (limited to 'tests') diff --git a/tests/common/errorfunc.rs b/tests/common/errorfunc.rs new file mode 100644 index 0000000..99ba641 --- /dev/null +++ b/tests/common/errorfunc.rs @@ -0,0 +1,89 @@ +// Copyright (c) 2021 Soni L. + +use ::std::marker::PhantomData; + +use ::iosonism::strcursor::ReadError; +use ::iosonism::strcursor::StringReader; + +/// An error callback. +pub trait ErrorFunc<'a, C: StringReader<'a>> { + fn call<'b>(context: &C, ty: ErrorType<'b>); +} + +/// An implementation of various Iosonism errors that calls T. +pub struct ErrorCall(PhantomData); + +#[non_exhaustive] +#[derive(PartialEq, Eq, Debug)] +pub enum ErrorType<'a> { + InvalidInteger(&'a str), + ExpectedInteger, + InvalidFloat(&'a str), + ExpectedFloat, + InvalidBool(&'a str), + ExpectedBool, + ExpectedStartOfQuote, + ExpectedEndOfQuote, + InvalidEscape(&'a str), + ExpectedSymbol(&'a str), +} + +impl ::std::fmt::Display for ErrorCall { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "error!") + } +} + +impl ::std::fmt::Debug for ErrorCall { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "ErrorCall") + } +} + +impl ::std::error::Error for ErrorCall { +} + +impl<'a, C: StringReader<'a>, T> ReadError<'a, C> for ErrorCall +where T: ErrorFunc<'a, C> { + fn invalid_integer(context: &C, from: &str) -> Self { + T::call(context, ErrorType::InvalidInteger(from)); + Self(PhantomData) + } + fn expected_integer(context: &C) -> Self { + T::call(context, ErrorType::ExpectedInteger); + Self(PhantomData) + } + fn invalid_float(context: &C, from: &str) -> Self { + T::call(context, ErrorType::InvalidFloat(from)); + Self(PhantomData) + } + fn expected_float(context: &C) -> Self { + T::call(context, ErrorType::ExpectedFloat); + Self(PhantomData) + } + fn invalid_bool(context: &C, from: &str) -> Self { + T::call(context, ErrorType::InvalidBool(from)); + Self(PhantomData) + } + fn expected_bool(context: &C) -> Self { + T::call(context, ErrorType::ExpectedBool); + Self(PhantomData) + } + fn expected_start_of_quote(context: &C) -> Self { + T::call(context, ErrorType::ExpectedStartOfQuote); + Self(PhantomData) + } + fn expected_end_of_quote(context: &C) -> Self { + T::call(context, ErrorType::ExpectedEndOfQuote); + Self(PhantomData) + } + fn invalid_escape(context: &C, from: &str) -> Self { + T::call(context, ErrorType::InvalidEscape(from)); + Self(PhantomData) + } + fn expected_symbol(context: &C, from: &str) -> Self { + T::call(context, ErrorType::ExpectedSymbol(from)); + Self(PhantomData) + } +} + diff --git a/tests/common/errorpanic.rs b/tests/common/errorpanic.rs new file mode 100644 index 0000000..202c4be --- /dev/null +++ b/tests/common/errorpanic.rs @@ -0,0 +1,114 @@ +// Copyright (c) 2021 Soni L. + +use ::iosonism::strcursor::ReadError; +use ::iosonism::strcursor::StringReader; + +/// An implementation of various Iosonism errors that just panics. +#[derive(Debug)] +pub enum ErrorPanic { + // uninhabitable! +} + +impl ::std::fmt::Display for ErrorPanic { + fn fmt(&self, _: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { + } + } +} + +impl ::std::error::Error for ErrorPanic { +} + +impl<'a, C: StringReader<'a>> ReadError<'a, C> for ErrorPanic { + fn invalid_integer(context: &C, from: &str) -> Self { + if !context.get_remaining().is_empty() { + panic!( + "invalid integer: {} at ...{}", + from, + context.get_remaining(), + ); + } else { + panic!("invalid integer: {}", from); + } + } + fn expected_integer(context: &C) -> Self { + if !context.get_remaining().is_empty() { + panic!("expected integer at ...{}", context.get_remaining()); + } else { + panic!("expected integer"); + } + } + fn invalid_float(context: &C, from: &str) -> Self { + if !context.get_remaining().is_empty() { + panic!( + "invalid float: {} at ...{}", + from, + context.get_remaining(), + ); + } else { + panic!("invalid float: {}", from); + } + } + fn expected_float(context: &C) -> Self { + if !context.get_remaining().is_empty() { + panic!("expected float at ...{}", context.get_remaining()); + } else { + panic!("expected float"); + } + } + fn invalid_bool(context: &C, from: &str) -> Self { + if !context.get_remaining().is_empty() { + panic!( + "invalid bool: {} at ...{}", + from, + context.get_remaining(), + ); + } else { + panic!("invalid bool: {}", from); + } + } + fn expected_bool(context: &C) -> Self { + if !context.get_remaining().is_empty() { + panic!("expected bool at ...{}", context.get_remaining()); + } else { + panic!("expected bool"); + } + } + fn expected_start_of_quote(context: &C) -> Self { + if !context.get_remaining().is_empty() { + panic!("expected start of quote at ...{}", context.get_remaining()); + } else { + panic!("expected start of quote"); + } + } + fn expected_end_of_quote(context: &C) -> Self { + if !context.get_remaining().is_empty() { + panic!("expected end of quote at ...{}", context.get_remaining()); + } else { + panic!("expected end of quote"); + } + } + fn invalid_escape(context: &C, from: &str) -> Self { + if !context.get_remaining().is_empty() { + panic!( + "invalid escape: {} at ...{}", + from, + context.get_remaining(), + ); + } else { + panic!("invalid escape: {}", from); + } + } + fn expected_symbol(context: &C, from: &str) -> Self { + if !context.get_remaining().is_empty() { + panic!( + "expected symbol: {} at ...{}", + from, + context.get_remaining(), + ); + } else { + panic!("expected symbol: {}", from); + } + } +} + diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..6760da1 --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,12 @@ +// Copyright (c) 2021 Soni L. + +// see rationale in tests/*.rs +#![warn(non_snake_case)] + +pub mod errorfunc; +pub mod errorpanic; + +pub use self::errorfunc::ErrorCall; +pub use self::errorfunc::ErrorFunc; +pub use self::errorfunc::ErrorType; +pub use self::errorpanic::ErrorPanic; diff --git a/tests/strcursor.rs b/tests/strcursor.rs new file mode 100644 index 0000000..3ec876e --- /dev/null +++ b/tests/strcursor.rs @@ -0,0 +1,592 @@ +// Copyright (c) 2021 Soni L. +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +// because we wanna use double underscore (__) for test names +#![allow(non_snake_case)] + +use ::std::io::Cursor; + +use ::iosonism::strcursor::StringReader; + +mod common; + +use self::common::ErrorCall; +use self::common::ErrorFunc; +use self::common::ErrorPanic; +use self::common::ErrorType; + +#[test] +fn test_can_read() { + let mut reader = Cursor::new("abc"); + assert_eq!(reader.can_read(), true); + reader.skip(); // 'a' + assert_eq!(reader.can_read(), true); + reader.skip(); // 'b' + assert_eq!(reader.can_read(), true); + reader.skip(); // 'c' + assert_eq!(reader.can_read(), false); +} + +#[test] +fn test_get_remaining_len() { + let mut reader = Cursor::new("abc"); + assert_eq!(reader.get_remaining().len(), 3); + reader.set_position(1); + assert_eq!(reader.get_remaining().len(), 2); + reader.set_position(2); + assert_eq!(reader.get_remaining().len(), 1); + reader.set_position(3); + assert_eq!(reader.get_remaining().len(), 0); +} + +#[test] +fn test_can_read_n() { + let reader = Cursor::new("abc"); + assert_eq!(reader.can_read_n(1), true); + assert_eq!(reader.can_read_n(2), true); + assert_eq!(reader.can_read_n(3), true); + assert_eq!(reader.can_read_n(4), false); + assert_eq!(reader.can_read_n(5), false); +} + +#[test] +fn test_peek() { + let mut reader = Cursor::new("abc"); + assert_eq!(reader.peek(), 'a'); + assert_eq!(reader.position(), 0); + reader.set_position(2); + assert_eq!(reader.peek(), 'c'); + assert_eq!(reader.position(), 2); +} + +#[test] +fn test_peek_n() { + let mut reader = Cursor::new("abc"); + assert_eq!(reader.peek_n(0), 'a'); + assert_eq!(reader.peek_n(2), 'c'); + assert_eq!(reader.position(), 0); + reader.set_position(1); + assert_eq!(reader.peek_n(1), 'c'); + assert_eq!(reader.position(), 1); +} + +#[test] +fn test_read_char() { + let mut reader = Cursor::new("abc"); + assert_eq!(reader.read_char(), Some('a')); + assert_eq!(reader.read_char(), Some('b')); + assert_eq!(reader.read_char(), Some('c')); + assert_eq!(reader.position(), 3); +} + +#[test] +fn test_skip() { + let mut reader = Cursor::new("abc"); + reader.skip(); + assert_eq!(reader.position(), 1); +} + +#[test] +fn test_get_remaining() { + let mut reader = Cursor::new("Hello!"); + assert_eq!(reader.get_remaining(), "Hello!"); + reader.set_position(3); + assert_eq!(reader.get_remaining(), "lo!"); + reader.set_position(6); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_get_read() { + let mut reader = Cursor::new("Hello!"); + assert_eq!(reader.get_read(), ""); + reader.set_position(3); + assert_eq!(reader.get_read(), "Hel"); + reader.set_position(6); + assert_eq!(reader.get_read(), "Hello!"); +} + +#[test] +fn test_skip_whitespace__none() { + let mut reader = Cursor::new("Hello!"); + reader.skip_whitespace(); + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_skip_whitespace__mixed() { + let mut reader = Cursor::new(" \t \t\nHello!"); + reader.skip_whitespace(); + assert_eq!(reader.position(), 5); +} + +#[test] +fn test_skip_whitespace__empty() { + let mut reader = Cursor::new(""); + reader.skip_whitespace(); + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_unquoted_str() { + let mut reader = Cursor::new("hello world"); + assert_eq!(reader.read_unquoted_str(), "hello"); + assert_eq!(reader.get_read(), "hello"); + assert_eq!(reader.get_remaining(), " world"); +} + +#[test] +fn test_read_unquoted_str__empty() { + let mut reader = Cursor::new(""); + assert_eq!(reader.read_unquoted_str(), ""); + assert_eq!(reader.get_read(), ""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_unquoted_str__empty_with_remaining() { + let mut reader = Cursor::new(" hello world"); + assert_eq!(reader.read_unquoted_str(), ""); + assert_eq!(reader.get_read(), ""); + assert_eq!(reader.get_remaining(), " hello world"); +} + +#[test] +fn test_read_quoted_string() { + let mut reader = Cursor::new("\"hello world\""); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello world", + ); + assert_eq!(reader.get_read(), "\"hello world\""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__single() { + let mut reader = Cursor::new("'hello world'"); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello world", + ); + assert_eq!(reader.get_read(), "'hello world'"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__double_inside_single() { + let mut reader = Cursor::new("'hello \"world\"'"); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello \"world\"", + ); + assert_eq!(reader.get_read(), "'hello \"world\"'"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__single_inside_double() { + let mut reader = Cursor::new("\"hello 'world'\""); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello 'world'", + ); + assert_eq!(reader.get_read(), "\"hello 'world'\""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__empty() { + let mut reader = Cursor::new(""); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "", + ); + assert_eq!(reader.get_read(), ""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__empty_quoted() { + let mut reader = Cursor::new("\"\""); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "", + ); + assert_eq!(reader.get_read(), "\"\""); + assert_eq!(reader.get_remaining(), ""); +} + + +#[test] +fn test_read_quoted_string__empty_quoted_with_remaining() { + let mut reader = Cursor::new("\"\" hello world"); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "", + ); + assert_eq!(reader.get_read(), "\"\""); + assert_eq!(reader.get_remaining(), " hello world"); +} + +#[test] +fn test_read_quoted_string__with_escaped_quote() { + let mut reader = Cursor::new("\"hello \\\"world\\\"\""); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello \"world\"", + ); + assert_eq!(reader.get_read(), "\"hello \\\"world\\\"\""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__with_escaped_escapes() { + let mut reader = Cursor::new("\"\\\\o/\""); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "\\o/", + ); + assert_eq!(reader.get_read(), "\"\\\\o/\""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_quoted_string__with_remaining() { + let mut reader = Cursor::new("\"hello world\" foo bar"); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello world", + ); + assert_eq!(reader.get_read(), "\"hello world\""); + assert_eq!(reader.get_remaining(), " foo bar"); +} + +#[test] +fn test_read_quoted_string__with_immediate_remaining() { + let mut reader = Cursor::new("\"hello world\"foo bar"); + assert_eq!( + reader.read_quoted_string::().unwrap(), + "hello world", + ); + assert_eq!(reader.get_read(), "\"hello world\""); + assert_eq!(reader.get_remaining(), "foo bar"); +} + +#[test] +fn test_read_quoted_string__no_open() { + let mut reader = Cursor::new("hello world\""); + assert!(reader.read_quoted_string::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedStartOfQuote); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_quoted_string__no_close() { + let mut reader = Cursor::new("\"hello world"); + assert!(reader.read_quoted_string::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedEndOfQuote); + assert_eq!(context.position(), 12); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_quoted_string__invalid_escape() { + let mut reader = Cursor::new("\"hello\\nworld\""); + assert!(reader.read_quoted_string::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::InvalidEscape("n")); + // NOTE: brigadier makes this 7. we make this 8. + // FIXME: maybe do the same as brigadier? + assert_eq!(context.position(), 8); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_quoted_string__invalid_quote_escape() { + let mut reader = Cursor::new("'hello\\\"'world"); + assert!(reader.read_quoted_string::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::InvalidEscape("\"")); + assert_eq!(context.position(), 8); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_string__no_quotes() { + let mut reader = Cursor::new("hello world"); + assert_eq!( + reader.read_string::().unwrap(), + "hello", + ); + assert_eq!(reader.get_read(), "hello"); + assert_eq!(reader.get_remaining(), " world"); +} + +#[test] +fn test_read_string__single_quotes() { + let mut reader = Cursor::new("'hello world'"); + assert_eq!( + reader.read_string::().unwrap(), + "hello world", + ); + assert_eq!(reader.get_read(), "'hello world'"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_string__double_quotes() { + let mut reader = Cursor::new("\"hello world\""); + assert_eq!( + reader.read_string::().unwrap(), + "hello world", + ); + assert_eq!(reader.get_read(), "\"hello world\""); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_integer() { + let mut reader = Cursor::new("1234567890"); + assert_eq!( + reader.read_integer::().unwrap(), + 1234567890, + ); + assert_eq!(reader.get_read(), "1234567890"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_integer__negative() { + let mut reader = Cursor::new("-1234567890"); + assert_eq!( + reader.read_integer::().unwrap(), + -1234567890, + ); + assert_eq!(reader.get_read(), "-1234567890"); + assert_eq!(reader.get_remaining(), ""); +} + + +#[test] +fn test_read_integer__invalid() { + let mut reader = Cursor::new("12.34"); + assert!(reader.read_integer::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::InvalidInteger("12.34")); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_integer__none() { + let mut reader = Cursor::new(""); + assert!(reader.read_integer::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedInteger); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_integer__with_remaining() { + let mut reader = Cursor::new("1234567890 foo bar"); + assert_eq!( + reader.read_integer::().unwrap(), + 1234567890, + ); + assert_eq!(reader.get_read(), "1234567890"); + assert_eq!(reader.get_remaining(), " foo bar"); +} + +#[test] +fn test_read_integer__with_remaining_immediate() { + let mut reader = Cursor::new("1234567890foo bar"); + assert_eq!( + reader.read_integer::().unwrap(), + 1234567890, + ); + assert_eq!(reader.get_read(), "1234567890"); + assert_eq!(reader.get_remaining(), "foo bar"); +} + +#[test] +fn test_read_float() { + let mut reader = Cursor::new("123"); + assert_eq!( + reader.read_float::().unwrap(), + 123.0, + ); + assert_eq!(reader.get_read(), "123"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_float__with_decimal() { + let mut reader = Cursor::new("12.34"); + assert_eq!( + reader.read_float::().unwrap(), + 12.34, + ); + assert_eq!(reader.get_read(), "12.34"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_float__negative() { + let mut reader = Cursor::new("-123"); + assert_eq!( + reader.read_float::().unwrap(), + -123.0, + ); + assert_eq!(reader.get_read(), "-123"); + assert_eq!(reader.get_remaining(), ""); +} + +#[test] +fn test_read_float__invalid() { + let mut reader = Cursor::new("12.34.56"); + assert!(reader.read_float::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::InvalidFloat("12.34.56")); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_float__none() { + let mut reader = Cursor::new(""); + assert!(reader.read_float::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedFloat); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_float__with_remaining() { + let mut reader = Cursor::new("12.34 foo bar"); + assert_eq!( + reader.read_float::().unwrap(), + 12.34, + ); + assert_eq!(reader.get_read(), "12.34"); + assert_eq!(reader.get_remaining(), " foo bar"); +} + +#[test] +fn test_read_float__with_remaining_immediate() { + let mut reader = Cursor::new("12.34foo bar"); + assert_eq!( + reader.read_float::().unwrap(), + 12.34, + ); + assert_eq!(reader.get_read(), "12.34"); + assert_eq!(reader.get_remaining(), "foo bar"); +} + +#[test] +fn test_expect__correct() { + let mut reader = Cursor::new("abc"); + assert!(reader.expect::('a').is_ok()); + assert_eq!(reader.position(), 1); +} + +#[test] +fn test_expect__incorrect() { + let mut reader = Cursor::new("bcd"); + assert!(reader.expect::>('a').is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedSymbol("a")); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_expect__none() { + let mut reader = Cursor::new(""); + assert!(reader.expect::>('a').is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedSymbol("a")); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_bool__correct() { + let mut reader = Cursor::new("true"); + assert_eq!(reader.read_bool::().unwrap(), true); + assert_eq!(reader.get_read(), "true"); +} + +#[test] +fn test_read_bool__incorrect() { + let mut reader = Cursor::new("tuesday"); + assert!(reader.read_bool::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::InvalidBool("tuesday")); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} + +#[test] +fn test_read_bool__none() { + let mut reader = Cursor::new(""); + assert!(reader.read_bool::>().is_err()); + struct ErrFn; + impl<'a> ErrorFunc<'a, Cursor<&'a str>> for ErrFn { + fn call(context: &Cursor<&'a str>, ty: ErrorType) { + assert_eq!(ty, ErrorType::ExpectedBool); + assert_eq!(context.position(), 0); + } + } + assert_eq!(reader.position(), 0); +} -- cgit 1.4.1