diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 7d15cf0..ab02a05 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -187,7 +187,7 @@ pub trait CommandList(self, name: &'a CStr, desc: &'a CStr, handler: H) -> Command<'a, Self, H, T> + fn and<'a, H, T>(self, name: &'a CStr, desc: &'a CStr, handler: H) -> impl CommandList where H: FnMut(&mut stdio::Stdio, Args<'_>) -> T, T: crate::main::Termination, diff --git a/tests/shell/Cargo.toml b/tests/shell/Cargo.toml new file mode 100644 index 0000000..939fd3f --- /dev/null +++ b/tests/shell/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "riot-wrappers-test-shell" +version = "0.1.0" +authors = ["Christian Amsüss "] +edition = "2021" +publish = false + +[lib] +crate-type = ["staticlib"] + +[profile.release] +panic = "abort" + +[dependencies] +riot-wrappers = { path = "../..", features = [ "set_panic_handler", "panic_handler_format" ] } diff --git a/tests/shell/Makefile b/tests/shell/Makefile new file mode 100644 index 0000000..9e8cdd5 --- /dev/null +++ b/tests/shell/Makefile @@ -0,0 +1,10 @@ +# name of your application +APPLICATION = riot-wrappers-test-shell +BOARD ?= native +APPLICATION_RUST_MODULE = riot_wrappers_test_shell +BASELIBS += $(APPLICATION_RUST_MODULE).module +FEATURES_REQUIRED += rust_target + +USEMODULE += shell + +include $(RIOTBASE)/Makefile.include diff --git a/tests/shell/src/lib.rs b/tests/shell/src/lib.rs new file mode 100644 index 0000000..131871c --- /dev/null +++ b/tests/shell/src/lib.rs @@ -0,0 +1,40 @@ +#![no_std] + +use core::fmt::Write; +use riot_wrappers::println; +use riot_wrappers::riot_main; +use riot_wrappers::shell::CommandList; + +riot_main!(main); + +fn main() -> ! { + let mut nonglobal_state = 0; + + // Not running anything fancy with run_once (where we could, for example, play around with + // different buffer sizes) because . + + riot_wrappers::shell::new() + .and( + c"closure", + c"Run a command that holds a mutable reference", + |stdout, _args| { + writeln!(stdout, "Previous state was {}", nonglobal_state).unwrap(); + nonglobal_state += 1; + writeln!(stdout, "New state is {}", nonglobal_state).unwrap(); + }, + ) + .run_forever() +} + +fn do_echo(_stdio: &mut riot_wrappers::stdio::Stdio, args: riot_wrappers::shell::Args<'_>) { + println!("Arguments:"); + for a in args.iter() { + println!("- {}", a); + } +} +riot_wrappers::static_command!( + echo, + "echo", + "Print the arguments in separate lines", + do_echo +); diff --git a/tests/shell/tests/01-run.py b/tests/shell/tests/01-run.py new file mode 100755 index 0000000..bf79803 --- /dev/null +++ b/tests/shell/tests/01-run.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import sys +from testrunner import run + +def test(child): + child.expect("> ") + child.sendline("help") + # Could also be the other sequence, we're not guaranteeing that + commands = ["closure", "echo"] + helps = ["Run a command that holds a mutable reference", "Print the arguments in separate lines"] + command1 = child.expect(commands) + help1 = child.expect(helps) + command2 = child.expect(commands) + help2 = child.expect(helps) + if command1 != help1 or command2 != help2: + print("Commands and helps were mixed up") + sys.exit(1) + child.expect("> ") + child.sendline("echo foo bar") + child.expect("- echo") + child.expect("- foo") + child.expect("- bar") + child.expect("> ") + child.sendline("closure") + child.expect("New state is 1") + child.expect("> ") + child.sendline("closure") + child.expect("New state is 2") + +if __name__ == "__main__": + sys.exit(run(test))