1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

more tests and start adding redirects

This commit is contained in:
mat 2022-04-17 18:08:19 -05:00
parent 6f3c41e01c
commit e945bfac77
2 changed files with 316 additions and 16 deletions

View file

@ -12,14 +12,15 @@ pub enum ArgumentBuilderType {
/// A node that hasn't yet been built.
#[derive(Clone)]
pub struct ArgumentBuilder<S: Any + Clone> {
value: ArgumentBuilderType,
arguments: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
children: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
literals: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
arguments: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
executes: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>,
command: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>,
requirement: Rc<dyn Fn(Rc<S>) -> bool>,
target: Option<Rc<RefCell<CommandNode<S>>>>,
value: ArgumentBuilderType,
forks: bool,
modifier: Option<Rc<dyn RedirectModifier<S>>>,
}
@ -34,10 +35,11 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
children: BTreeMap::new(),
literals: BTreeMap::new(),
arguments: BTreeMap::new(),
executes: None,
command: None,
requirement: Rc::new(|_| true),
forks: false,
modifier: None,
target: None,
}
}
@ -62,7 +64,7 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
where
F: Fn(&CommandContext<S>) -> i32 + 'static,
{
self.executes = Some(Rc::new(f));
self.command = Some(Rc::new(f));
self.clone()
}
@ -74,6 +76,25 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
self.clone()
}
pub fn redirect(&mut self, target: Rc<RefCell<CommandNode<S>>>) -> Self {
self.forward(target, None, false)
}
pub fn forward(
&mut self,
target: Rc<RefCell<CommandNode<S>>>,
modifier: Option<Rc<dyn RedirectModifier<S>>>,
fork: bool,
) -> Self {
if !self.arguments.is_empty() {
panic!("Cannot forward a node with children");
}
self.target = Some(target);
self.modifier = modifier;
self.forks = fork;
self.clone()
}
pub fn build(self) -> CommandNode<S> {
CommandNode {
value: self.value,
@ -82,9 +103,9 @@ impl<S: Any + Clone> ArgumentBuilder<S> {
literals: self.literals,
arguments: self.arguments,
command: self.executes.clone(),
command: self.command.clone(),
requirement: self.requirement.clone(),
redirect: None,
redirect: self.target,
forks: self.forks,
modifier: self.modifier,
}
@ -98,7 +119,7 @@ impl<S: Any + Clone> Debug for ArgumentBuilder<S> {
.field("children", &self.children)
.field("literals", &self.literals)
.field("arguments", &self.arguments)
.field("executes", &self.executes.is_some())
.field("executes", &self.command.is_some())
// .field("requirement", &self.requirement)
.field("forks", &self.forks)
// .field("modifier", &self.modifier)

View file

@ -26,9 +26,10 @@ impl<S: Any + Clone> CommandDispatcher<S> {
}
}
pub fn register(&mut self, node: ArgumentBuilder<S>) {
pub fn register(&mut self, node: ArgumentBuilder<S>) -> Rc<RefCell<CommandNode<S>>> {
let build = Rc::new(RefCell::new(node.build()));
self.root.borrow_mut().add_child(&build);
build
}
pub fn parse(&self, command: StringReader, source: S) -> ParseResults<S> {
@ -241,7 +242,10 @@ impl<S: Any + Clone> Clone for CommandDispatcher<S> {
#[cfg(test)]
mod tests {
use super::*;
use crate::builder::literal_argument_builder::literal;
use crate::{
builder::{literal_argument_builder::literal, required_argument_builder::argument},
parsers::integer,
};
struct CommandSource {}
@ -260,7 +264,7 @@ mod tests {
// }
#[test]
fn create_and_execute_command() {
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
let mut subject = CommandDispatcher::new();
subject.register(literal("foo").executes(|_| 42));
assert_eq!(
@ -279,7 +283,7 @@ mod tests {
// }
#[test]
fn create_and_execute_offset_command() {
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
let mut subject = CommandDispatcher::new();
subject.register(literal("foo").executes(|_| 42));
assert_eq!(
@ -300,7 +304,7 @@ mod tests {
// }
#[test]
fn create_and_merge_commands() {
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
let mut subject = CommandDispatcher::new();
subject.register(literal("base").then(literal("foo").executes(|_| 42)));
subject.register(literal("base").then(literal("bar").executes(|_| 42)));
@ -332,7 +336,7 @@ mod tests {
// }
#[test]
fn execute_unknown_command() {
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
let mut subject = CommandDispatcher::new();
subject.register(literal("bar"));
subject.register(literal("baz"));
@ -359,7 +363,7 @@ mod tests {
// }
#[test]
fn execute_impermissible_command() {
let mut subject = CommandDispatcher::<Rc<CommandSource>>::new();
let mut subject = CommandDispatcher::new();
subject.register(literal("foo").requires(|_| false));
let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
@ -371,4 +375,279 @@ mod tests {
}
assert_eq!(err.cursor().unwrap(), 0);
}
// @Test
// public void testExecuteEmptyCommand() throws Exception {
// subject.register(literal(""));
// try {
// subject.execute("", source);
// fail();
// } catch (final CommandSyntaxException ex) {
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand()));
// assertThat(ex.getCursor(), is(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
// public void testExecuteUnknownSubcommand() throws Exception {
// subject.register(literal("foo").executes(command));
// try {
// subject.execute("foo bar", source);
// fail();
// } catch (final CommandSyntaxException ex) {
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()));
// assertThat(ex.getCursor(), is(4));
// }
// }
#[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
// public void testExecuteIncorrectLiteral() throws Exception {
// subject.register(literal("foo").executes(command).then(literal("bar")));
// try {
// subject.execute("foo baz", source);
// fail();
// } catch (final CommandSyntaxException ex) {
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()));
// assertThat(ex.getCursor(), is(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
// public void testExecuteAmbiguousIncorrectArgument() throws Exception {
// subject.register(
// literal("foo").executes(command)
// .then(literal("bar"))
// .then(literal("baz"))
// );
// try {
// subject.execute("foo unknown", source);
// fail();
// } catch (final CommandSyntaxException ex) {
// assertThat(ex.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument()));
// assertThat(ex.getCursor(), is(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
// public void testExecuteSubcommand() throws Exception {
// final Command<Object> subCommand = mock(Command.class);
// when(subCommand.run(any())).thenReturn(100);
// subject.register(literal("foo").then(
// literal("a")
// ).then(
// literal("=").executes(subCommand)
// ).then(
// literal("c")
// ).executes(command));
// assertThat(subject.execute("foo =", source), is(100));
// verify(subCommand).run(any(CommandContext.class));
// }
#[test]
fn test_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
// public void testParseIncompleteLiteral() throws Exception {
// subject.register(literal("foo").then(literal("bar").executes(command)));
// final ParseResults<Object> parse = subject.parse("foo ", source);
// assertThat(parse.getReader().getRemaining(), equalTo(" "));
// assertThat(parse.getContext().getNodes().size(), is(1));
// }
#[test]
fn test_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
// public void testParseIncompleteArgument() throws Exception {
// subject.register(literal("foo").then(argument("bar", integer()).executes(command)));
// final ParseResults<Object> parse = subject.parse("foo ", source);
// assertThat(parse.getReader().getRemaining(), equalTo(" "));
// assertThat(parse.getContext().getNodes().size(), is(1));
// }
#[test]
fn test_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
// public void testExecuteAmbiguiousParentSubcommand() throws Exception {
// final Command<Object> subCommand = mock(Command.class);
// when(subCommand.run(any())).thenReturn(100);
// subject.register(
// literal("test")
// .then(
// argument("incorrect", integer())
// .executes(command)
// )
// .then(
// argument("right", integer())
// .then(
// argument("sub", integer())
// .executes(subCommand)
// )
// )
// );
// assertThat(subject.execute("test 1 2", source), is(100));
// verify(subCommand).run(any(CommandContext.class));
// verify(command, never()).run(any());
// }
#[test]
fn test_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
// public void testExecuteAmbiguiousParentSubcommandViaRedirect() throws Exception {
// final Command<Object> subCommand = mock(Command.class);
// when(subCommand.run(any())).thenReturn(100);
// final LiteralCommandNode<Object> real = subject.register(
// literal("test")
// .then(
// argument("incorrect", integer())
// .executes(command)
// )
// .then(
// argument("right", integer())
// .then(
// argument("sub", integer())
// .executes(subCommand)
// )
// )
// );
// subject.register(literal("redirect").redirect(real));
// assertThat(subject.execute("redirect 1 2", source), is(100));
// verify(subCommand).run(any(CommandContext.class));
// verify(command, never()).run(any());
// }
// #[test]
// fn test_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
// );
// }
}