aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azalea-brigadier/src/builder/argument_builder.rs79
-rw-r--r--azalea-brigadier/src/command_dispatcher.rs415
-rw-r--r--azalea-brigadier/src/lib.rs48
-rw-r--r--azalea-brigadier/src/string_reader.rs616
-rw-r--r--azalea-brigadier/tests/arguments/bool_argument_type_test.rs0
-rw-r--r--azalea-brigadier/tests/arguments/double_argument_type_test.rs0
-rw-r--r--azalea-brigadier/tests/arguments/float_argument_type_test.rs0
-rw-r--r--azalea-brigadier/tests/arguments/integer_argument_type_test.rs0
-rw-r--r--azalea-brigadier/tests/arguments/long_argument_type_test.rs0
-rw-r--r--azalea-brigadier/tests/arguments/string_argument_type_test.rs0
-rw-r--r--azalea-brigadier/tests/builder/argument_builder_test.rs75
-rw-r--r--azalea-brigadier/tests/builder/literal_argument_builder_test.rs0
-rw-r--r--azalea-brigadier/tests/builder/required_argument_builder_test.rs0
-rw-r--r--azalea-brigadier/tests/command_dispatcher_test.rs410
-rw-r--r--azalea-brigadier/tests/command_dispatcher_usages_test.rs1
-rw-r--r--azalea-brigadier/tests/command_suggestions_test.rs1
-rw-r--r--azalea-brigadier/tests/context/command_context_test.rs0
-rw-r--r--azalea-brigadier/tests/context/parsed_argument_test.rs0
-rw-r--r--azalea-brigadier/tests/exceptions/dynamic_command_syntax_exception_type_test.rs0
-rw-r--r--azalea-brigadier/tests/exceptions/simple_command_syntax_exception_type_test.rs0
-rw-r--r--azalea-brigadier/tests/string_reader_test.rs612
-rw-r--r--azalea-brigadier/tests/suggestion/suggestion_test.rs0
-rw-r--r--azalea-brigadier/tests/suggestion/suggestions_builder_test.rs0
-rw-r--r--azalea-brigadier/tests/suggestion/suggestions_test.rs0
-rw-r--r--azalea-brigadier/tests/tree/abstract_command_node_test.rs0
-rw-r--r--azalea-brigadier/tests/tree/argument_command_node_test.rs0
-rw-r--r--azalea-brigadier/tests/tree/literal_command_node_test.rs0
-rw-r--r--azalea-brigadier/tests/tree/root_command_node_test.rs0
28 files changed, 1100 insertions, 1157 deletions
diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs
index 14d41f4e..d26b2a8a 100644
--- a/azalea-brigadier/src/builder/argument_builder.rs
+++ b/azalea-brigadier/src/builder/argument_builder.rs
@@ -135,82 +135,3 @@ impl<S> Debug for ArgumentBuilder<S> {
.finish()
}
}
-
-#[cfg(test)]
-mod tests {
- use std::rc::Rc;
-
- use crate::{
- arguments::integer_argument_type::integer,
- builder::{literal_argument_builder::literal, required_argument_builder::argument},
- };
-
- use super::ArgumentBuilder;
-
- // public class ArgumentBuilderTest {
- // private TestableArgumentBuilder<Object> builder;
-
- // @Before
- // public void setUp() throws Exception {
- // builder = new TestableArgumentBuilder<>();
- // }
-
- // @Test
- // public void testArguments() throws Exception {
- // final RequiredArgumentBuilder<Object, ?> argument = argument("bar", integer());
-
- // builder.then(argument);
-
- // assertThat(builder.getArguments(), hasSize(1));
- // assertThat(builder.getArguments(), hasItem((CommandNode<Object>) argument.build()));
- // }
-
- #[test]
- fn test_arguments() {
- let mut builder: ArgumentBuilder<()> = literal("foo");
-
- let argument: ArgumentBuilder<()> = argument("bar", integer());
- builder.then(argument.clone());
- assert_eq!(builder.arguments.children.len(), 1);
- let built_argument = Rc::new(argument.build());
- assert!(builder
- .arguments
- .children
- .values()
- .any(|e| *e.borrow() == *built_argument));
- }
-
- // @Test
- // public void testRedirect() throws Exception {
- // final CommandNode<Object> target = mock(CommandNode.class);
- // builder.redirect(target);
- // assertThat(builder.getRedirect(), is(target));
- // }
-
- // @Test(expected = IllegalStateException.class)
- // public void testRedirect_withChild() throws Exception {
- // final CommandNode<Object> target = mock(CommandNode.class);
- // builder.then(literal("foo"));
- // builder.redirect(target);
- // }
-
- // @Test(expected = IllegalStateException.class)
- // public void testThen_withRedirect() throws Exception {
- // final CommandNode<Object> target = mock(CommandNode.class);
- // builder.redirect(target);
- // builder.then(literal("foo"));
- // }
-
- // private static class TestableArgumentBuilder<S> extends ArgumentBuilder<S, TestableArgumentBuilder<S>> {
- // @Override
- // protected TestableArgumentBuilder<S> getThis() {
- // return this;
- // }
-
- // @Override
- // public CommandNode<S> build() {
- // return null;
- // }
- // }
- // }
-}
diff --git a/azalea-brigadier/src/command_dispatcher.rs b/azalea-brigadier/src/command_dispatcher.rs
index fc3f3d50..eab42dd8 100644
--- a/azalea-brigadier/src/command_dispatcher.rs
+++ b/azalea-brigadier/src/command_dispatcher.rs
@@ -10,7 +10,7 @@ use std::{cell::RefCell, cmp::Ordering, collections::HashMap, marker::PhantomDat
#[derive(Default)]
pub struct CommandDispatcher<S> {
- root: Rc<RefCell<CommandNode<S>>>,
+ pub root: Rc<RefCell<CommandNode<S>>>,
_marker: PhantomData<S>,
}
@@ -296,416 +296,3 @@ impl<S> Clone for CommandDispatcher<S> {
}
}
}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::{
- arguments::integer_argument_type::integer,
- builder::{literal_argument_builder::literal, required_argument_builder::argument},
- };
-
- #[derive(Debug, PartialEq)]
- struct CommandSource {}
-
- fn input_with_offset(input: &str, offset: usize) -> StringReader {
- let mut result: StringReader = input.into();
- result.cursor = offset;
- result
- }
-
- #[test]
- fn create_and_execute_command() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").executes(|_| 42));
-
- assert_eq!(
- subject
- .execute("foo".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 42
- );
- }
-
- #[test]
- fn create_and_execute_offset_command() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").executes(|_| 42));
-
- assert_eq!(
- subject
- .execute(input_with_offset("/foo", 1), Rc::new(CommandSource {}))
- .unwrap(),
- 42
- );
- }
-
- #[test]
- fn create_and_merge_commands() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("base").then(literal("foo").executes(|_| 42)));
- subject.register(literal("base").then(literal("bar").executes(|_| 42)));
-
- assert_eq!(
- subject
- .execute("base foo".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 42
- );
- assert_eq!(
- subject
- .execute("base bar".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 42
- );
- }
-
- #[test]
- fn execute_unknown_command() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("bar"));
- subject.register(literal("baz"));
-
- let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
-
- let err = execute_result.err().unwrap();
- match err.type_ {
- BuiltInExceptions::DispatcherUnknownCommand => {}
- _ => panic!("Unexpected error"),
- }
- assert_eq!(err.cursor().unwrap(), 0);
- }
-
- #[test]
- fn execute_impermissible_command() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").requires(|_| false));
-
- let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
-
- let err = execute_result.err().unwrap();
- match err.type_ {
- BuiltInExceptions::DispatcherUnknownCommand => {}
- _ => panic!("Unexpected error"),
- }
- assert_eq!(err.cursor().unwrap(), 0);
- }
-
- #[test]
- fn execute_empty_command() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal(""));
-
- let execute_result = subject.execute("".into(), Rc::new(CommandSource {}));
-
- let err = execute_result.err().unwrap();
- match err.type_ {
- BuiltInExceptions::DispatcherUnknownCommand => {}
- _ => panic!("Unexpected error"),
- }
- assert_eq!(err.cursor().unwrap(), 0);
- }
-
- #[test]
- fn execute_unknown_subcommand() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").executes(|_| 42));
-
- let execute_result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
-
- let err = execute_result.err().unwrap();
- match err.type_ {
- BuiltInExceptions::DispatcherUnknownArgument => {}
- _ => panic!("Unexpected error"),
- }
- assert_eq!(err.cursor().unwrap(), 4);
- }
-
- #[test]
- fn execute_incorrect_literal() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").executes(|_| 42).then(literal("bar")));
-
- let execute_result = subject.execute("foo baz".into(), Rc::new(CommandSource {}));
-
- let err = execute_result.err().unwrap();
- match err.type_ {
- BuiltInExceptions::DispatcherUnknownArgument => {}
- _ => panic!("Unexpected error"),
- }
- assert_eq!(err.cursor().unwrap(), 4);
- }
-
- #[test]
- fn execute_ambiguous_incorrect_argument() {
- let mut subject = CommandDispatcher::new();
- subject.register(
- literal("foo")
- .executes(|_| 42)
- .then(literal("bar"))
- .then(literal("baz")),
- );
-
- let execute_result = subject.execute("foo unknown".into(), Rc::new(CommandSource {}));
-
- let err = execute_result.err().unwrap();
- match err.type_ {
- BuiltInExceptions::DispatcherUnknownArgument => {}
- _ => panic!("Unexpected error"),
- }
- assert_eq!(err.cursor().unwrap(), 4);
- }
-
- #[test]
- fn execute_subcommand() {
- let mut subject = CommandDispatcher::new();
-
- subject.register(
- literal("foo")
- .then(literal("a"))
- .then(literal("=").executes(|_| 100))
- .then(literal("c"))
- .executes(|_| 42),
- );
-
- assert_eq!(
- subject
- .execute("foo =".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 100
- );
- }
-
- #[test]
- fn parse_incomplete_literal() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").then(literal("bar").executes(|_| 42)));
-
- let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
- assert_eq!(parse.reader.remaining(), " ");
- assert_eq!(parse.context.nodes.len(), 1);
- }
-
- #[test]
- fn parse_incomplete_argument() {
- let mut subject = CommandDispatcher::new();
- subject.register(literal("foo").then(argument("bar", integer()).executes(|_| 42)));
-
- let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
- assert_eq!(parse.reader.remaining(), " ");
- assert_eq!(parse.context.nodes.len(), 1);
- }
-
- #[test]
- fn execute_ambiguious_parent_subcommand() {
- let mut subject = CommandDispatcher::new();
-
- subject.register(
- literal("test")
- .then(argument("incorrect", integer()).executes(|_| 42))
- .then(
- argument("right", integer()).then(argument("sub", integer()).executes(|_| 100)),
- ),
- );
-
- assert_eq!(
- subject
- .execute("test 1 2".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 100
- );
- }
-
- #[test]
- fn execute_ambiguious_parent_subcommand_via_redirect() {
- let mut subject = CommandDispatcher::new();
-
- let real = subject.register(
- literal("test")
- .then(argument("incorrect", integer()).executes(|_| 42))
- .then(
- argument("right", integer()).then(argument("sub", integer()).executes(|_| 100)),
- ),
- );
-
- subject.register(literal("redirect").redirect(real));
-
- assert_eq!(
- subject
- .execute("redirect 1 2".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 100
- );
- }
-
- #[test]
- fn execute_redirected_multiple_times() {
- let mut subject = CommandDispatcher::new();
-
- let concrete_node = subject.register(literal("actual").executes(|_| 42));
- let root = subject.root.clone();
- let redirect_node = subject.register(literal("redirected").redirect(root.clone()));
-
- let input = "redirected redirected actual";
-
- let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
- assert_eq!(parse.context.range.get(input), "redirected");
- assert_eq!(parse.context.nodes.len(), 1);
- assert_eq!(parse.context.root, root);
- assert_eq!(parse.context.nodes[0].range, parse.context.range);
- assert_eq!(parse.context.nodes[0].node, redirect_node);
-
- let child1 = parse.context.child.clone();
- assert!(child1.is_some());
- assert_eq!(child1.clone().unwrap().range.get(input), "redirected");
- assert_eq!(child1.clone().unwrap().nodes.len(), 1);
- assert_eq!(child1.clone().unwrap().root, root);
- assert_eq!(
- child1.clone().unwrap().nodes[0].range,
- child1.clone().unwrap().range
- );
- assert_eq!(child1.clone().unwrap().nodes[0].node, redirect_node);
-
- let child2 = child1.unwrap().child.clone();
- assert!(child2.is_some());
- assert_eq!(child2.clone().unwrap().range.get(input), "actual");
- assert_eq!(child2.clone().unwrap().nodes.len(), 1);
- assert_eq!(child2.clone().unwrap().root, root);
- assert_eq!(
- child2.clone().unwrap().nodes[0].range,
- child2.clone().unwrap().range
- );
- assert_eq!(child2.clone().unwrap().nodes[0].node, concrete_node);
-
- assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 42);
- }
-
- #[test]
- fn execute_redirected() {
- let mut subject = CommandDispatcher::new();
-
- let source1 = Rc::new(CommandSource {});
- let source2 = Rc::new(CommandSource {});
-
- let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Rc<CommandSource>>, CommandSyntaxException> {
- Ok(vec![source1.clone(), source2.clone()])
- };
-
- let concrete_node = subject.register(literal("actual").executes(|_| 42));
- let redirect_node =
- subject.register(literal("redirected").fork(subject.root.clone(), Rc::new(modifier)));
-
- let input = "redirected actual";
- let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
- assert_eq!(parse.context.range.get(input), "redirected");
- assert_eq!(parse.context.nodes.len(), 1);
- assert_eq!(parse.context.root, subject.root);
- assert_eq!(parse.context.nodes[0].range, parse.context.range);
- assert_eq!(parse.context.nodes[0].node, redirect_node);
-
- let parent = parse.context.child.clone();
- assert!(parent.is_some());
- let parent = parent.unwrap();
- assert_eq!(parent.range.get(input), "actual");
- assert_eq!(parent.nodes.len(), 1);
- assert_eq!(parse.context.root, subject.root);
- assert_eq!(parent.nodes[0].range, parent.range);
- assert_eq!(parent.nodes[0].node, concrete_node);
- assert_eq!(parent.source, Rc::new(CommandSource {}));
-
- assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
- }
-
- #[test]
- fn execute_orphaned_subcommand() {
- let mut subject = CommandDispatcher::new();
-
- subject.register(
- literal("foo")
- .then(argument("bar", integer()))
- .executes(|_| 42),
- );
-
- let result = subject.execute("foo 5".into(), Rc::new(CommandSource {}));
- assert!(result.is_err());
- let result = result.unwrap_err();
- assert_eq!(
- *result.get_type(),
- BuiltInExceptions::DispatcherUnknownCommand
- );
- assert_eq!(result.cursor(), Some(5));
- }
-
- #[test]
- fn execute_invalid_other() {
- let mut subject = CommandDispatcher::new();
-
- subject.register(literal("w").executes(|_| panic!("This should not run")));
- subject.register(literal("world").executes(|_| 42));
-
- assert_eq!(
- subject
- .execute("world".into(), Rc::new(CommandSource {}))
- .unwrap(),
- 42
- );
- }
-
- #[test]
- fn parse_no_space_separator() {
- let mut subject = CommandDispatcher::new();
-
- subject.register(
- literal("foo")
- .then(argument("bar", integer()))
- .executes(|_| 42),
- );
-
- let result = subject.execute("foo$".into(), Rc::new(CommandSource {}));
- assert!(result.is_err());
- let result = result.unwrap_err();
- assert_eq!(
- *result.get_type(),
- BuiltInExceptions::DispatcherUnknownCommand
- );
- assert_eq!(result.cursor(), Some(0));
- }
-
- #[test]
- fn execute_invalid_subcommand() {
- let mut subject = CommandDispatcher::new();
-
- subject.register(
- literal("foo")
- .then(argument("bar", integer()))
- .executes(|_| 42),
- );
-
- let result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
- assert!(result.is_err());
- let result = result.unwrap_err();
- // this fails for some reason, i blame mojang
- // assert_eq!(*result.get_type(), BuiltInExceptions::ReaderExpectedInt);
- assert_eq!(result.cursor(), Some(4));
- }
-
- #[test]
- fn get_path() {
- let mut subject = CommandDispatcher::<()>::new();
-
- let bar = literal("bar").build();
- subject.register(literal("foo").then_built(bar.clone()));
-
- assert_eq!(
- subject.get_path(bar),
- vec!["foo".to_string(), "bar".to_string()]
- );
- }
-
- #[test]
- fn find_node_doesnt_exist() {
- let subject = CommandDispatcher::<()>::new();
-
- assert_eq!(subject.find_node(&vec!["foo", "bar"]), None)
- }
-}
diff --git a/azalea-brigadier/src/lib.rs b/azalea-brigadier/src/lib.rs
index db46d46e..a294eb19 100644
--- a/azalea-brigadier/src/lib.rs
+++ b/azalea-brigadier/src/lib.rs
@@ -8,51 +8,3 @@ pub mod modifier;
pub mod parse_results;
pub mod string_reader;
pub mod tree;
-
-#[cfg(test)]
-mod tests {
-
- use std::rc::Rc;
-
- use crate::{
- arguments::integer_argument_type::{get_integer, integer},
- builder::{literal_argument_builder::literal, required_argument_builder::argument},
- command_dispatcher::CommandDispatcher,
- context::CommandContext,
- };
-
- struct CommandSourceStack {
- player: String,
- }
-
- #[test]
- fn it_works() {
- let mut dispatcher = CommandDispatcher::new();
-
- let source = Rc::new(CommandSourceStack {
- player: "player".to_string(),
- });
-
- dispatcher.register(
- literal("foo")
- .then(argument("bar", integer()).executes(
- |c: &CommandContext<CommandSourceStack>| {
- println!(
- "Bar is {:?} and player is {}",
- get_integer(c, "bar"),
- c.source.player
- );
- 2
- },
- ))
- .executes(|_| {
- println!("Called foo with no arguments");
- 1
- }),
- );
-
- let parse = dispatcher.parse("foo 123".into(), source.clone());
- assert_eq!(CommandDispatcher::<_>::execute_parsed(parse).unwrap(), 2);
- assert_eq!(dispatcher.execute("foo".into(), source).unwrap(), 1);
- }
-}
diff --git a/azalea-brigadier/src/string_reader.rs b/azalea-brigadier/src/string_reader.rs
index dcb35fcb..9eb09b57 100644
--- a/azalea-brigadier/src/string_reader.rs
+++ b/azalea-brigadier/src/string_reader.rs
@@ -272,619 +272,3 @@ impl StringReader {
Ok(())
}
}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn can_read() {
- let mut reader = StringReader::from("abc".to_string());
- 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 get_remaining_length() {
- let mut reader = StringReader::from("abc".to_string());
- assert_eq!(reader.remaining_length(), 3);
- reader.cursor = 1;
- assert_eq!(reader.remaining_length(), 2);
- reader.cursor = 2;
- assert_eq!(reader.remaining_length(), 1);
- reader.cursor = 3;
- assert_eq!(reader.remaining_length(), 0);
- }
-
- #[test]
- fn can_read_length() {
- let reader = StringReader::from("abc".to_string());
- assert_eq!(reader.can_read_length(1), true);
- assert_eq!(reader.can_read_length(2), true);
- assert_eq!(reader.can_read_length(3), true);
- assert_eq!(reader.can_read_length(4), false);
- assert_eq!(reader.can_read_length(5), false);
- }
-
- #[test]
- fn peek() {
- let mut reader = StringReader::from("abc".to_string());
- assert_eq!(reader.peek(), 'a');
- assert_eq!(reader.cursor(), 0);
- reader.cursor = 2;
- assert_eq!(reader.peek(), 'c');
- assert_eq!(reader.cursor(), 2);
- }
-
- #[test]
- fn peek_length() {
- let mut reader = StringReader::from("abc".to_string());
- assert_eq!(reader.peek_offset(0), 'a');
- assert_eq!(reader.peek_offset(2), 'c');
- assert_eq!(reader.cursor(), 0);
- reader.cursor = 1;
- assert_eq!(reader.peek_offset(1), 'c');
- assert_eq!(reader.cursor(), 1);
- }
-
- #[test]
- fn read() {
- let mut reader = StringReader::from("abc".to_string());
- assert_eq!(reader.read(), 'a');
- assert_eq!(reader.read(), 'b');
- assert_eq!(reader.read(), 'c');
- assert_eq!(reader.cursor(), 3);
- }
-
- #[test]
- fn skip() {
- let mut reader = StringReader::from("abc".to_string());
- reader.skip();
- assert_eq!(reader.cursor(), 1);
- }
-
- #[test]
- fn get_remaining() {
- let mut reader = StringReader::from("Hello!".to_string());
- assert_eq!(reader.remaining(), "Hello!");
- reader.cursor = 3;
- assert_eq!(reader.remaining(), "lo!");
- reader.cursor = 6;
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn get_read() {
- let mut reader = StringReader::from("Hello!".to_string());
- assert_eq!(reader.get_read(), "");
- reader.cursor = 3;
- assert_eq!(reader.get_read(), "Hel");
- reader.cursor = 6;
- assert_eq!(reader.get_read(), "Hello!");
- }
-
- #[test]
- fn skip_whitespace_none() {
- let mut reader = StringReader::from("Hello!".to_string());
- reader.skip_whitespace();
- assert_eq!(reader.cursor(), 0);
- }
-
- #[test]
- fn skip_whitespace_mixed() {
- let mut reader = StringReader::from(" \t \t\nHello!".to_string());
- reader.skip_whitespace();
- assert_eq!(reader.cursor(), 5);
- }
-
- #[test]
- fn skip_whitespace_empty() {
- let mut reader = StringReader::from("".to_string());
- reader.skip_whitespace();
- assert_eq!(reader.cursor(), 0);
- }
-
- #[test]
- fn read_unquoted_string() {
- let mut reader = StringReader::from("hello world".to_string());
- assert_eq!(reader.read_unquoted_string(), "hello");
- assert_eq!(reader.get_read(), "hello");
- assert_eq!(reader.remaining(), " world");
- }
-
- #[test]
- fn read_unquoted_string_empty() {
- let mut reader = StringReader::from("".to_string());
- assert_eq!(reader.read_unquoted_string(), "");
- assert_eq!(reader.get_read(), "");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_unquoted_string_empty_with_remaining() {
- let mut reader = StringReader::from(" hello world".to_string());
- assert_eq!(reader.read_unquoted_string(), "");
- assert_eq!(reader.get_read(), "");
- assert_eq!(reader.remaining(), " hello world");
- }
-
- #[test]
- fn read_quoted_string() {
- let mut reader = StringReader::from("\"hello world\"".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
- assert_eq!(reader.get_read(), "\"hello world\"");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_single_quoted_string() {
- let mut reader = StringReader::from("'hello world'".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
- assert_eq!(reader.get_read(), "'hello world'");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_mixed_quoted_string_double_inside_single() {
- let mut reader = StringReader::from("'hello \"world\"'".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello \"world\"");
- assert_eq!(reader.get_read(), "'hello \"world\"'");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_mixed_quoted_string_single_inside_double() {
- let mut reader = StringReader::from("\"hello 'world'\"".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello 'world'");
- assert_eq!(reader.get_read(), "\"hello 'world'\"");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_quoted_string_empty_quoted() {
- let mut reader = StringReader::from("".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "");
- assert_eq!(reader.get_read(), "");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_quoted_string_empty_quoted_with_remaining() {
- let mut reader = StringReader::from("\"\" hello world".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "");
- assert_eq!(reader.get_read(), "\"\"");
- assert_eq!(reader.remaining(), " hello world");
- }
-
- #[test]
- fn read_quoted_string_with_escaped_quote() {
- let mut reader = StringReader::from("\"hello \\\"world\\\"\"".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello \"world\"");
- assert_eq!(reader.get_read(), "\"hello \\\"world\\\"\"");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_quoted_string_with_escaped_escapes() {
- let mut reader = StringReader::from("\"\\\\o/\"".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "\\o/");
- assert_eq!(reader.get_read(), "\"\\\\o/\"");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_quoted_string_with_remaining() {
- let mut reader = StringReader::from("\"hello world\" foo bar".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
- assert_eq!(reader.get_read(), "\"hello world\"");
- assert_eq!(reader.remaining(), " foo bar");
- }
-
- #[test]
- fn read_quoted_string_with_immediate_remaining() {
- let mut reader = StringReader::from("\"hello world\"foo bar".to_string());
- assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
- assert_eq!(reader.get_read(), "\"hello world\"");
- assert_eq!(reader.remaining(), "foo bar");
- }
-
- #[test]
- fn read_quoted_string_no_open() {
- let mut reader = StringReader::from("hello world\"".to_string());
- let result = reader.read_quoted_string();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedStartOfQuote);
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_quoted_string_no_close() {
- let mut reader = StringReader::from("\"hello world".to_string());
- let result = reader.read_quoted_string();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedEndOfQuote);
- assert_eq!(e.cursor(), Some(12));
- }
- }
-
- #[test]
- fn read_quoted_string_invalid_escape() {
- let mut reader = StringReader::from("\"hello\\nworld\"".to_string());
- let result = reader.read_quoted_string();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidEscape { character: 'n' }
- );
- assert_eq!(e.cursor(), Some(7));
- }
- }
-
- #[test]
- fn read_quoted_string_invalid_quote_escape() {
- let mut reader = StringReader::from("'hello\\\"\'world".to_string());
- let result = reader.read_quoted_string();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidEscape { character: '"' }
- );
- assert_eq!(e.cursor(), Some(7));
- }
- }
-
- #[test]
- fn read_string_no_quotes() {
- let mut reader = StringReader::from("hello world".to_string());
- assert_eq!(reader.read_string().unwrap(), "hello");
- assert_eq!(reader.get_read(), "hello");
- assert_eq!(reader.remaining(), " world");
- }
-
- #[test]
- fn read_string_single_quotes() {
- let mut reader = StringReader::from("'hello world'".to_string());
- assert_eq!(reader.read_string().unwrap(), "hello world");
- assert_eq!(reader.get_read(), "'hello world'");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_string_double_quotes() {
- let mut reader = StringReader::from("\"hello world\"".to_string());
- assert_eq!(reader.read_string().unwrap(), "hello world");
- assert_eq!(reader.get_read(), "\"hello world\"");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_int() {
- let mut reader = StringReader::from("1234567890".to_string());
- assert_eq!(reader.read_int().unwrap(), 1234567890);
- assert_eq!(reader.get_read(), "1234567890");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_int_negative() {
- let mut reader = StringReader::from("-1234567890".to_string());
- assert_eq!(reader.read_int().unwrap(), -1234567890);
- assert_eq!(reader.get_read(), "-1234567890");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_int_invalid() {
- let mut reader = StringReader::from("12.34".to_string());
- let result = reader.read_int();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidInt {
- value: "12.34".to_string()
- }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_int_none() {
- let mut reader = StringReader::from("".to_string());
- let result = reader.read_int();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedInt);
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_int_with_remaining() {
- let mut reader = StringReader::from("1234567890 foo bar".to_string());
- assert_eq!(reader.read_int().unwrap(), 1234567890);
- assert_eq!(reader.get_read(), "1234567890");
- assert_eq!(reader.remaining(), " foo bar");
- }
-
- #[test]
- fn read_int_with_remaining_immediate() {
- let mut reader = StringReader::from("1234567890foo bar".to_string());
- assert_eq!(reader.read_int().unwrap(), 1234567890);
- assert_eq!(reader.get_read(), "1234567890");
- assert_eq!(reader.remaining(), "foo bar");
- }
-
- #[test]
- fn read_long() {
- let mut reader = StringReader::from("1234567890".to_string());
- assert_eq!(reader.read_long().unwrap(), 1234567890);
- assert_eq!(reader.get_read(), "1234567890");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_long_negative() {
- let mut reader = StringReader::from("-1234567890".to_string());
- assert_eq!(reader.read_long().unwrap(), -1234567890);
- assert_eq!(reader.get_read(), "-1234567890");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_long_invalid() {
- let mut reader = StringReader::from("12.34".to_string());
- let result = reader.read_long();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidLong {
- value: "12.34".to_string()
- }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_long_none() {
- let mut reader = StringReader::from("".to_string());
- let result = reader.read_long();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedLong);
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_long_with_remaining() {
- let mut reader = StringReader::from("1234567890 foo bar".to_string());
- assert_eq!(reader.read_long().unwrap(), 1234567890);
- assert_eq!(reader.get_read(), "1234567890");
- assert_eq!(reader.remaining(), " foo bar");
- }
-
- #[test]
- fn read_long_with_remaining_immediate() {
- let mut reader = StringReader::from("1234567890foo bar".to_string());
- assert_eq!(reader.read_long().unwrap(), 1234567890);
- assert_eq!(reader.get_read(), "1234567890");
- assert_eq!(reader.remaining(), "foo bar");
- }
-
- #[test]
- fn read_double() {
- let mut reader = StringReader::from("123".to_string());
- assert_eq!(reader.read_double().unwrap(), 123.0);
- assert_eq!(reader.get_read(), "123");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_double_with_decimal() {
- let mut reader = StringReader::from("12.34".to_string());
- assert_eq!(reader.read_double().unwrap(), 12.34);
- assert_eq!(reader.get_read(), "12.34");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_double_negative() {
- let mut reader = StringReader::from("-123".to_string());
- assert_eq!(reader.read_double().unwrap(), -123.0);
- assert_eq!(reader.get_read(), "-123");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_double_invalid() {
- let mut reader = StringReader::from("12.34.56".to_string());
- let result = reader.read_double();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidDouble {
- value: "12.34.56".to_string()
- }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_double_none() {
- let mut reader = StringReader::from("".to_string());
- let result = reader.read_double();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedDouble);
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_double_with_remaining() {
- let mut reader = StringReader::from("12.34 foo bar".to_string());
- assert_eq!(reader.read_double().unwrap(), 12.34);
- assert_eq!(reader.get_read(), "12.34");
- assert_eq!(reader.remaining(), " foo bar");
- }
-
- #[test]
- fn read_double_with_remaining_immediate() {
- let mut reader = StringReader::from("12.34foo bar".to_string());
- assert_eq!(reader.read_double().unwrap(), 12.34);
- assert_eq!(reader.get_read(), "12.34");
- assert_eq!(reader.remaining(), "foo bar");
- }
-
- #[test]
- fn read_float() {
- let mut reader = StringReader::from("123".to_string());
- assert_eq!(reader.read_float().unwrap(), 123.0f32);
- assert_eq!(reader.get_read(), "123");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_float_with_decimal() {
- let mut reader = StringReader::from("12.34".to_string());
- assert_eq!(reader.read_float().unwrap(), 12.34f32);
- assert_eq!(reader.get_read(), "12.34");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_float_negative() {
- let mut reader = StringReader::from("-123".to_string());
- assert_eq!(reader.read_float().unwrap(), -123.0f32);
- assert_eq!(reader.get_read(), "-123");
- assert_eq!(reader.remaining(), "");
- }
-
- #[test]
- fn read_float_invalid() {
- let mut reader = StringReader::from("12.34.56".to_string());
- let result = reader.read_float();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidFloat {
- value: "12.34.56".to_string()
- }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_float_none() {
- let mut reader = StringReader::from("".to_string());
- let result = reader.read_float();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedFloat);
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_float_with_remaining() {
- let mut reader = StringReader::from("12.34 foo bar".to_string());
- assert_eq!(reader.read_float().unwrap(), 12.34f32);
- assert_eq!(reader.get_read(), "12.34");
- assert_eq!(reader.remaining(), " foo bar");
- }
-
- #[test]
- fn read_float_with_remaining_immediate() {
- let mut reader = StringReader::from("12.34foo bar".to_string());
- assert_eq!(reader.read_float().unwrap(), 12.34f32);
- assert_eq!(reader.get_read(), "12.34");
- assert_eq!(reader.remaining(), "foo bar");
- }
-
- #[test]
- fn expect_correct() {
- let mut reader = StringReader::from("abc".to_string());
- reader.expect('a').unwrap();
- assert_eq!(reader.cursor(), 1);
- }
-
- #[test]
- fn expect_incorrect() {
- let mut reader = StringReader::from("bcd".to_string());
- let result = reader.expect('a');
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderExpectedSymbol { symbol: 'a' }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn expect_none() {
- let mut reader = StringReader::from("".to_string());
- let result = reader.expect('a');
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderExpectedSymbol { symbol: 'a' }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_boolean_correct() {
- let mut reader = StringReader::from("true".to_string());
- assert_eq!(reader.read_boolean().unwrap(), true);
- assert_eq!(reader.get_read(), "true");
- }
-
- #[test]
- fn read_boolean_incorrect() {
- let mut reader = StringReader::from("tuesday".to_string());
- let result = reader.read_boolean();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(
- e.get_type(),
- &BuiltInExceptions::ReaderInvalidBool {
- value: "tuesday".to_string()
- }
- );
- assert_eq!(e.cursor(), Some(0));
- }
- }
-
- #[test]
- fn read_boolean_none() {
- let mut reader = StringReader::from("".to_string());
- let result = reader.read_boolean();
- assert!(result.is_err());
- if let Err(e) = result {
- assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedBool);
- assert_eq!(e.cursor(), Some(0));
- }
- }
-}
diff --git a/azalea-brigadier/tests/arguments/bool_argument_type_test.rs b/azalea-brigadier/tests/arguments/bool_argument_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/arguments/bool_argument_type_test.rs
diff --git a/azalea-brigadier/tests/arguments/double_argument_type_test.rs b/azalea-brigadier/tests/arguments/double_argument_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/arguments/double_argument_type_test.rs
diff --git a/azalea-brigadier/tests/arguments/float_argument_type_test.rs b/azalea-brigadier/tests/arguments/float_argument_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/arguments/float_argument_type_test.rs
diff --git a/azalea-brigadier/tests/arguments/integer_argument_type_test.rs b/azalea-brigadier/tests/arguments/integer_argument_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/arguments/integer_argument_type_test.rs
diff --git a/azalea-brigadier/tests/arguments/long_argument_type_test.rs b/azalea-brigadier/tests/arguments/long_argument_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/arguments/long_argument_type_test.rs
diff --git a/azalea-brigadier/tests/arguments/string_argument_type_test.rs b/azalea-brigadier/tests/arguments/string_argument_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/arguments/string_argument_type_test.rs
diff --git a/azalea-brigadier/tests/builder/argument_builder_test.rs b/azalea-brigadier/tests/builder/argument_builder_test.rs
new file mode 100644
index 00000000..e570c988
--- /dev/null
+++ b/azalea-brigadier/tests/builder/argument_builder_test.rs
@@ -0,0 +1,75 @@
+use std::rc::Rc;
+
+use crate::{
+ arguments::integer_argument_type::integer,
+ builder::{literal_argument_builder::literal, required_argument_builder::argument},
+};
+
+use super::ArgumentBuilder;
+
+// public class ArgumentBuilderTest {
+// private TestableArgumentBuilder<Object> builder;
+
+// @Before
+// public void setUp() throws Exception {
+// builder = new TestableArgumentBuilder<>();
+// }
+
+// @Test
+// public void testArguments() throws Exception {
+// final RequiredArgumentBuilder<Object, ?> argument = argument("bar", integer());
+
+// builder.then(argument);
+
+// assertThat(builder.getArguments(), hasSize(1));
+// assertThat(builder.getArguments(), hasItem((CommandNode<Object>) argument.build()));
+// }
+
+#[test]
+fn test_arguments() {
+ let mut builder: ArgumentBuilder<()> = literal("foo");
+
+ let argument: ArgumentBuilder<()> = argument("bar", integer());
+ builder.then(argument.clone());
+ assert_eq!(builder.arguments.children.len(), 1);
+ let built_argument = Rc::new(argument.build());
+ assert!(builder
+ .arguments
+ .children
+ .values()
+ .any(|e| *e.borrow() == *built_argument));
+}
+
+// @Test
+// public void testRedirect() throws Exception {
+// final CommandNode<Object> target = mock(CommandNode.class);
+// builder.redirect(target);
+// assertThat(builder.getRedirect(), is(target));
+// }
+
+// @Test(expected = IllegalStateException.class)
+// public void testRedirect_withChild() throws Exception {
+// final CommandNode<Object> target = mock(CommandNode.class);
+// builder.then(literal("foo"));
+// builder.redirect(target);
+// }
+
+// @Test(expected = IllegalStateException.class)
+// public void testThen_withRedirect() throws Exception {
+// final CommandNode<Object> target = mock(CommandNode.class);
+// builder.redirect(target);
+// builder.then(literal("foo"));
+// }
+
+// private static class TestableArgumentBuilder<S> extends ArgumentBuilder<S, TestableArgumentBuilder<S>> {
+// @Override
+// protected TestableArgumentBuilder<S> getThis() {
+// return this;
+// }
+
+// @Override
+// public CommandNode<S> build() {
+// return null;
+// }
+// }
+// }
diff --git a/azalea-brigadier/tests/builder/literal_argument_builder_test.rs b/azalea-brigadier/tests/builder/literal_argument_builder_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/builder/literal_argument_builder_test.rs
diff --git a/azalea-brigadier/tests/builder/required_argument_builder_test.rs b/azalea-brigadier/tests/builder/required_argument_builder_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/builder/required_argument_builder_test.rs
diff --git a/azalea-brigadier/tests/command_dispatcher_test.rs b/azalea-brigadier/tests/command_dispatcher_test.rs
new file mode 100644
index 00000000..cb33ac73
--- /dev/null
+++ b/azalea-brigadier/tests/command_dispatcher_test.rs
@@ -0,0 +1,410 @@
+use std::rc::Rc;
+
+use azalea_brigadier::{
+ arguments::integer_argument_type::integer,
+ builder::{literal_argument_builder::literal, required_argument_builder::argument},
+ command_dispatcher::CommandDispatcher,
+ context::CommandContext,
+ exceptions::{BuiltInExceptions, CommandSyntaxException},
+ string_reader::StringReader,
+};
+
+#[derive(Debug, PartialEq)]
+struct CommandSource {}
+
+fn input_with_offset(input: &str, offset: usize) -> StringReader {
+ let mut result: StringReader = input.into();
+ result.cursor = offset;
+ result
+}
+
+#[test]
+fn create_and_execute_command() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").executes(|_| 42));
+
+ assert_eq!(
+ subject
+ .execute("foo".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 42
+ );
+}
+
+#[test]
+fn create_and_execute_offset_command() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").executes(|_| 42));
+
+ assert_eq!(
+ subject
+ .execute(input_with_offset("/foo", 1), Rc::new(CommandSource {}))
+ .unwrap(),
+ 42
+ );
+}
+
+#[test]
+fn create_and_merge_commands() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("base").then(literal("foo").executes(|_| 42)));
+ subject.register(literal("base").then(literal("bar").executes(|_| 42)));
+
+ assert_eq!(
+ subject
+ .execute("base foo".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 42
+ );
+ assert_eq!(
+ subject
+ .execute("base bar".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 42
+ );
+}
+
+#[test]
+fn execute_unknown_command() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("bar"));
+ subject.register(literal("baz"));
+
+ let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
+
+ let err = execute_result.err().unwrap();
+ match err.type_ {
+ BuiltInExceptions::DispatcherUnknownCommand => {}
+ _ => panic!("Unexpected error"),
+ }
+ assert_eq!(err.cursor().unwrap(), 0);
+}
+
+#[test]
+fn execute_impermissible_command() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").requires(|_| false));
+
+ let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
+
+ let err = execute_result.err().unwrap();
+ match err.type_ {
+ BuiltInExceptions::DispatcherUnknownCommand => {}
+ _ => panic!("Unexpected error"),
+ }
+ assert_eq!(err.cursor().unwrap(), 0);
+}
+
+#[test]
+fn execute_empty_command() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal(""));
+
+ let execute_result = subject.execute("".into(), Rc::new(CommandSource {}));
+
+ let err = execute_result.err().unwrap();
+ match err.type_ {
+ BuiltInExceptions::DispatcherUnknownCommand => {}
+ _ => panic!("Unexpected error"),
+ }
+ assert_eq!(err.cursor().unwrap(), 0);
+}
+
+#[test]
+fn execute_unknown_subcommand() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").executes(|_| 42));
+
+ let execute_result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
+
+ let err = execute_result.err().unwrap();
+ match err.type_ {
+ BuiltInExceptions::DispatcherUnknownArgument => {}
+ _ => panic!("Unexpected error"),
+ }
+ assert_eq!(err.cursor().unwrap(), 4);
+}
+
+#[test]
+fn execute_incorrect_literal() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").executes(|_| 42).then(literal("bar")));
+
+ let execute_result = subject.execute("foo baz".into(), Rc::new(CommandSource {}));
+
+ let err = execute_result.err().unwrap();
+ match err.type_ {
+ BuiltInExceptions::DispatcherUnknownArgument => {}
+ _ => panic!("Unexpected error"),
+ }
+ assert_eq!(err.cursor().unwrap(), 4);
+}
+
+#[test]
+fn execute_ambiguous_incorrect_argument() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(
+ literal("foo")
+ .executes(|_| 42)
+ .then(literal("bar"))
+ .then(literal("baz")),
+ );
+
+ let execute_result = subject.execute("foo unknown".into(), Rc::new(CommandSource {}));
+
+ let err = execute_result.err().unwrap();
+ match err.type_ {
+ BuiltInExceptions::DispatcherUnknownArgument => {}
+ _ => panic!("Unexpected error"),
+ }
+ assert_eq!(err.cursor().unwrap(), 4);
+}
+
+#[test]
+fn execute_subcommand() {
+ let mut subject = CommandDispatcher::new();
+
+ subject.register(
+ literal("foo")
+ .then(literal("a"))
+ .then(literal("=").executes(|_| 100))
+ .then(literal("c"))
+ .executes(|_| 42),
+ );
+
+ assert_eq!(
+ subject
+ .execute("foo =".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 100
+ );
+}
+
+#[test]
+fn parse_incomplete_literal() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").then(literal("bar").executes(|_| 42)));
+
+ let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
+ assert_eq!(parse.reader.remaining(), " ");
+ assert_eq!(parse.context.nodes.len(), 1);
+}
+
+#[test]
+fn parse_incomplete_argument() {
+ let mut subject = CommandDispatcher::new();
+ subject.register(literal("foo").then(argument("bar", integer()).executes(|_| 42)));
+
+ let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
+ assert_eq!(parse.reader.remaining(), " ");
+ assert_eq!(parse.context.nodes.len(), 1);
+}
+
+#[test]
+fn execute_ambiguious_parent_subcommand() {
+ let mut subject = CommandDispatcher::new();
+
+ subject.register(
+ literal("test")
+ .then(argument("incorrect", integer()).executes(|_| 42))
+ .then(argument("right", integer()).then(argument("sub", integer()).executes(|_| 100))),
+ );
+
+ assert_eq!(
+ subject
+ .execute("test 1 2".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 100
+ );
+}
+
+#[test]
+fn execute_ambiguious_parent_subcommand_via_redirect() {
+ let mut subject = CommandDispatcher::new();
+
+ let real = subject.register(
+ literal("test")
+ .then(argument("incorrect", integer()).executes(|_| 42))
+ .then(argument("right", integer()).then(argument("sub", integer()).executes(|_| 100))),
+ );
+
+ subject.register(literal("redirect").redirect(real));
+
+ assert_eq!(
+ subject
+ .execute("redirect 1 2".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 100
+ );
+}
+
+#[test]
+fn execute_redirected_multiple_times() {
+ let mut subject = CommandDispatcher::new();
+
+ let concrete_node = subject.register(literal("actual").executes(|_| 42));
+ let root = subject.root.clone();
+ let redirect_node = subject.register(literal("redirected").redirect(root.clone()));
+
+ let input = "redirected redirected actual";
+
+ let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
+ assert_eq!(parse.context.range.get(input), "redirected");
+ assert_eq!(parse.context.nodes.len(), 1);
+ assert_eq!(parse.context.root, root);
+ assert_eq!(parse.context.nodes[0].range, parse.context.range);
+ assert_eq!(parse.context.nodes[0].node, redirect_node);
+
+ let child1 = parse.context.child.clone();
+ assert!(child1.is_some());
+ assert_eq!(child1.clone().unwrap().range.get(input), "redirected");
+ assert_eq!(child1.clone().unwrap().nodes.len(), 1);
+ assert_eq!(child1.clone().unwrap().root, root);
+ assert_eq!(
+ child1.clone().unwrap().nodes[0].range,
+ child1.clone().unwrap().range
+ );
+ assert_eq!(child1.clone().unwrap().nodes[0].node, redirect_node);
+
+ let child2 = child1.unwrap().child.clone();
+ assert!(child2.is_some());
+ assert_eq!(child2.clone().unwrap().range.get(input), "actual");
+ assert_eq!(child2.clone().unwrap().nodes.len(), 1);
+ assert_eq!(child2.clone().unwrap().root, root);
+ assert_eq!(
+ child2.clone().unwrap().nodes[0].range,
+ child2.clone().unwrap().range
+ );
+ assert_eq!(child2.clone().unwrap().nodes[0].node, concrete_node);
+
+ assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 42);
+}
+
+#[test]
+fn execute_redirected() {
+ let mut subject = CommandDispatcher::new();
+
+ let source1 = Rc::new(CommandSource {});
+ let source2 = Rc::new(CommandSource {});
+
+ let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Rc<CommandSource>>, CommandSyntaxException> {
+ Ok(vec![source1.clone(), source2.clone()])
+ };
+
+ let concrete_node = subject.register(literal("actual").executes(|_| 42));
+ let redirect_node =
+ subject.register(literal("redirected").fork(subject.root.clone(), Rc::new(modifier)));
+
+ let input = "redirected actual";
+ let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
+ assert_eq!(parse.context.range.get(input), "redirected");
+ assert_eq!(parse.context.nodes.len(), 1);
+ assert_eq!(parse.context.root, subject.root);
+ assert_eq!(parse.context.nodes[0].range, parse.context.range);
+ assert_eq!(parse.context.nodes[0].node, redirect_node);
+
+ let parent = parse.context.child.clone();
+ assert!(parent.is_some());
+ let parent = parent.unwrap();
+ assert_eq!(parent.range.get(input), "actual");
+ assert_eq!(parent.nodes.len(), 1);
+ assert_eq!(parse.context.root, subject.root);
+ assert_eq!(parent.nodes[0].range, parent.range);
+ assert_eq!(parent.nodes[0].node, concrete_node);
+ assert_eq!(parent.source, Rc::new(CommandSource {}));
+
+ assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
+}
+
+#[test]
+fn execute_orphaned_subcommand() {
+ let mut subject = CommandDispatcher::new();
+
+ subject.register(
+ literal("foo")
+ .then(argument("bar", integer()))
+ .executes(|_| 42),
+ );
+
+ let result = subject.execute("foo 5".into(), Rc::new(CommandSource {}));
+ assert!(result.is_err());
+ let result = result.unwrap_err();
+ assert_eq!(
+ *result.get_type(),
+ BuiltInExceptions::DispatcherUnknownCommand
+ );
+ assert_eq!(result.cursor(), Some(5));
+}
+
+#[test]
+fn execute_invalid_other() {
+ let mut subject = CommandDispatcher::new();
+
+ subject.register(literal("w").executes(|_| panic!("This should not run")));
+ subject.register(literal("world").executes(|_| 42));
+
+ assert_eq!(
+ subject
+ .execute("world".into(), Rc::new(CommandSource {}))
+ .unwrap(),
+ 42
+ );
+}
+
+#[test]
+fn parse_no_space_separator() {
+ let mut subject = CommandDispatcher::new();
+
+ subject.register(
+ literal("foo")
+ .then(argument("bar", integer()))
+ .executes(|_| 42),
+ );
+
+ let result = subject.execute("foo$".into(), Rc::new(CommandSource {}));
+ assert!(result.is_err());
+ let result = result.unwrap_err();
+ assert_eq!(
+ *result.get_type(),
+ BuiltInExceptions::DispatcherUnknownCommand
+ );
+ assert_eq!(result.cursor(), Some(0));
+}
+
+#[test]
+fn execute_invalid_subcommand() {
+ let mut subject = CommandDispatcher::new();
+
+ subject.register(
+ literal("foo")
+ .then(argument("bar", integer()))
+ .executes(|_| 42),
+ );
+
+ let result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
+ assert!(result.is_err());
+ let result = result.unwrap_err();
+ // this fails for some reason, i blame mojang
+ // assert_eq!(*result.get_type(), BuiltInExceptions::ReaderExpectedInt);
+ assert_eq!(result.cursor(), Some(4));
+}
+
+#[test]
+fn get_path() {
+ let mut subject = CommandDispatcher::<()>::new();
+
+ let bar = literal("bar").build();
+ subject.register(literal("foo").then_built(bar.clone()));
+
+ assert_eq!(
+ subject.get_path(bar),
+ vec!["foo".to_string(), "bar".to_string()]
+ );
+}
+
+#[test]
+fn find_node_doesnt_exist() {
+ let subject = CommandDispatcher::<()>::new();
+
+ assert_eq!(subject.find_node(&vec!["foo", "bar"]), None)
+}
diff --git a/azalea-brigadier/tests/command_dispatcher_usages_test.rs b/azalea-brigadier/tests/command_dispatcher_usages_test.rs
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/azalea-brigadier/tests/command_dispatcher_usages_test.rs
@@ -0,0 +1 @@
+
diff --git a/azalea-brigadier/tests/command_suggestions_test.rs b/azalea-brigadier/tests/command_suggestions_test.rs
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/azalea-brigadier/tests/command_suggestions_test.rs
@@ -0,0 +1 @@
+
diff --git a/azalea-brigadier/tests/context/command_context_test.rs b/azalea-brigadier/tests/context/command_context_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/context/command_context_test.rs
diff --git a/azalea-brigadier/tests/context/parsed_argument_test.rs b/azalea-brigadier/tests/context/parsed_argument_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/context/parsed_argument_test.rs
diff --git a/azalea-brigadier/tests/exceptions/dynamic_command_syntax_exception_type_test.rs b/azalea-brigadier/tests/exceptions/dynamic_command_syntax_exception_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/exceptions/dynamic_command_syntax_exception_type_test.rs
diff --git a/azalea-brigadier/tests/exceptions/simple_command_syntax_exception_type_test.rs b/azalea-brigadier/tests/exceptions/simple_command_syntax_exception_type_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/exceptions/simple_command_syntax_exception_type_test.rs
diff --git a/azalea-brigadier/tests/string_reader_test.rs b/azalea-brigadier/tests/string_reader_test.rs
new file mode 100644
index 00000000..5008eff8
--- /dev/null
+++ b/azalea-brigadier/tests/string_reader_test.rs
@@ -0,0 +1,612 @@
+use azalea_brigadier::{exceptions::BuiltInExceptions, string_reader::StringReader};
+
+#[test]
+fn can_read() {
+ let mut reader = StringReader::from("abc".to_string());
+ 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 get_remaining_length() {
+ let mut reader = StringReader::from("abc".to_string());
+ assert_eq!(reader.remaining_length(), 3);
+ reader.cursor = 1;
+ assert_eq!(reader.remaining_length(), 2);
+ reader.cursor = 2;
+ assert_eq!(reader.remaining_length(), 1);
+ reader.cursor = 3;
+ assert_eq!(reader.remaining_length(), 0);
+}
+
+#[test]
+fn can_read_length() {
+ let reader = StringReader::from("abc".to_string());
+ assert_eq!(reader.can_read_length(1), true);
+ assert_eq!(reader.can_read_length(2), true);
+ assert_eq!(reader.can_read_length(3), true);
+ assert_eq!(reader.can_read_length(4), false);
+ assert_eq!(reader.can_read_length(5), false);
+}
+
+#[test]
+fn peek() {
+ let mut reader = StringReader::from("abc".to_string());
+ assert_eq!(reader.peek(), 'a');
+ assert_eq!(reader.cursor(), 0);
+ reader.cursor = 2;
+ assert_eq!(reader.peek(), 'c');
+ assert_eq!(reader.cursor(), 2);
+}
+
+#[test]
+fn peek_length() {
+ let mut reader = StringReader::from("abc".to_string());
+ assert_eq!(reader.peek_offset(0), 'a');
+ assert_eq!(reader.peek_offset(2), 'c');
+ assert_eq!(reader.cursor(), 0);
+ reader.cursor = 1;
+ assert_eq!(reader.peek_offset(1), 'c');
+ assert_eq!(reader.cursor(), 1);
+}
+
+#[test]
+fn read() {
+ let mut reader = StringReader::from("abc".to_string());
+ assert_eq!(reader.read(), 'a');
+ assert_eq!(reader.read(), 'b');
+ assert_eq!(reader.read(), 'c');
+ assert_eq!(reader.cursor(), 3);
+}
+
+#[test]
+fn skip() {
+ let mut reader = StringReader::from("abc".to_string());
+ reader.skip();
+ assert_eq!(reader.cursor(), 1);
+}
+
+#[test]
+fn get_remaining() {
+ let mut reader = StringReader::from("Hello!".to_string());
+ assert_eq!(reader.remaining(), "Hello!");
+ reader.cursor = 3;
+ assert_eq!(reader.remaining(), "lo!");
+ reader.cursor = 6;
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn get_read() {
+ let mut reader = StringReader::from("Hello!".to_string());
+ assert_eq!(reader.get_read(), "");
+ reader.cursor = 3;
+ assert_eq!(reader.get_read(), "Hel");
+ reader.cursor = 6;
+ assert_eq!(reader.get_read(), "Hello!");
+}
+
+#[test]
+fn skip_whitespace_none() {
+ let mut reader = StringReader::from("Hello!".to_string());
+ reader.skip_whitespace();
+ assert_eq!(reader.cursor(), 0);
+}
+
+#[test]
+fn skip_whitespace_mixed() {
+ let mut reader = StringReader::from(" \t \t\nHello!".to_string());
+ reader.skip_whitespace();
+ assert_eq!(reader.cursor(), 5);
+}
+
+#[test]
+fn skip_whitespace_empty() {
+ let mut reader = StringReader::from("".to_string());
+ reader.skip_whitespace();
+ assert_eq!(reader.cursor(), 0);
+}
+
+#[test]
+fn read_unquoted_string() {
+ let mut reader = StringReader::from("hello world".to_string());
+ assert_eq!(reader.read_unquoted_string(), "hello");
+ assert_eq!(reader.get_read(), "hello");
+ assert_eq!(reader.remaining(), " world");
+}
+
+#[test]
+fn read_unquoted_string_empty() {
+ let mut reader = StringReader::from("".to_string());
+ assert_eq!(reader.read_unquoted_string(), "");
+ assert_eq!(reader.get_read(), "");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_unquoted_string_empty_with_remaining() {
+ let mut reader = StringReader::from(" hello world".to_string());
+ assert_eq!(reader.read_unquoted_string(), "");
+ assert_eq!(reader.get_read(), "");
+ assert_eq!(reader.remaining(), " hello world");
+}
+
+#[test]
+fn read_quoted_string() {
+ let mut reader = StringReader::from("\"hello world\"".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
+ assert_eq!(reader.get_read(), "\"hello world\"");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_single_quoted_string() {
+ let mut reader = StringReader::from("'hello world'".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
+ assert_eq!(reader.get_read(), "'hello world'");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_mixed_quoted_string_double_inside_single() {
+ let mut reader = StringReader::from("'hello \"world\"'".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello \"world\"");
+ assert_eq!(reader.get_read(), "'hello \"world\"'");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_mixed_quoted_string_single_inside_double() {
+ let mut reader = StringReader::from("\"hello 'world'\"".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello 'world'");
+ assert_eq!(reader.get_read(), "\"hello 'world'\"");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_quoted_string_empty_quoted() {
+ let mut reader = StringReader::from("".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "");
+ assert_eq!(reader.get_read(), "");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_quoted_string_empty_quoted_with_remaining() {
+ let mut reader = StringReader::from("\"\" hello world".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "");
+ assert_eq!(reader.get_read(), "\"\"");
+ assert_eq!(reader.remaining(), " hello world");
+}
+
+#[test]
+fn read_quoted_string_with_escaped_quote() {
+ let mut reader = StringReader::from("\"hello \\\"world\\\"\"".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello \"world\"");
+ assert_eq!(reader.get_read(), "\"hello \\\"world\\\"\"");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_quoted_string_with_escaped_escapes() {
+ let mut reader = StringReader::from("\"\\\\o/\"".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "\\o/");
+ assert_eq!(reader.get_read(), "\"\\\\o/\"");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_quoted_string_with_remaining() {
+ let mut reader = StringReader::from("\"hello world\" foo bar".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
+ assert_eq!(reader.get_read(), "\"hello world\"");
+ assert_eq!(reader.remaining(), " foo bar");
+}
+
+#[test]
+fn read_quoted_string_with_immediate_remaining() {
+ let mut reader = StringReader::from("\"hello world\"foo bar".to_string());
+ assert_eq!(reader.read_quoted_string().unwrap(), "hello world");
+ assert_eq!(reader.get_read(), "\"hello world\"");
+ assert_eq!(reader.remaining(), "foo bar");
+}
+
+#[test]
+fn read_quoted_string_no_open() {
+ let mut reader = StringReader::from("hello world\"".to_string());
+ let result = reader.read_quoted_string();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedStartOfQuote);
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_quoted_string_no_close() {
+ let mut reader = StringReader::from("\"hello world".to_string());
+ let result = reader.read_quoted_string();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedEndOfQuote);
+ assert_eq!(e.cursor(), Some(12));
+ }
+}
+
+#[test]
+fn read_quoted_string_invalid_escape() {
+ let mut reader = StringReader::from("\"hello\\nworld\"".to_string());
+ let result = reader.read_quoted_string();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidEscape { character: 'n' }
+ );
+ assert_eq!(e.cursor(), Some(7));
+ }
+}
+
+#[test]
+fn read_quoted_string_invalid_quote_escape() {
+ let mut reader = StringReader::from("'hello\\\"\'world".to_string());
+ let result = reader.read_quoted_string();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidEscape { character: '"' }
+ );
+ assert_eq!(e.cursor(), Some(7));
+ }
+}
+
+#[test]
+fn read_string_no_quotes() {
+ let mut reader = StringReader::from("hello world".to_string());
+ assert_eq!(reader.read_string().unwrap(), "hello");
+ assert_eq!(reader.get_read(), "hello");
+ assert_eq!(reader.remaining(), " world");
+}
+
+#[test]
+fn read_string_single_quotes() {
+ let mut reader = StringReader::from("'hello world'".to_string());
+ assert_eq!(reader.read_string().unwrap(), "hello world");
+ assert_eq!(reader.get_read(), "'hello world'");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_string_double_quotes() {
+ let mut reader = StringReader::from("\"hello world\"".to_string());
+ assert_eq!(reader.read_string().unwrap(), "hello world");
+ assert_eq!(reader.get_read(), "\"hello world\"");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_int() {
+ let mut reader = StringReader::from("1234567890".to_string());
+ assert_eq!(reader.read_int().unwrap(), 1234567890);
+ assert_eq!(reader.get_read(), "1234567890");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_int_negative() {
+ let mut reader = StringReader::from("-1234567890".to_string());
+ assert_eq!(reader.read_int().unwrap(), -1234567890);
+ assert_eq!(reader.get_read(), "-1234567890");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_int_invalid() {
+ let mut reader = StringReader::from("12.34".to_string());
+ let result = reader.read_int();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidInt {
+ value: "12.34".to_string()
+ }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_int_none() {
+ let mut reader = StringReader::from("".to_string());
+ let result = reader.read_int();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedInt);
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_int_with_remaining() {
+ let mut reader = StringReader::from("1234567890 foo bar".to_string());
+ assert_eq!(reader.read_int().unwrap(), 1234567890);
+ assert_eq!(reader.get_read(), "1234567890");
+ assert_eq!(reader.remaining(), " foo bar");
+}
+
+#[test]
+fn read_int_with_remaining_immediate() {
+ let mut reader = StringReader::from("1234567890foo bar".to_string());
+ assert_eq!(reader.read_int().unwrap(), 1234567890);
+ assert_eq!(reader.get_read(), "1234567890");
+ assert_eq!(reader.remaining(), "foo bar");
+}
+
+#[test]
+fn read_long() {
+ let mut reader = StringReader::from("1234567890".to_string());
+ assert_eq!(reader.read_long().unwrap(), 1234567890);
+ assert_eq!(reader.get_read(), "1234567890");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_long_negative() {
+ let mut reader = StringReader::from("-1234567890".to_string());
+ assert_eq!(reader.read_long().unwrap(), -1234567890);
+ assert_eq!(reader.get_read(), "-1234567890");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_long_invalid() {
+ let mut reader = StringReader::from("12.34".to_string());
+ let result = reader.read_long();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidLong {
+ value: "12.34".to_string()
+ }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_long_none() {
+ let mut reader = StringReader::from("".to_string());
+ let result = reader.read_long();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedLong);
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_long_with_remaining() {
+ let mut reader = StringReader::from("1234567890 foo bar".to_string());
+ assert_eq!(reader.read_long().unwrap(), 1234567890);
+ assert_eq!(reader.get_read(), "1234567890");
+ assert_eq!(reader.remaining(), " foo bar");
+}
+
+#[test]
+fn read_long_with_remaining_immediate() {
+ let mut reader = StringReader::from("1234567890foo bar".to_string());
+ assert_eq!(reader.read_long().unwrap(), 1234567890);
+ assert_eq!(reader.get_read(), "1234567890");
+ assert_eq!(reader.remaining(), "foo bar");
+}
+
+#[test]
+fn read_double() {
+ let mut reader = StringReader::from("123".to_string());
+ assert_eq!(reader.read_double().unwrap(), 123.0);
+ assert_eq!(reader.get_read(), "123");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_double_with_decimal() {
+ let mut reader = StringReader::from("12.34".to_string());
+ assert_eq!(reader.read_double().unwrap(), 12.34);
+ assert_eq!(reader.get_read(), "12.34");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_double_negative() {
+ let mut reader = StringReader::from("-123".to_string());
+ assert_eq!(reader.read_double().unwrap(), -123.0);
+ assert_eq!(reader.get_read(), "-123");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_double_invalid() {
+ let mut reader = StringReader::from("12.34.56".to_string());
+ let result = reader.read_double();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidDouble {
+ value: "12.34.56".to_string()
+ }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_double_none() {
+ let mut reader = StringReader::from("".to_string());
+ let result = reader.read_double();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedDouble);
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_double_with_remaining() {
+ let mut reader = StringReader::from("12.34 foo bar".to_string());
+ assert_eq!(reader.read_double().unwrap(), 12.34);
+ assert_eq!(reader.get_read(), "12.34");
+ assert_eq!(reader.remaining(), " foo bar");
+}
+
+#[test]
+fn read_double_with_remaining_immediate() {
+ let mut reader = StringReader::from("12.34foo bar".to_string());
+ assert_eq!(reader.read_double().unwrap(), 12.34);
+ assert_eq!(reader.get_read(), "12.34");
+ assert_eq!(reader.remaining(), "foo bar");
+}
+
+#[test]
+fn read_float() {
+ let mut reader = StringReader::from("123".to_string());
+ assert_eq!(reader.read_float().unwrap(), 123.0f32);
+ assert_eq!(reader.get_read(), "123");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_float_with_decimal() {
+ let mut reader = StringReader::from("12.34".to_string());
+ assert_eq!(reader.read_float().unwrap(), 12.34f32);
+ assert_eq!(reader.get_read(), "12.34");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_float_negative() {
+ let mut reader = StringReader::from("-123".to_string());
+ assert_eq!(reader.read_float().unwrap(), -123.0f32);
+ assert_eq!(reader.get_read(), "-123");
+ assert_eq!(reader.remaining(), "");
+}
+
+#[test]
+fn read_float_invalid() {
+ let mut reader = StringReader::from("12.34.56".to_string());
+ let result = reader.read_float();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidFloat {
+ value: "12.34.56".to_string()
+ }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_float_none() {
+ let mut reader = StringReader::from("".to_string());
+ let result = reader.read_float();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedFloat);
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_float_with_remaining() {
+ let mut reader = StringReader::from("12.34 foo bar".to_string());
+ assert_eq!(reader.read_float().unwrap(), 12.34f32);
+ assert_eq!(reader.get_read(), "12.34");
+ assert_eq!(reader.remaining(), " foo bar");
+}
+
+#[test]
+fn read_float_with_remaining_immediate() {
+ let mut reader = StringReader::from("12.34foo bar".to_string());
+ assert_eq!(reader.read_float().unwrap(), 12.34f32);
+ assert_eq!(reader.get_read(), "12.34");
+ assert_eq!(reader.remaining(), "foo bar");
+}
+
+#[test]
+fn expect_correct() {
+ let mut reader = StringReader::from("abc".to_string());
+ reader.expect('a').unwrap();
+ assert_eq!(reader.cursor(), 1);
+}
+
+#[test]
+fn expect_incorrect() {
+ let mut reader = StringReader::from("bcd".to_string());
+ let result = reader.expect('a');
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderExpectedSymbol { symbol: 'a' }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn expect_none() {
+ let mut reader = StringReader::from("".to_string());
+ let result = reader.expect('a');
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderExpectedSymbol { symbol: 'a' }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_boolean_correct() {
+ let mut reader = StringReader::from("true".to_string());
+ assert_eq!(reader.read_boolean().unwrap(), true);
+ assert_eq!(reader.get_read(), "true");
+}
+
+#[test]
+fn read_boolean_incorrect() {
+ let mut reader = StringReader::from("tuesday".to_string());
+ let result = reader.read_boolean();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(
+ e.get_type(),
+ &BuiltInExceptions::ReaderInvalidBool {
+ value: "tuesday".to_string()
+ }
+ );
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
+
+#[test]
+fn read_boolean_none() {
+ let mut reader = StringReader::from("".to_string());
+ let result = reader.read_boolean();
+ assert!(result.is_err());
+ if let Err(e) = result {
+ assert_eq!(e.get_type(), &BuiltInExceptions::ReaderExpectedBool);
+ assert_eq!(e.cursor(), Some(0));
+ }
+}
diff --git a/azalea-brigadier/tests/suggestion/suggestion_test.rs b/azalea-brigadier/tests/suggestion/suggestion_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/suggestion/suggestion_test.rs
diff --git a/azalea-brigadier/tests/suggestion/suggestions_builder_test.rs b/azalea-brigadier/tests/suggestion/suggestions_builder_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/suggestion/suggestions_builder_test.rs
diff --git a/azalea-brigadier/tests/suggestion/suggestions_test.rs b/azalea-brigadier/tests/suggestion/suggestions_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/suggestion/suggestions_test.rs
diff --git a/azalea-brigadier/tests/tree/abstract_command_node_test.rs b/azalea-brigadier/tests/tree/abstract_command_node_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/tree/abstract_command_node_test.rs
diff --git a/azalea-brigadier/tests/tree/argument_command_node_test.rs b/azalea-brigadier/tests/tree/argument_command_node_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/tree/argument_command_node_test.rs
diff --git a/azalea-brigadier/tests/tree/literal_command_node_test.rs b/azalea-brigadier/tests/tree/literal_command_node_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/tree/literal_command_node_test.rs
diff --git a/azalea-brigadier/tests/tree/root_command_node_test.rs b/azalea-brigadier/tests/tree/root_command_node_test.rs
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/azalea-brigadier/tests/tree/root_command_node_test.rs