diff options
Diffstat (limited to 'tests/strcursor.rs')
-rw-r--r-- | tests/strcursor.rs | 592 |
1 files changed, 592 insertions, 0 deletions
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::<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); +} |