2020-03-22 03:18:16 +01:00
|
|
|
///! This test simulates an external command object that is driven by a script.
|
2021-03-15 04:36:30 +01:00
|
|
|
use rhai::{Engine, EvalAltResult, Scope, INT};
|
2020-06-22 03:46:36 +02:00
|
|
|
use std::sync::{Arc, Mutex, RwLock};
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-06-22 03:46:36 +02:00
|
|
|
/// Simulate a command object.
|
2020-03-22 03:18:16 +01:00
|
|
|
struct Command {
|
2020-06-22 03:46:36 +02:00
|
|
|
/// Simulate an external state.
|
2020-08-05 18:24:25 +02:00
|
|
|
state: INT,
|
2020-03-22 03:18:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Command {
|
|
|
|
/// Do some action.
|
2020-08-05 18:24:25 +02:00
|
|
|
pub fn action(&mut self, val: INT) {
|
2020-03-22 03:18:16 +01:00
|
|
|
self.state = val;
|
|
|
|
}
|
|
|
|
/// Get current value.
|
2020-08-05 18:24:25 +02:00
|
|
|
pub fn get(&self) -> INT {
|
2020-03-22 03:18:16 +01:00
|
|
|
self.state
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-30 18:07:39 +01:00
|
|
|
#[allow(clippy::upper_case_acronyms)]
|
2020-06-22 03:46:36 +02:00
|
|
|
type API = Arc<Mutex<Command>>;
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-04-07 07:23:06 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-03-20 12:27:02 +01:00
|
|
|
#[test]
|
2020-04-21 17:25:12 +02:00
|
|
|
fn test_side_effects_command() -> Result<(), Box<EvalAltResult>> {
|
2020-03-20 12:27:02 +01:00
|
|
|
let mut engine = Engine::new();
|
|
|
|
let mut scope = Scope::new();
|
|
|
|
|
2020-06-21 18:03:45 +02:00
|
|
|
// Create the command object with initial state, handled by an `Arc`.
|
2020-04-02 13:40:02 +02:00
|
|
|
let command = Arc::new(Mutex::new(Command { state: 12 }));
|
|
|
|
assert_eq!(command.lock().unwrap().get(), 12);
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-06-22 03:46:36 +02:00
|
|
|
// Create the API object.
|
|
|
|
let api = command.clone(); // Notice this clones the `Arc` only
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-06-22 03:46:36 +02:00
|
|
|
// Make the API object a singleton in the script environment.
|
|
|
|
scope.push_constant("Command", api);
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-03-22 03:18:16 +01:00
|
|
|
// Register type.
|
2020-06-22 03:46:36 +02:00
|
|
|
engine.register_type_with_name::<API>("CommandType");
|
2020-08-05 18:24:25 +02:00
|
|
|
engine.register_fn("action", |api: &mut API, x: INT| {
|
2020-06-22 03:46:36 +02:00
|
|
|
let mut command = api.lock().unwrap();
|
|
|
|
let val = command.get();
|
|
|
|
command.action(val + x);
|
|
|
|
});
|
|
|
|
engine.register_get("value", |command: &mut API| command.lock().unwrap().get());
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-03-22 03:18:16 +01:00
|
|
|
assert_eq!(
|
|
|
|
engine.eval_with_scope::<INT>(
|
|
|
|
&mut scope,
|
2021-04-20 06:01:35 +02:00
|
|
|
"
|
2020-03-22 03:18:16 +01:00
|
|
|
// Drive the command object via the wrapper
|
|
|
|
Command.action(30);
|
|
|
|
Command.value
|
|
|
|
"
|
|
|
|
)?,
|
|
|
|
42
|
|
|
|
);
|
2020-03-20 12:27:02 +01:00
|
|
|
|
2020-03-22 03:18:16 +01:00
|
|
|
// Make sure the actions are properly performed
|
2020-04-02 13:40:02 +02:00
|
|
|
assert_eq!(command.lock().unwrap().get(), 42);
|
2020-03-20 12:27:02 +01:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-04-07 07:23:06 +02:00
|
|
|
|
|
|
|
#[test]
|
2020-04-21 17:25:12 +02:00
|
|
|
fn test_side_effects_print() -> Result<(), Box<EvalAltResult>> {
|
2021-02-26 04:21:05 +01:00
|
|
|
let result = Arc::new(RwLock::new(String::new()));
|
2020-04-07 07:23:06 +02:00
|
|
|
|
2020-04-16 17:31:48 +02:00
|
|
|
let mut engine = Engine::new();
|
2020-04-07 07:23:06 +02:00
|
|
|
|
2020-04-16 17:31:48 +02:00
|
|
|
// Override action of 'print' function
|
|
|
|
let logger = result.clone();
|
|
|
|
engine.on_print(move |s| logger.write().unwrap().push_str(s));
|
2020-04-07 07:23:06 +02:00
|
|
|
|
2021-08-06 08:46:27 +02:00
|
|
|
engine.run("print(40 + 2);")?;
|
2020-04-07 07:23:06 +02:00
|
|
|
|
|
|
|
assert_eq!(*result.read().unwrap(), "42");
|
|
|
|
Ok(())
|
|
|
|
}
|