// Copyright (c) 2021 Soni L.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// Documentation and comments licensed under CC BY-SA 4.0.
// 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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorCall<ErrFn>>().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::<ErrorCall<ErrFn>>().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::<ErrorCall<ErrFn>>().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::<ErrorCall<ErrFn>>().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::<ErrorPanic>().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::<ErrorPanic>().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::<ErrorPanic>().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::<i32, ErrorPanic>().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::<i32, ErrorPanic>().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::<i32, ErrorCall<ErrFn>>().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::<i32, ErrorCall<ErrFn>>().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::<i32, ErrorPanic>().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::<i32, ErrorPanic>().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::<f32, ErrorPanic>().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::<f32, ErrorPanic>().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::<f32, ErrorPanic>().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::<f32, ErrorCall<ErrFn>>().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::<f32, ErrorCall<ErrFn>>().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::<f32, ErrorPanic>().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::<f32, ErrorPanic>().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::<ErrorPanic>('a').is_ok());
assert_eq!(reader.position(), 1);
}
#[test]
fn test_expect__incorrect() {
let mut reader = Cursor::new("bcd");
assert!(reader.expect::<ErrorCall<ErrFn>>('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::<ErrorCall<ErrFn>>('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::<ErrorPanic>().unwrap(), true);
assert_eq!(reader.get_read(), "true");
}
#[test]
fn test_read_bool__incorrect() {
let mut reader = Cursor::new("tuesday");
assert!(reader.read_bool::<ErrorCall<ErrFn>>().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::<ErrorCall<ErrFn>>().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);
}