Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Boris Zhguchev committed Sep 3, 2023
1 parent 74b369b commit 3d7bac8
Show file tree
Hide file tree
Showing 14 changed files with 6,371 additions and 60 deletions.
2 changes: 1 addition & 1 deletion src/runtime/action/builtin/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ mod tests {
assert_eq!(r, Ok(TickResult::success()));

assert_eq!(
bb.clone().lock().unwrap().get("k".to_string()),
bb.lock().unwrap().get("k".to_string()),
Ok(Some(&RtValue::str("OK".to_string())))
);
}
Expand Down
1 change: 1 addition & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod actions_re;
mod args;
mod decorator;
mod flow;
mod parser;
mod project;
mod rtree;
mod simulator;
Expand Down
12 changes: 7 additions & 5 deletions src/tests/actions.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use crate::runtime::action::builtin::remote::RemoteHttpAction;
use crate::runtime::args::RtValue;
use crate::runtime::env::RtEnv;
use crate::runtime::TickResult;
use crate::tests::fb;
use serde_json::json;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};

#[test]
fn builtin_actions() {
Expand All @@ -27,3 +22,10 @@ fn lock_unlock() {
let k = guard.get("k".to_string()).unwrap();
assert_eq!(k, Some(&RtValue::str("v2".to_string())))
}

#[test]
fn builtin_http_get() {
let mut fb = fb("actions/simple_http");
let mut f = fb.build().unwrap();
assert_eq!(f.run(), Ok(TickResult::success()));
}
54 changes: 28 additions & 26 deletions src/tests/actions_re.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn smoke_serv() {

let rt = RtEnv::try_new().unwrap().runtime;

let info = start(&rt, ServerPort::Static(9999), bb.clone(), tr.clone()).unwrap();
let info = start(&rt, ServerPort::Static(20000), bb.clone(), tr.clone()).unwrap();
let stop = info.stop_cmd;

rt.spawn(async {
Expand All @@ -39,8 +39,24 @@ fn smoke_serv() {
#[test]
fn remote_smoke() {
turn_on_logs();
let action = RemoteHttpAction::new("http://localhost:10000/action".to_string());
let mut env = RtEnv::try_new().unwrap();

let port = env.runtime.block_on(async {
let mock_server = MockServer::start().await;

let mut resp = ResponseTemplate::new(200);
let resp = resp.set_body_json(json!("Success"));

Mock::given(method("POST"))
.and(path("/action"))
.respond_with(resp)
.mount(&mock_server)
.await;
mock_server.address().port()
});

let action = RemoteHttpAction::new(format!("http://localhost:{}/action", port));

let result = action.tick(
RtArgs(vec![
RtArgument::new("a".to_string(), RtValue::int(1)),
Expand All @@ -53,31 +69,13 @@ fn remote_smoke() {
TreeRemoteContextRef::new(1, 9999, &mut env),
);

println!("{:?}", result);
assert_eq!(result, Ok(TickResult::success()));
}

#[test]
fn remote_serv() {
fn remote_in_tree() {
turn_on_logs();

let mut builder = fb("actions/remote");

builder.tracer(Tracer::default());

let action = RemoteHttpAction::new("http://localhost:10001/action".to_string());
builder.register_remote_action("action", action);
builder.http_serv(9999);
let mut f = builder.build().unwrap();

let result = f.run();

println!("{:?}", result);
}

#[test]
fn remote() {
let mut env = RtEnv::try_new().unwrap();

let port = env.runtime.block_on(async {
let mock_server = MockServer::start().await;

Expand All @@ -92,12 +90,16 @@ fn remote() {
mock_server.address().port()
});

let mut builder = fb("actions/remote");
builder.rt_env(env);
builder.tracer(Tracer::default());

let action = RemoteHttpAction::new(format!("http://localhost:{}/action", port));
let mut fb = fb("actions/simple_http");
fb.rt_env(env);
fb.register_remote_action("a", action);
builder.register_remote_action("action", action);
builder.http_serv(9999);
let mut f = builder.build().unwrap();

let mut f = fb.build().unwrap();
let result = f.run();

assert_eq!(result, Ok(TickResult::success()));
}
12 changes: 12 additions & 0 deletions src/tests/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::tests::test_folder;
use crate::tree::parser::Parser;
use std::fs;

#[test]
fn smoke() {
let path = test_folder("plain_project/main.tree");
let scr = fs::read_to_string(path).unwrap();
let parser = Parser::new(scr.as_str()).unwrap();
let result = parser.parse().unwrap();
println!("{:#?}", result);
}
17 changes: 17 additions & 0 deletions src/tree/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ use parsit::{seq, token, wrap};
use std::collections::HashMap;
use std::str::FromStr;

/// just a parser for the tree language
///
/// # Example of the language
/// ```tree
/// // built in library
/// import "std:actions"
///
/// r_fallback retry_with_delay(delay:num, attempts:num,trg:tree){
/// retry(attempts) fallback {
/// trg(..)
/// wait(delay)
/// fail()
/// }
/// wait(delay)
/// }
/// ```

pub struct Parser<'a> {
inner: Parsit<'a, Token>,
}
Expand Down
12 changes: 12 additions & 0 deletions src/tree/parser/ast/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};

/// Just a pair of name and type
/// This is a representation of a tree parameter
/// # Example
/// `sequence tree(a:string){...}`
/// and a:string is a param
#[derive(Clone, Debug, PartialEq)]
pub struct Param {
pub name: Key,
Expand All @@ -33,10 +38,14 @@ impl Params {
}
}

/// The right part of the argument
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum ArgumentRhs {
/// A pointer to the bb key or the parameter from the parent tree
Id(Key),
/// A scalar value
Mes(Message),
/// A call to a tree
Call(Call),
}

Expand Down Expand Up @@ -72,6 +81,7 @@ impl Display for ArgumentRhs {
}
}

/// An argument is a pair of name and value or just a value
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum Argument {
Assigned(Key, ArgumentRhs),
Expand Down Expand Up @@ -132,6 +142,8 @@ pub struct Arguments {
pub args: Vec<Argument>,
}

/// this is a plain representation of the argument type
/// to avoid several levels of nesting
pub enum ArgumentsType {
Unnamed,
Named,
Expand Down
33 changes: 32 additions & 1 deletion src/tree/parser/ast/call.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
use crate::tree::parser::ast::arg::Arguments;
use crate::tree::parser::ast::{Key, TreeType};
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display, Formatter};

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
/// A call to a tree
#[derive(Clone, PartialEq, Deserialize, Serialize)]
pub enum Call {
/// An invocation of a tree like 'root main { invocation()}'
Invocation(Key, Arguments),
/// An Higher order invocation of a tree like 'root main { ho-invocation(..)}'
HoInvocation(Key),
/// A lambda call like 'root main { sequence {...} }'
Lambda(TreeType, Calls),
/// A decorator call like 'root main { decorator(..) child() }'
Decorator(TreeType, Arguments, Box<Call>),
}

impl Debug for Call {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Call::Invocation(id, args) => write!(f, "{}({})", id, args),
Call::HoInvocation(id) => write!(f, "{}(..)", id),
Call::Lambda(tpe, calls) => {
let _ = write!(f, "{} :", tpe);
let mut elems = f.debug_list();
for call in calls.elems.iter() {
elems.entry(call);
}
let _ = elems.finish();
Ok(())
}
Call::Decorator(tpe, args, call) => {
let _ = write!(f, "{}({}) :", tpe, args);
let mut elems = f.debug_list();
elems.entry(call);
elems.finish();
Ok(())
}
}
}
}

impl Call {
pub fn is_lambda(&self) -> bool {
matches!(self, Call::Lambda(_, _))
Expand Down
4 changes: 4 additions & 0 deletions src/tree/parser/ast/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::{Display, Formatter};

/// A gathering structure for numeric scalar values
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
pub enum Number {
Int(i64),
Expand All @@ -11,9 +12,11 @@ pub enum Number {
Binary(isize),
}

/// A gathering structure for string scalar values
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct StringLit(pub String);

/// A gathering structure for boolean scalar values
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub enum Bool {
True,
Expand All @@ -29,6 +32,7 @@ impl Into<bool> for Bool {
}
}

/// A gathering structure for scalar values
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub enum Message {
Num(Number),
Expand Down
30 changes: 3 additions & 27 deletions src/tree/parser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,13 @@ mod params;

#[cfg(test)]
mod tests {
use crate::tree::parser::ast::arg::{Argument, Arguments};
use crate::tree::parser::ast::call::Call;
use crate::tree::parser::ast::message::{Bool, Message, Number, StringLit};
use crate::tree::parser::ast::Key;
use crate::tree::parser::Parser;
use parsit::test::parser_test::*;
use std::fs;
use std::path::PathBuf;

pub fn load_file(path: &str) -> String {
let mut ex = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
for next in path.split("/") {
match next {
".." => ex = ex.parent().unwrap().into(),
n => ex.push(n),
}
}
fs::read_to_string(ex).unwrap()
}

#[test]
fn smoke() {
let script = load_file("tree/tests/plain_project/main.tree");
let parser = Parser::new(script.as_str()).unwrap();
let result = parser.parse().unwrap();
}

#[test]
fn script() {
let script = r#"
import "std:actions"
// built in library
import "std:actions"
r_fallback retry_with_delay(delay:num, attempts:num,trg:tree){
retry(attempts) fallback {
trg(..)
Expand Down Expand Up @@ -109,5 +84,6 @@ root main r_fallback {

let parser = Parser::new(script).unwrap();
let result = parser.parse().unwrap();
assert_eq!(result.0.len(), 12);
}
}
20 changes: 20 additions & 0 deletions src/tree/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub type AliasName = String;
/// - `root` is a root of the project. Every import relates to it.
/// - `main` is a pointer to the file and definition when the tree is started.
/// - `files` is a map of the files
/// - `std` is a set of the standard actions
#[derive(Debug, Default, Clone)]
pub struct Project {
pub root: PathBuf,
Expand All @@ -45,6 +46,16 @@ impl<'a> Project {
self.files.get(file).and_then(|f| f.definitions.get(tree))
}

/// build the project with the given root and main file
///
/// Suppose we have the following structure:
/// ```no-run
/// - root_folder
/// - folder
/// - main.tree # root tree_name
/// - other.tree
/// ```
/// Setting up the rooot as root_folder allows pulling in the other.tree file.
pub fn build_with_root(
main_file: FileName,
main_call: TreeName,
Expand All @@ -65,6 +76,9 @@ impl<'a> Project {
project.parse_file(root, main_file)?;
Ok(project)
}
/// build the project with the given main file and root.
/// The root will be found in the main file.
/// If there are more than one root in the main file, the first one will be used.
pub fn build(main_file: FileName, root: PathBuf) -> Result<Project, TreeError> {
let mut project = Project {
root: root.clone(),
Expand Down Expand Up @@ -92,6 +106,12 @@ impl<'a> Project {
project.main = (main_file, main_call);
Ok(project)
}
/// build the project with the given text.
/// The root will be empty.
///
/// # Note
/// If there are some imports to the other files they will not work
/// unless the imports are absolute,
pub fn build_from_text(text: String) -> Result<Project, TreeError> {
let mut project = Project {
root: PathBuf::new(),
Expand Down
Loading

0 comments on commit 3d7bac8

Please sign in to comment.