use super::*;
use crate::models::duration::OneOfDurationOrIso8601Expression;
use crate::models::error::OneOfErrorDefinitionOrReference;
use crate::models::retry::OneOfRetryPolicyDefinitionOrReference;
#[test]
fn test_set_task_deserialize() {
let json = r#"{
"set": {"key1": "value1", "key2": 42}
}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
match &task.set {
SetValue::Map(map) => {
assert_eq!(map.get("key1").unwrap(), "value1");
assert_eq!(map.get("key2").unwrap(), 42);
}
_ => panic!("Expected Map variant"),
}
}
#[test]
fn test_set_task_expression() {
let json = r#"{"set": "${ .items }"}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
match &task.set {
SetValue::Expression(expr) => assert_eq!(expr, "${ .items }"),
_ => panic!("Expected Expression variant"),
}
}
#[test]
fn test_set_task_with_common_fields() {
let json = r#"{
"set": {"result": "done"},
"if": "${ .enabled }",
"then": "continue",
"output": {"as": {"transformed": true}}
}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${ .enabled }"));
assert_eq!(task.common.then.as_deref(), Some("continue"));
assert!(task.common.output.is_some());
}
#[test]
fn test_set_task_roundtrip() {
let json = r#"{"set": {"key1": "value1", "key2": 42}}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: SetTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_do_task_deserialize() {
let json = r#"{
"do": [
{"step1": {"set": {"a": 1}}},
{"step2": {"set": {"b": 2}}}
]
}"#;
let task: DoTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.do_.entries.len(), 2);
assert!(task.do_.contains_key(&"step1".to_string()));
assert!(task.do_.contains_key(&"step2".to_string()));
}
#[test]
fn test_do_task_roundtrip() {
let json = r#"{"do": [{"step1": {"set": {"a": 1}}}]}"#;
let task: DoTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: DoTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_for_task_deserialize() {
let json = r#"{
"for": {"each": "item", "in": "${ .items }", "at": "index"},
"while": "${ .hasMore }",
"do": [{"processItem": {"set": {"result": "done"}}}]
}"#;
let task: ForTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.for_.each, "item");
assert_eq!(task.for_.in_, "${ .items }");
assert_eq!(task.for_.at.as_deref(), Some("index"));
assert_eq!(task.while_.as_deref(), Some("${ .hasMore }"));
assert!(task.do_.contains_key(&"processItem".to_string()));
}
#[test]
fn test_for_task_minimal() {
let json = r#"{
"for": {"each": "item", "in": "${ .items }"},
"do": [{"step": {"set": {"x": 1}}}]
}"#;
let task: ForTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.for_.each, "item");
assert!(task.for_.at.is_none());
assert!(task.while_.is_none());
}
#[test]
fn test_for_task_roundtrip() {
let json = r#"{
"for": {"each": "item", "in": "${ .items }", "at": "idx"},
"do": [{"step": {"set": {"x": 1}}}]
}"#;
let task: ForTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: ForTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_fork_task_deserialize() {
let json = r#"{
"fork": {
"branches": [
{"branch1": {"set": {"a": 1}}},
{"branch2": {"set": {"b": 2}}}
],
"compete": true
}
}"#;
let task: ForkTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.fork.compete);
assert_eq!(task.fork.branches.entries.len(), 2);
}
#[test]
fn test_fork_task_no_compete() {
let json = r#"{
"fork": {
"branches": [
{"branch1": {"set": {"a": 1}}},
{"branch2": {"set": {"b": 2}}}
],
"compete": false
}
}"#;
let task: ForkTaskDefinition = serde_json::from_str(json).unwrap();
assert!(!task.fork.compete);
}
#[test]
fn test_fork_task_roundtrip() {
let json = r#"{
"fork": {
"branches": [{"b1": {"set": {"x": 1}}}],
"compete": true
}
}"#;
let task: ForkTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: ForkTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_switch_task_deserialize() {
let json = r#"{
"switch": [
{"case1": {"when": ".color == \"red\"", "then": "setRed"}},
{"case2": {"when": ".color == \"green\"", "then": "setGreen"}}
]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.switch.entries.len(), 2);
let (name, case1) = &task.switch.entries[0];
assert_eq!(name, "case1");
assert_eq!(case1.when.as_deref(), Some(".color == \"red\""));
assert_eq!(case1.then.as_deref(), Some("setRed"));
}
#[test]
fn test_switch_task_default_case() {
let json = r#"{
"switch": [
{"red": {"when": ".color == \"red\"", "then": "setRed"}},
{"fallback": {"then": "setDefault"}}
]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
let (name, fallback) = &task.switch.entries[1];
assert_eq!(name, "fallback");
assert!(fallback.when.is_none());
assert_eq!(fallback.then.as_deref(), Some("setDefault"));
}
#[test]
fn test_switch_task_roundtrip() {
let json = r#"{
"switch": [{"case1": {"when": ".x > 0", "then": "end"}}]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: SwitchTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_raise_task_deserialize() {
let json = r#"{
"raise": {
"error": {
"type": "http://example.com/error",
"status": 500,
"title": "Internal Server Error",
"detail": "An unexpected error occurred."
}
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
match &task.raise.error {
crate::models::error::OneOfErrorDefinitionOrReference::Error(err) => {
assert_eq!(err.type_.as_str(), "http://example.com/error");
assert_eq!(err.status, serde_json::json!(500));
assert_eq!(err.title, Some("Internal Server Error".to_string()));
assert_eq!(
err.detail,
Some("An unexpected error occurred.".to_string())
);
}
_ => panic!("Expected Error variant"),
}
}
#[test]
fn test_raise_task_with_reference() {
let json = r#"{
"raise": {
"error": "authError"
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
match &task.raise.error {
crate::models::error::OneOfErrorDefinitionOrReference::Reference(name) => {
assert_eq!(name, "authError");
}
_ => panic!("Expected Reference variant"),
}
}
#[test]
fn test_raise_task_roundtrip() {
let json = r#"{
"raise": {
"error": {
"type": "http://example.com/error",
"status": 500,
"title": "Error"
}
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RaiseTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_task_shell_deserialize() {
let json = r#"{
"run": {
"shell": {
"command": "echo",
"arguments": {"msg": "hello"},
"environment": {"HOME": "/tmp"}
},
"await": false
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.run.shell.is_some());
assert_eq!(task.run.await_, Some(false));
let shell = task.run.shell.as_ref().unwrap();
assert_eq!(shell.command, "echo");
assert!(shell.arguments.is_some());
assert!(shell.environment.is_some());
}
#[test]
fn test_run_task_container_deserialize() {
let json = r#"{
"run": {
"container": {
"image": "example-image",
"name": "example-name",
"command": "example-command",
"environment": {"ENV_VAR": "value"},
"arguments": ["arg1", "arg2"],
"pullPolicy": "always",
"lifetime": {
"cleanup": "eventually",
"after": {"seconds": 20}
}
},
"await": true
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let container = task.run.container.as_ref().unwrap();
assert_eq!(container.image, "example-image");
assert_eq!(container.name.as_deref(), Some("example-name"));
assert_eq!(container.command.as_deref(), Some("example-command"));
assert_eq!(container.pull_policy.as_deref(), Some("always"));
assert!(container.lifetime.is_some());
let lifetime = container.lifetime.as_ref().unwrap();
assert_eq!(lifetime.cleanup, "eventually");
assert!(lifetime.after.is_some());
}
#[test]
fn test_run_task_script_deserialize() {
let json = r#"{
"run": {
"script": {
"language": "python",
"code": "print('Hello')",
"arguments": ["arg1=value1"],
"environment": {"ENV_VAR": "value"},
"stdin": "example-input"
},
"await": true
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let script = task.run.script.as_ref().unwrap();
assert_eq!(script.language, "python");
assert_eq!(script.code.as_deref(), Some("print('Hello')"));
assert_eq!(script.stdin.as_deref(), Some("example-input"));
}
#[test]
fn test_run_task_roundtrip() {
let json = r#"{
"run": {
"shell": {"command": "ls"},
"await": true
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_wait_task_iso8601_deserialize() {
let json = r#"{"wait": "PT1S"}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
match &task.wait {
crate::models::duration::OneOfDurationOrIso8601Expression::Iso8601Expression(expr) => {
assert_eq!(expr, "PT1S");
}
_ => panic!("Expected Iso8601Expression variant"),
}
}
#[test]
fn test_wait_task_inline_duration_deserialize() {
let json = r#"{"wait": {"milliseconds": 25}}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
match &task.wait {
crate::models::duration::OneOfDurationOrIso8601Expression::Duration(d) => {
assert_eq!(d.milliseconds, Some(25));
}
_ => panic!("Expected Duration variant"),
}
}
#[test]
fn test_wait_task_with_common_fields() {
let json = r#"{
"wait": "PT1S",
"if": "${ .shouldWait }",
"then": "continue",
"output": {"as": {"waited": true}}
}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${ .shouldWait }"));
assert_eq!(task.common.then.as_deref(), Some("continue"));
assert!(task.common.output.is_some());
}
#[test]
fn test_wait_task_roundtrip() {
let json = r#"{"wait": "PT1S"}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: WaitTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_try_task_deserialize() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"errors": {"with": {"type": "https://example.com/errors/work"}},
"as": "error",
"do": [{"handleError": {"set": {"handled": true}}}]
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.try_.contains_key(&"doWork".to_string()));
assert!(task.catch.errors.is_some());
assert_eq!(task.catch.as_.as_deref(), Some("error"));
assert!(task.catch.do_.is_some());
}
#[test]
fn test_try_task_with_retry() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"retry": {
"delay": {"seconds": 3},
"limit": {"attempt": {"count": 5}}
}
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.catch.retry.is_some());
}
#[test]
fn test_try_task_with_when() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"when": "${ .error.status >= 500 }",
"do": [{"handleError": {"set": {"handled": true}}}]
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(
task.catch.when.as_deref(),
Some("${ .error.status >= 500 }")
);
}
#[test]
fn test_try_task_roundtrip() {
let json = r#"{
"try": [{"step": {"set": {"x": 1}}}],
"catch": {
"as": "err",
"do": [{"handle": {"set": {"ok": true}}}]
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: TryTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_flow_directive_enumerated() {
let json = r#""continue""#;
let fd: FlowDirectiveValue = serde_json::from_str(json).unwrap();
assert!(fd.is_enumerated());
assert!(!fd.is_termination());
}
#[test]
fn test_flow_directive_end() {
let json = r#""end""#;
let fd: FlowDirectiveValue = serde_json::from_str(json).unwrap();
assert!(fd.is_enumerated());
assert!(fd.is_termination());
}
#[test]
fn test_flow_directive_custom() {
let json = r#""someTaskName""#;
let fd: FlowDirectiveValue = serde_json::from_str(json).unwrap();
assert!(!fd.is_enumerated());
assert!(!fd.is_termination());
match fd {
FlowDirectiveValue::Custom(s) => assert_eq!(s, "someTaskName"),
_ => panic!("Expected Custom variant"),
}
}
#[test]
fn test_flow_directive_roundtrip() {
let fd = FlowDirectiveValue::Enumerated(FlowDirectiveType::Exit);
let serialized = serde_json::to_string(&fd).unwrap();
let deserialized: FlowDirectiveValue = serde_json::from_str(&serialized).unwrap();
assert_eq!(fd, deserialized);
}
#[test]
fn test_task_definition_set_dispatch() {
let json = r#"{"set": {"key": "value"}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Set(_)));
}
#[test]
fn test_task_definition_do_dispatch() {
let json = r#"{"do": [{"step": {"set": {"x": 1}}}]}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Do(_)));
}
#[test]
fn test_task_definition_for_dispatch() {
let json = r#"{"for": {"each": "i", "in": ".items"}, "do": [{"step": {"set": {"x": 1}}}]}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::For(_)));
}
#[test]
fn test_task_definition_fork_dispatch() {
let json = r#"{"fork": {"branches": [{"b": {"set": {"x": 1}}}], "compete": false}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Fork(_)));
}
#[test]
fn test_task_definition_switch_dispatch() {
let json = r#"{"switch": [{"c1": {"when": ".x > 0", "then": "end"}}]}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Switch(_)));
}
#[test]
fn test_task_definition_raise_dispatch() {
let json = r#"{"raise": {"error": "someError"}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Raise(_)));
}
#[test]
fn test_task_definition_wait_dispatch() {
let json = r#"{"wait": "PT1S"}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Wait(_)));
}
#[test]
fn test_task_definition_try_dispatch() {
let json = r#"{"try": [{"step": {"set": {"x": 1}}}], "catch": {}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Try(_)));
}
#[test]
fn test_task_definition_run_dispatch() {
let json = r#"{"run": {"shell": {"command": "ls"}}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Run(_)));
}
#[test]
fn test_task_definition_call_dispatch() {
let json = r#"{"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Call(_)));
}
#[test]
fn test_task_definition_emit_dispatch() {
let json = r#"{"emit": {"event": {"type": "test.event"}}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Emit(_)));
}
#[test]
fn test_task_definition_listen_dispatch() {
let json = r#"{"listen": {"to": {"one": {"with": {"type": "test.event"}}}}}"#;
let task: TaskDefinition = serde_json::from_str(json).unwrap();
assert!(matches!(task, TaskDefinition::Listen(_)));
}
#[test]
fn test_emit_task_deserialize() {
let json = r#"{"emit": {"event": {"type": "test.event", "source": "test-source"}}}"#;
let task: EmitTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.emit.event.type_, Some("test.event".to_string()));
}
#[test]
fn test_emit_task_roundtrip() {
let json = r#"{"emit": {"event": {"type": "test.event"}}}"#;
let task: EmitTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: EmitTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_listen_task_deserialize() {
let json = r#"{"listen": {"to": {"one": {"with": {"type": "test.event"}}}}}"#;
let task: ListenTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.listen.to.one.is_some());
let one = task.listen.to.one.as_ref().unwrap();
assert!(one.with.is_some());
}
#[test]
fn test_listen_task_roundtrip() {
let json = r#"{"listen": {"to": {"one": {"with": {"type": "test.event"}}}}}"#;
let task: ListenTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: ListenTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_container_process_deserialize() {
let json = r#"{
"image": "nginx:latest",
"name": "web-server",
"command": "nginx",
"ports": {"80": 8080},
"environment": {"HOST": "0.0.0.0"},
"arguments": ["-g", "daemon off"],
"pullPolicy": "always",
"lifetime": {"cleanup": "eventually", "after": {"minutes": 30}}
}"#;
let container: ContainerProcessDefinition = serde_json::from_str(json).unwrap();
assert_eq!(container.image, "nginx:latest");
assert_eq!(container.name.as_deref(), Some("web-server"));
assert_eq!(container.pull_policy.as_deref(), Some("always"));
assert!(container.lifetime.is_some());
let lifetime = container.lifetime.as_ref().unwrap();
assert_eq!(lifetime.cleanup, "eventually");
}
#[test]
fn test_container_process_roundtrip() {
let json = r#"{"image": "nginx", "name": "web"}"#;
let container: ContainerProcessDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&container).unwrap();
let deserialized: ContainerProcessDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(container, deserialized);
}
#[test]
fn test_shell_process_deserialize() {
let json = r#"{
"command": "echo",
"arguments": {"msg": "hello"},
"environment": {"HOME": "/tmp"}
}"#;
let shell: ShellProcessDefinition = serde_json::from_str(json).unwrap();
assert_eq!(shell.command, "echo");
assert!(shell.arguments.is_some());
assert!(shell.arguments.as_ref().unwrap().is_map());
let map = shell.arguments.as_ref().unwrap().as_map().unwrap();
assert_eq!(map.get("msg").unwrap(), &Value::String("hello".to_string()));
assert!(shell.environment.is_some());
}
#[test]
fn test_shell_process_array_args_deserialize() {
let json = r#"{
"command": "echo",
"arguments": ["arg1=value1", "arg2=value2"]
}"#;
let shell: ShellProcessDefinition = serde_json::from_str(json).unwrap();
assert_eq!(shell.command, "echo");
assert!(shell.arguments.is_some());
assert!(shell.arguments.as_ref().unwrap().is_array());
let arr = shell.arguments.as_ref().unwrap().as_array().unwrap();
assert_eq!(arr.len(), 2);
assert_eq!(arr[0], "arg1=value1");
assert_eq!(arr[1], "arg2=value2");
}
#[test]
fn test_shell_process_roundtrip() {
let json = r#"{
"command": "echo",
"arguments": {"msg": "hello"},
"environment": {"HOME": "/tmp"}
}"#;
let shell: ShellProcessDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&shell).unwrap();
let deserialized: ShellProcessDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(shell, deserialized);
}
#[test]
fn test_shell_process_array_args_roundtrip() {
let json = r#"{
"command": "echo",
"arguments": ["arg1=value1", "arg2"]
}"#;
let shell: ShellProcessDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&shell).unwrap();
let deserialized: ShellProcessDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(shell, deserialized);
}
#[test]
fn test_error_catcher_deserialize() {
let json = r#"{
"errors": {"with": {"type": "https://example.com/errors/work", "status": 500}},
"as": "err",
"when": "${ .err.status >= 500 }",
"exceptWhen": "${ .err.type == \"https://example.com/ignore\" }",
"do": [{"handleError": {"set": {"handled": true}}}]
}"#;
let catcher: ErrorCatcherDefinition = serde_json::from_str(json).unwrap();
assert!(catcher.errors.is_some());
assert_eq!(catcher.as_.as_deref(), Some("err"));
assert!(catcher.when.is_some());
assert!(catcher.except_when.is_some());
assert!(catcher.do_.is_some());
}
#[test]
fn test_error_filter_deserialize() {
let json = r#"{
"with": {
"type": "https://example.com/errors/auth",
"status": 401,
"title": "Unauthorized",
"detail": "Token expired",
"instance": "/auth/login"
}
}"#;
let filter: ErrorFilterDefinition = serde_json::from_str(json).unwrap();
let props = filter.with.as_ref().unwrap();
assert_eq!(
props.type_.as_deref(),
Some("https://example.com/errors/auth")
);
assert_eq!(props.status, Some(serde_json::json!(401)));
assert_eq!(props.title.as_deref(), Some("Unauthorized"));
}
#[test]
fn test_subscription_iterator_deserialize() {
let json = r#"{
"item": "event",
"at": "index",
"do": [{"processEvent": {"set": {"processed": true}}}],
"output": {"as": {"result": "ok"}}
}"#;
let iter: SubscriptionIteratorDefinition = serde_json::from_str(json).unwrap();
assert_eq!(iter.item.as_deref(), Some("event"));
assert_eq!(iter.at.as_deref(), Some("index"));
assert!(iter.do_.is_some());
assert!(iter.output.is_some());
}
#[test]
fn test_set_value_map() {
let json = r#"{"key1": "value1", "key2": 42}"#;
let sv: SetValue = serde_json::from_str(json).unwrap();
match sv {
SetValue::Map(map) => {
assert_eq!(map.len(), 2);
assert_eq!(map.get("key1").unwrap(), "value1");
}
_ => panic!("Expected Map variant"),
}
}
#[test]
fn test_set_value_expression() {
let json = r#""${ .items }""#;
let sv: SetValue = serde_json::from_str(json).unwrap();
match sv {
SetValue::Expression(expr) => assert_eq!(expr, "${ .items }"),
_ => panic!("Expected Expression variant"),
}
}
#[test]
fn test_run_arguments_array_deserialize() {
let json = r#"{
"run": {
"await": true,
"script": {
"language": "python",
"arguments": ["arg1=value1", "arg2"],
"environment": {"ENV_VAR": "value"},
"code": "print('Hello, World!')",
"stdin": "example-input"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let script = task.run.script.as_ref().unwrap();
assert_eq!(script.language, "python");
assert!(script.arguments.is_some());
let args = script.arguments.as_ref().unwrap();
assert!(args.is_array());
assert_eq!(args.as_array().unwrap(), &["arg1=value1", "arg2"]);
assert_eq!(script.code.as_deref(), Some("print('Hello, World!')"));
}
#[test]
fn test_run_arguments_map_deserialize() {
let json = r#"{
"run": {
"await": true,
"script": {
"language": "python",
"arguments": {"arg1": "value1"},
"environment": {"ENV_VAR": "value"},
"code": "print('Hello, World!')",
"stdin": "example-input"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let script = task.run.script.as_ref().unwrap();
assert_eq!(script.language, "python");
assert!(script.arguments.is_some());
let args = script.arguments.as_ref().unwrap();
assert!(args.is_map());
assert_eq!(
args.as_map().unwrap().get("arg1").unwrap(),
&serde_json::json!("value1")
);
}
#[test]
fn test_run_arguments_array_roundtrip() {
let json = r#"{
"run": {
"script": {
"language": "python",
"arguments": ["arg1=value1"],
"code": "print('test')"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_arguments_map_roundtrip() {
let json = r#"{
"run": {
"script": {
"language": "python",
"arguments": {"key1": "val1"},
"code": "print('test')"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_arguments_no_arguments() {
let json = r#"{
"run": {
"script": {
"language": "bash",
"code": "echo hello"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let script = task.run.script.as_ref().unwrap();
assert!(script.arguments.is_none());
}
#[test]
fn test_run_arguments_default() {
let args = OneOfRunArguments::default();
assert!(args.is_array());
assert_eq!(args.as_array().unwrap().len(), 0);
}
#[test]
fn test_try_task_retry_with_iso8601_delay() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"retry": {
"delay": "PT5S",
"backoff": {"exponential": {"factor": 2}},
"limit": {
"attempt": {"count": 3, "duration": "PT1M"},
"duration": "PT10M"
},
"jitter": {"from": {"seconds": 1}, "to": {"seconds": 3}}
}
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
let retry = task.catch.retry.as_ref().unwrap();
match retry {
OneOfRetryPolicyDefinitionOrReference::Retry(policy) => {
assert!(policy.delay.is_some());
match policy.delay.as_ref().unwrap() {
OneOfDurationOrIso8601Expression::Iso8601Expression(expr) => {
assert_eq!(expr, "PT5S");
}
_ => panic!("Expected Iso8601Expression for delay"),
}
assert!(policy.backoff.is_some());
assert!(policy.limit.is_some());
let limit = policy.limit.as_ref().unwrap();
match limit.duration.as_ref().unwrap() {
OneOfDurationOrIso8601Expression::Iso8601Expression(expr) => {
assert_eq!(expr, "PT10M");
}
_ => panic!("Expected Iso8601Expression for limit duration"),
}
}
_ => panic!("Expected Retry variant"),
}
}
#[test]
fn test_try_task_retry_with_reference() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"retry": "defaultRetry"
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
let retry = task.catch.retry.as_ref().unwrap();
match retry {
OneOfRetryPolicyDefinitionOrReference::Reference(name) => {
assert_eq!(name, "defaultRetry");
}
_ => panic!("Expected Reference variant"),
}
}
#[test]
fn test_try_task_retry_inline() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"retry": {
"delay": {"seconds": 3},
"backoff": {"exponential": {}},
"limit": {"attempt": {"count": 5}}
}
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
let retry = task.catch.retry.as_ref().unwrap();
match retry {
OneOfRetryPolicyDefinitionOrReference::Retry(policy) => {
assert!(policy.delay.is_some());
assert!(policy.backoff.is_some());
assert!(policy.backoff.as_ref().unwrap().exponential.is_some());
assert_eq!(
policy
.limit
.as_ref()
.unwrap()
.attempt
.as_ref()
.unwrap()
.count,
Some(5)
);
}
_ => panic!("Expected Retry variant"),
}
}
#[test]
fn test_try_task_retry_constant_backoff() {
let json = r#"{
"try": [{"doWork": {"set": {"x": 1}}}],
"catch": {
"retry": {
"delay": {"seconds": 3},
"backoff": {"constant": {"delay": "PT5S"}},
"limit": {"attempt": {"count": 5}}
}
}
}"#;
let task: TryTaskDefinition = serde_json::from_str(json).unwrap();
let retry = task.catch.retry.as_ref().unwrap();
match retry {
OneOfRetryPolicyDefinitionOrReference::Retry(policy) => {
assert!(policy.backoff.as_ref().unwrap().constant.is_some());
let constant = policy.backoff.as_ref().unwrap().constant.as_ref().unwrap();
assert_eq!(constant.delay(), Some("PT5S"));
}
_ => panic!("Expected Retry variant"),
}
}
#[test]
fn test_switch_task_with_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"switch": [
{"case1": {"when": "${condition1}", "then": "next"}},
{"case2": {"when": "${condition2}", "then": "end"}}
]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${condition}"));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then.as_deref(), Some("continue"));
assert_eq!(task.switch.entries.len(), 2);
let (_, case1) = &task.switch.entries[0];
assert_eq!(case1.when.as_deref(), Some("${condition1}"));
assert_eq!(case1.then.as_deref(), Some("next"));
}
#[test]
fn test_raise_task_with_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"raise": {
"error": {
"type": "http://example.com/error",
"status": 500,
"title": "Internal Server Error",
"detail": "An unexpected error occurred."
}
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${condition}"));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then.as_deref(), Some("continue"));
match &task.raise.error {
crate::models::error::OneOfErrorDefinitionOrReference::Error(err) => {
assert_eq!(err.type_.as_str(), "http://example.com/error");
assert_eq!(err.status, serde_json::json!(500));
assert_eq!(err.title, Some("Internal Server Error".to_string()));
assert_eq!(
err.detail,
Some("An unexpected error occurred.".to_string())
);
}
_ => panic!("Expected Error variant"),
}
}
#[test]
fn test_emit_task_full_event_properties() {
let json = r#"{
"emit": {
"event": {
"id": "event-id",
"source": "http://example.com/source",
"type": "example.event.type",
"time": "2023-01-01T00:00:00Z",
"subject": "example.subject",
"datacontenttype": "application/json",
"dataschema": "http://example.com/schema",
"with": {"extra": "value"}
}
}
}"#;
let task: EmitTaskDefinition = serde_json::from_str(json).unwrap();
let event = &task.emit.event;
assert_eq!(event.id.as_deref(), Some("event-id"));
assert_eq!(event.source.as_deref(), Some("http://example.com/source"));
assert_eq!(event.type_.as_deref(), Some("example.event.type"));
assert_eq!(event.time.as_deref(), Some("2023-01-01T00:00:00Z"));
assert_eq!(event.subject.as_deref(), Some("example.subject"));
assert_eq!(event.data_content_type.as_deref(), Some("application/json"));
assert_eq!(
event.data_schema.as_deref(),
Some("http://example.com/schema")
);
assert!(!event.with.is_empty());
assert_eq!(event.with.get("extra").unwrap(), "value");
}
#[test]
fn test_emit_task_with_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"emit": {
"event": {
"type": "example.event.type",
"source": "http://example.com/source",
"with": {"extra": "value"}
}
}
}"#;
let task: EmitTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${condition}"));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then.as_deref(), Some("continue"));
assert_eq!(task.emit.event.type_.as_deref(), Some("example.event.type"));
}
#[test]
fn test_listen_task_with_until_condition() {
let json = r#"{
"listen": {
"to": {
"any": [
{"with": {"type": "example.event.type", "source": "http://example.com/source"}}
],
"until": "workflow.data.condition == true"
}
}
}"#;
let task: ListenTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.listen.to.any.is_some());
assert!(task.listen.to.until.is_some());
let until = task.listen.to.until.as_ref().unwrap();
match **until {
crate::models::event::OneOfEventConsumptionStrategyDefinitionOrExpression::Expression(
ref expr,
) => {
assert_eq!(expr, "workflow.data.condition == true");
}
_ => panic!("Expected Expression variant for until"),
}
}
#[test]
fn test_listen_task_with_until_disabled() {
let json = r#"{
"listen": {
"to": {
"one": {"with": {"type": "example.event.type"}},
"until": false
}
}
}"#;
let task: ListenTaskDefinition = serde_json::from_str(json).unwrap();
let until = task.listen.to.until.as_ref().unwrap();
match **until {
crate::models::event::OneOfEventConsumptionStrategyDefinitionOrExpression::Bool(val) => {
assert!(!val);
}
_ => panic!("Expected Bool variant for until"),
}
}
#[test]
fn test_listen_task_with_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"listen": {
"to": {
"one": {"with": {"type": "example.event.type", "source": "http://example.com/source"}}
}
}
}"#;
let task: ListenTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${condition}"));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then.as_deref(), Some("continue"));
}
#[test]
fn test_for_task_with_call_subtask() {
let json = r#"{
"for": {"each": "item", "in": "${items}", "at": "index"},
"while": "${condition}",
"do": [
{"task1": {"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}},
{"task2": {"call": "openapi", "with": {"document": {"name": "doc1", "endpoint": "http://example.com/openapi.json"}, "operationId": "op1"}}}
]
}"#;
let task: ForTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.for_.each, "item");
assert_eq!(task.for_.in_, "${items}");
assert_eq!(task.for_.at.as_deref(), Some("index"));
assert_eq!(task.while_.as_deref(), Some("${condition}"));
assert_eq!(task.do_.entries.len(), 2);
assert!(task.do_.contains_key(&"task1".to_string()));
assert!(task.do_.contains_key(&"task2".to_string()));
}
#[test]
fn test_for_task_with_while_roundtrip() {
let json = r#"{
"for": {"each": "item", "in": "${items}", "at": "index"},
"while": "${condition}",
"do": [{"step": {"set": {"x": 1}}}]
}"#;
let task: ForTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: ForTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_do_task_with_call_subtask() {
let json = r#"{
"do": [
{"task1": {"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}},
{"task2": {"call": "openapi", "with": {"document": {"name": "doc1", "endpoint": "http://example.com/openapi.json"}, "operationId": "op1"}}}
]
}"#;
let task: DoTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.do_.entries.len(), 2);
assert!(task.do_.contains_key(&"task1".to_string()));
assert!(task.do_.contains_key(&"task2".to_string()));
}
#[test]
fn test_fork_task_with_call_branches() {
let json = r#"{
"fork": {
"branches": [
{"task1": {"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}},
{"task2": {"call": "openapi", "with": {"document": {"name": "doc1", "endpoint": "http://example.com/openapi.json"}, "operationId": "op1"}}}
],
"compete": true
}
}"#;
let task: ForkTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.fork.compete);
assert_eq!(task.fork.branches.entries.len(), 2);
assert!(task.fork.branches.contains_key(&"task1".to_string()));
assert!(task.fork.branches.contains_key(&"task2".to_string()));
}
#[test]
fn test_wait_task_with_iso8601_and_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"wait": "P1DT1H"
}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_.as_deref(), Some("${condition}"));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then.as_deref(), Some("continue"));
match &task.wait {
OneOfDurationOrIso8601Expression::Iso8601Expression(expr) => {
assert_eq!(expr, "P1DT1H");
}
_ => panic!("Expected Iso8601Expression variant"),
}
}
#[test]
fn test_switch_task_with_common_fields_roundtrip() {
let json = r#"{
"if": "${condition}",
"output": {"as": {"result": "output"}},
"then": "continue",
"switch": [{"case1": {"when": "${c1}", "then": "next"}}]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: SwitchTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_set_task_with_common_fields_roundtrip() {
let json = r#"{
"if": "${condition}",
"output": {"as": {"result": "output"}},
"then": "continue",
"set": {"key1": "value1", "key2": 42}
}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: SetTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_raise_task_with_common_fields_roundtrip() {
let json = r#"{
"if": "${condition}",
"output": {"as": {"result": "output"}},
"then": "continue",
"raise": {
"error": {
"type": "http://example.com/error",
"status": 500,
"title": "Error"
}
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RaiseTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_emit_task_full_event_roundtrip() {
let json = r#"{
"emit": {
"event": {
"id": "event-id",
"source": "http://example.com/source",
"type": "example.event.type",
"time": "2023-01-01T00:00:00Z",
"subject": "example.subject",
"datacontenttype": "application/json",
"dataschema": "http://example.com/schema",
"with": {"extra": "value"}
}
}
}"#;
let task: EmitTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: EmitTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_listen_task_with_until_roundtrip() {
let json = r#"{
"listen": {
"to": {
"any": [{"with": {"type": "example.event.type"}}],
"until": "workflow.data.condition == true"
}
}
}"#;
let task: ListenTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: ListenTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_task_container_with_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"run": {
"await": true,
"container": {
"image": "example-image",
"name": "example-name",
"command": "example-command",
"ports": {"8080": "80"},
"environment": {"ENV_VAR": "value"},
"stdin": "example-input",
"arguments": ["arg1", "arg2"],
"pullPolicy": "always",
"lifetime": {
"cleanup": "eventually",
"after": {"seconds": 20}
}
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_, Some("${condition}".to_string()));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then, Some("continue".to_string()));
assert!(task.common.metadata.is_some());
assert_eq!(task.run.await_, Some(true));
assert!(task.run.container.is_some());
let container = task.run.container.as_ref().unwrap();
assert_eq!(container.image, "example-image");
assert_eq!(container.command, Some("example-command".to_string()));
assert!(container.ports.is_some());
assert!(container.environment.is_some());
assert_eq!(container.stdin, Some("example-input".to_string()));
assert!(container.arguments.is_some());
let args = container.arguments.as_ref().unwrap();
assert_eq!(args, &vec!["arg1".to_string(), "arg2".to_string()]);
assert_eq!(container.pull_policy, Some("always".to_string()));
assert!(container.lifetime.is_some());
let lifetime = container.lifetime.as_ref().unwrap();
assert_eq!(lifetime.cleanup, "eventually");
}
#[test]
fn test_run_task_script_with_map_args() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"run": {
"await": true,
"script": {
"language": "python",
"arguments": {"arg1": "value1"},
"environment": {"ENV_VAR": "value"},
"code": "print('Hello, World!')",
"stdin": "example-input"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.run.await_, Some(true));
assert!(task.run.script.is_some());
let script = task.run.script.as_ref().unwrap();
assert_eq!(script.language, "python");
assert!(script.arguments.is_some());
let args = script.arguments.as_ref().unwrap();
assert!(args.is_map());
assert_eq!(script.code, Some("print('Hello, World!')".to_string()));
assert_eq!(script.stdin, Some("example-input".to_string()));
assert!(script.environment.is_some());
}
#[test]
fn test_run_task_script_with_array_args() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"run": {
"await": true,
"script": {
"language": "python",
"arguments": ["arg1=value1"],
"environment": {"ENV_VAR": "value"},
"code": "print('Hello, World!')",
"stdin": "example-input"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.run.script.is_some());
let script = task.run.script.as_ref().unwrap();
assert!(script.arguments.is_some());
let args = script.arguments.as_ref().unwrap();
assert!(args.is_array());
assert_eq!(args.as_array().unwrap(), &vec!["arg1=value1".to_string()]);
}
#[test]
fn test_run_task_container_roundtrip() {
let json = r#"{
"if": "${condition}",
"then": "continue",
"run": {
"await": true,
"container": {
"image": "example-image",
"command": "example-command",
"environment": {"ENV_VAR": "value"}
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_task_script_map_args_roundtrip() {
let json = r#"{
"run": {
"script": {
"language": "python",
"arguments": {"arg1": "value1"},
"code": "print('hello')"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_task_script_array_args_roundtrip() {
let json = r#"{
"run": {
"script": {
"language": "python",
"arguments": ["arg1=value1"],
"code": "print('hello')"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_set_task_full_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"set": {
"key1": "value1",
"key2": 42
}
}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_, Some("${condition}".to_string()));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then, Some("continue".to_string()));
assert!(task.common.metadata.is_some());
match &task.set {
SetValue::Map(map) => {
assert_eq!(map.len(), 2);
assert_eq!(map.get("key1").unwrap(), &serde_json::json!("value1"));
assert_eq!(map.get("key2").unwrap(), &serde_json::json!(42));
}
_ => panic!("Expected Map variant"),
}
}
#[test]
fn test_set_task_full_common_fields_roundtrip() {
let json = r#"{
"if": "${condition}",
"then": "continue",
"set": {"key1": "value1"}
}"#;
let task: SetTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: SetTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_do_task_with_multiple_subtasks() {
let json = r#"{
"do": [
{"task1": {"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}},
{"task2": {"set": {"result": "ok"}}}
]
}"#;
let task: DoTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.do_.len(), 2);
}
#[test]
fn test_do_task_with_subtasks_roundtrip() {
let json = r#"{
"do": [
{"task1": {"set": {"x": 1}}},
{"task2": {"set": {"y": 2}}}
]
}"#;
let task: DoTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: DoTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_fork_task_with_compete_and_branches() {
let json = r#"{
"fork": {
"branches": [
{"task1": {"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}},
{"task2": {"set": {"result": "ok"}}}
],
"compete": true
}
}"#;
let task: ForkTaskDefinition = serde_json::from_str(json).unwrap();
assert!(task.fork.compete);
assert_eq!(task.fork.branches.len(), 2);
}
#[test]
fn test_fork_task_with_compete_roundtrip() {
let json = r#"{
"fork": {
"branches": [
{"task1": {"set": {"x": 1}}},
{"task2": {"set": {"y": 2}}}
],
"compete": true
}
}"#;
let task: ForkTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: ForkTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_switch_task_with_common_fields_and_cases() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"switch": [
{"case1": {"when": "${condition1}", "then": "next"}},
{"case2": {"when": "${condition2}", "then": "end"}}
]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_, Some("${condition}".to_string()));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then, Some("continue".to_string()));
assert!(task.common.metadata.is_some());
assert_eq!(task.switch.len(), 2);
}
#[test]
fn test_switch_task_with_cases_roundtrip() {
let json = r#"{
"switch": [
{"case1": {"when": "${condition1}", "then": "next"}},
{"case2": {"when": "${condition2}", "then": "end"}}
]
}"#;
let task: SwitchTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: SwitchTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_raise_task_with_common_fields_and_error() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"raise": {
"error": {
"type": "http://example.com/error",
"status": 500,
"title": "Internal Server Error",
"detail": "An unexpected error occurred."
}
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_, Some("${condition}".to_string()));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then, Some("continue".to_string()));
assert!(task.common.metadata.is_some());
match &task.raise.error {
OneOfErrorDefinitionOrReference::Error(error) => {
assert_eq!(error.type_.as_str(), "http://example.com/error");
assert_eq!(error.status, serde_json::json!(500));
assert_eq!(error.title, Some("Internal Server Error".to_string()));
assert_eq!(
error.detail,
Some("An unexpected error occurred.".to_string())
);
}
_ => panic!("Expected Error variant"),
}
}
#[test]
fn test_raise_task_with_error_roundtrip() {
let json = r#"{
"raise": {
"error": {
"type": "http://example.com/error",
"status": 500,
"title": "Internal Server Error",
"detail": "An unexpected error occurred."
}
}
}"#;
let task: RaiseTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RaiseTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_wait_task_full_common_fields() {
let json = r#"{
"if": "${condition}",
"input": {"from": {"key": "value"}},
"output": {"as": {"result": "output"}},
"timeout": {"after": "PT10S"},
"then": "continue",
"metadata": {"meta": "data"},
"wait": "P1DT1H"
}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.common.if_, Some("${condition}".to_string()));
assert!(task.common.input.is_some());
assert!(task.common.output.is_some());
assert!(task.common.timeout.is_some());
assert_eq!(task.common.then, Some("continue".to_string()));
assert!(task.common.metadata.is_some());
assert!(task.wait.is_iso8601());
}
#[test]
fn test_wait_task_iso8601_roundtrip() {
let json = r#"{
"wait": "P1DT1H"
}"#;
let task: WaitTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: WaitTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_task_definition_dispatch_with_nested_do() {
let json = r#"{
"do": [
{"task1": {"call": "http", "with": {"method": "GET", "endpoint": "http://example.com"}}},
{"task2": {"do": [{"task3": {"set": {"result": "ok"}}}]}}
]
}"#;
let task: DoTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.do_.len(), 2);
let (name, task2_value) = &task.do_.entries[1];
assert_eq!(name, "task2");
match task2_value {
TaskDefinition::Do(nested_do) => {
assert_eq!(nested_do.do_.len(), 1);
}
_ => panic!("Expected Do variant for task2"),
}
}
#[test]
fn test_container_ports_string_values() {
let json = r#"{
"image": "nginx",
"ports": {"8080": "80", "443": "443"}
}"#;
let container: ContainerProcessDefinition = serde_json::from_str(json).unwrap();
assert!(container.ports.is_some());
let ports = container.ports.as_ref().unwrap();
assert_eq!(ports.len(), 2);
assert_eq!(ports.get("8080").unwrap(), &serde_json::json!("80"));
}
#[test]
fn test_container_ports_numeric_values() {
let json = r#"{
"image": "nginx",
"ports": {"8080": 80, "443": 443}
}"#;
let container: ContainerProcessDefinition = serde_json::from_str(json).unwrap();
assert!(container.ports.is_some());
let ports = container.ports.as_ref().unwrap();
assert_eq!(ports.get("8080").unwrap(), &serde_json::json!(80));
}
#[test]
fn test_container_with_lifetime_deserialize() {
let json = r#"{
"run": {
"await": true,
"container": {
"image": "example-image",
"name": "example-name",
"command": "example-command",
"ports": {"8080": "80"},
"environment": {"ENV_VAR": "value"},
"stdin": "example-input",
"arguments": ["arg1", "arg2"],
"lifetime": {
"cleanup": "eventually",
"after": {
"seconds": 20
}
}
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let container = task.run.container.as_ref().unwrap();
assert_eq!(container.image, "example-image");
assert_eq!(container.name, Some("example-name".to_string()));
assert_eq!(container.command, Some("example-command".to_string()));
assert_eq!(container.stdin, Some("example-input".to_string()));
assert_eq!(
container.arguments,
Some(vec!["arg1".to_string(), "arg2".to_string()])
);
let lifetime = container.lifetime.as_ref().unwrap();
assert_eq!(lifetime.cleanup, "eventually");
assert!(lifetime.after.is_some());
}
#[test]
fn test_container_with_lifetime_roundtrip() {
let json = r#"{
"run": {
"await": true,
"container": {
"image": "example-image",
"command": "example-command",
"stdin": "example-input",
"arguments": ["arg1","arg2"],
"pullPolicy": "always",
"lifetime": {
"cleanup": "eventually",
"after": "PT20S"
}
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let serialized = serde_json::to_string(&task).unwrap();
let deserialized: RunTaskDefinition = serde_json::from_str(&serialized).unwrap();
assert_eq!(task, deserialized);
}
#[test]
fn test_run_task_with_await() {
let json = r#"{
"run": {
"await": true,
"shell": {
"command": "echo hello"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.run.await_, Some(true));
}
#[test]
fn test_run_task_without_await() {
let json = r#"{
"run": {
"shell": {
"command": "echo hello"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
assert_eq!(task.run.await_, None);
}
#[test]
fn test_script_with_stdin_and_arguments() {
let json = r#"{
"run": {
"await": true,
"script": {
"language": "python",
"arguments": {"arg1": "value1"},
"environment": {"ENV_VAR": "value"},
"code": "print('Hello, World!')",
"stdin": "example-input"
}
}
}"#;
let task: RunTaskDefinition = serde_json::from_str(json).unwrap();
let script = task.run.script.as_ref().unwrap();
assert_eq!(script.language, "python");
assert_eq!(script.stdin, Some("example-input".to_string()));
assert_eq!(script.code, Some("print('Hello, World!')".to_string()));
assert!(script.arguments.is_some());
match script.arguments.as_ref().unwrap() {
OneOfRunArguments::Map(map) => {
assert_eq!(map.get("arg1").unwrap(), &serde_json::json!("value1"));
}
_ => panic!("Expected Map variant"),
}
}
#[test]
fn test_container_pull_policy_deserialize() {
let json = r#"{
"image": "nginx",
"pullPolicy": "always"
}"#;
let container: ContainerProcessDefinition = serde_json::from_str(json).unwrap();
assert_eq!(container.pull_policy, Some("always".to_string()));
}