#![allow(missing_docs)]
use std::path::PathBuf;
use flowcore::content::file_provider::FileProvider;
use flowcore::model::flow_manifest::FlowManifest;
use url::Url;
fn load_example_manifest(example_name: &str) -> FlowManifest {
let sample_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("examples")
.join(example_name);
utilities::compile_example(&sample_dir, "flowrcli");
let manifest_url =
Url::from_file_path(sample_dir.join("manifest.json")).expect("Could not create URL");
let provider = FileProvider;
let (manifest, _) =
FlowManifest::load(&provider, &manifest_url).expect("Could not load manifest");
manifest
}
fn verify_basic_invariants(manifest: &FlowManifest, example_name: &str) {
for function in manifest.functions().values() {
for conn in function.get_output_connections() {
let dst_fn = manifest
.functions()
.get(&conn.destination_id)
.unwrap_or_else(|| {
panic!(
"{example_name}: destination fn#{} not found",
conn.destination_id
)
});
let src_parent = function.get_parent_id();
let dst_parent = dst_fn.get_parent_id();
if function.id() == conn.destination_id {
assert!(
conn.internal,
"{example_name}: self-loopback fn#{} should be internal",
function.id()
);
}
if src_parent != dst_parent {
assert!(
!conn.internal,
"{example_name}: cross-flow fn#{}(flow={}) -> fn#{}(flow={}) should be external",
function.id(),
src_parent,
conn.destination_id,
dst_parent
);
}
}
}
}
#[test]
fn factorial_all_internal() {
let manifest = load_example_manifest("factorial");
verify_basic_invariants(&manifest, "factorial");
for function in manifest.functions().values() {
for conn in function.get_output_connections() {
assert!(
conn.internal,
"factorial: fn#{} -> fn#{}:io{} should be internal (single flow)",
function.id(),
conn.destination_id,
conn.destination_io_number
);
}
}
}
#[test]
fn sequence_of_sequences_classification() {
let manifest = load_example_manifest("sequence-of-sequences");
verify_basic_invariants(&manifest, "sequence-of-sequences");
}
#[test]
fn router_classification() {
let manifest = load_example_manifest("router");
verify_basic_invariants(&manifest, "router");
let mut found_parent_routed = false;
for function in manifest.functions().values() {
for conn in function.get_output_connections() {
let dst_fn = manifest
.functions()
.get(&conn.destination_id)
.expect("destination not found");
if function.get_parent_id() == dst_fn.get_parent_id() && !conn.internal {
found_parent_routed = true;
}
}
}
assert!(
found_parent_routed,
"router: should have at least one parent-routed (crossed boundary) connection"
);
}
#[test]
fn prime_classification() {
let manifest = load_example_manifest("prime");
verify_basic_invariants(&manifest, "prime");
let mut has_internal = false;
let mut has_external = false;
for function in manifest.functions().values() {
for conn in function.get_output_connections() {
if conn.internal {
has_internal = true;
} else {
has_external = true;
}
}
}
assert!(has_internal, "prime: should have internal connections");
assert!(has_external, "prime: should have external connections");
}
#[test]
fn running_average_classification() {
let manifest = load_example_manifest("running-average");
verify_basic_invariants(&manifest, "running-average");
}
#[test]
fn fibonacci_classification() {
let manifest = load_example_manifest("fibonacci");
verify_basic_invariants(&manifest, "fibonacci");
for function in manifest.functions().values() {
for conn in function.get_output_connections() {
assert!(
conn.internal,
"fibonacci: fn#{} -> fn#{}:io{} should be internal",
function.id(),
conn.destination_id,
conn.destination_io_number
);
}
}
}