// 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::().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); }