use crate::features::PlanarProfileRef;
use crate::features::{FeatureId, GeneratedCurveRef, PathRef, ProfileRef};
use crate::ids::{FeatureInputTopologyId, HistoricalEdgeId, HistoricalFaceId};
use crate::sketches::{SketchEntityId, SketchId, SpatialSketchEntityId, SpatialSketchId};
#[test]
fn profile_selection_members_are_checked_at_construction_and_on_wire() {
let sketch = SketchId::mint("test:test:sketch#one").unwrap();
let spatial = SpatialSketchId::mint("test:test:spatial-sketch#one").unwrap();
let entity = SketchEntityId::mint("test:test:sketch-entity#one").unwrap();
let state = FeatureInputTopologyId::mint("test:model:feature-input#one").unwrap();
let face = HistoricalFaceId::mint("test:model:historical-face#one").unwrap();
let profiles = [
(
ProfileRef::Planar(
PlanarProfileRef::sketch_profiles(sketch.clone(), vec![1, 0]).unwrap(),
),
"profiles",
),
(
ProfileRef::spatial_sketch_profiles(spatial.clone(), vec![1, 0]).unwrap(),
"profiles",
),
(
ProfileRef::Planar(
PlanarProfileRef::sketch_entities(sketch.clone(), vec![entity.clone()]).unwrap(),
),
"entities",
),
(
ProfileRef::Planar(
PlanarProfileRef::sketch_selection(sketch.clone(), vec!["group".into()]).unwrap(),
),
"selections",
),
(
ProfileRef::spatial_sketch_selection(spatial.clone(), vec!["group".into()]).unwrap(),
"selections",
),
(
ProfileRef::Planar(
PlanarProfileRef::historical_faces(
state.clone(),
vec![face.clone()],
vec!["group".into()],
)
.unwrap(),
),
"faces",
),
];
for (profile, field) in profiles {
let wire = serde_json::to_value(&profile).unwrap();
assert_eq!(
serde_json::from_value::<ProfileRef>(wire.clone()).unwrap(),
profile
);
let first = wire["value"][field][0].clone();
for invalid in [serde_json::json!([]), serde_json::json!([first, first])] {
let mut invalid_wire = wire.clone();
invalid_wire["value"][field] = invalid;
assert!(serde_json::from_value::<ProfileRef>(invalid_wire.clone()).is_err());
if profile.planar().is_some() {
let message = serde_json::from_value::<PlanarProfileRef>(invalid_wire)
.unwrap_err()
.to_string();
assert!(message.contains(field), "{message}");
}
}
}
for indices in [vec![], vec![0, 0]] {
assert!(PlanarProfileRef::sketch_profiles(sketch.clone(), indices.clone(),).is_err());
assert!(ProfileRef::spatial_sketch_profiles(spatial.clone(), indices,).is_err());
}
for entities in [vec![], vec![entity.clone(), entity]] {
assert!(PlanarProfileRef::sketch_entities(sketch.clone(), entities,).is_err());
}
for names in [
vec![],
vec![String::new()],
vec![" \t".into()],
vec!["group".into(), "group".into()],
] {
assert!(PlanarProfileRef::sketch_selection(sketch.clone(), names.clone(),).is_err());
assert!(ProfileRef::spatial_sketch_selection(spatial.clone(), names.clone(),).is_err());
assert!(
PlanarProfileRef::historical_faces(state.clone(), vec![face.clone()], names,).is_err()
);
}
assert!(
PlanarProfileRef::historical_faces(state.clone(), vec![], vec!["group".into()],).is_err()
);
assert!(PlanarProfileRef::historical_faces(
state,
vec![face.clone(), face],
vec!["group".into()],
)
.is_err());
}
#[test]
fn path_selection_members_are_checked_at_construction_and_on_wire() {
let sketch = SketchId::mint("test:test:sketch#one").unwrap();
let spatial = SpatialSketchId::mint("test:test:spatial-sketch#one").unwrap();
let entity = SketchEntityId::mint("test:test:sketch-entity#one").unwrap();
let spatial_entity = SpatialSketchEntityId::mint("test:test:spatial-entity#one").unwrap();
let state = FeatureInputTopologyId::mint("test:model:feature-input#one").unwrap();
let edge = HistoricalEdgeId::mint("test:model:historical-edge#one").unwrap();
let paths = [
(
PathRef::sketch_curves(sketch.clone(), vec![entity.clone()]).unwrap(),
"curves",
),
(
PathRef::spatial_sketch_curves(spatial.clone(), vec![spatial_entity.clone()]).unwrap(),
"curves",
),
(
crate::features::NativeSelections::try_from(vec!["group".into()])
.map(
|selections| crate::features::PathRef::SpatialSketchSelection {
sketch: spatial.clone(),
selections,
},
)
.unwrap(),
"selections",
),
(
PathRef::historical_edges(state.clone(), vec![edge.clone()], "group".into()).unwrap(),
"edges",
),
];
for (path, field) in paths {
let wire = serde_json::to_value(&path).unwrap();
assert_eq!(
serde_json::from_value::<PathRef>(wire.clone()).unwrap(),
path
);
let first = wire["value"][field][0].clone();
for invalid in [serde_json::json!([]), serde_json::json!([first, first])] {
let mut invalid_wire = wire.clone();
invalid_wire["value"][field] = invalid;
assert!(serde_json::from_value::<PathRef>(invalid_wire)
.unwrap_err()
.to_string()
.contains(field));
}
}
for curves in [vec![], vec![entity.clone(), entity]] {
assert!(PathRef::sketch_curves(sketch.clone(), curves,).is_err());
}
for curves in [vec![], vec![spatial_entity.clone(), spatial_entity]] {
assert!(PathRef::spatial_sketch_curves(spatial.clone(), curves,).is_err());
}
for names in [
vec![],
vec![String::new()],
vec![" \t".into()],
vec!["group".into(), "group".into()],
] {
assert!(crate::features::NativeSelections::try_from(names)
.map(
|selections| crate::features::PathRef::SpatialSketchSelection {
sketch: spatial.clone(),
selections
}
)
.is_err());
}
assert!(PathRef::historical_edges(state.clone(), vec![], "group".into(),).is_err());
assert!(PathRef::historical_edges(
state.clone(),
vec![edge.clone(), edge.clone()],
"group".into(),
)
.is_err());
assert!(PathRef::historical_edges(state.clone(), vec![edge.clone()], String::new(),).is_err());
assert!(PathRef::historical_edges(state.clone(), vec![edge.clone()], " ".into(),).is_err());
assert!(PathRef::historical_edges(state, vec![edge], " g ".into(),).is_ok());
}
#[test]
fn generated_profiles_require_references_and_preserve_repeated_curves() {
let feature = FeatureId::mint("test:test:feature#one").unwrap();
for invalid in ["", " \t"] {
assert!(GeneratedCurveRef::new(feature.clone(), invalid.into()).is_err());
assert!(serde_json::from_value::<GeneratedCurveRef>(
serde_json::json!({"feature": feature, "local_id": invalid})
)
.unwrap_err()
.to_string()
.contains("local_id"));
}
let curve = GeneratedCurveRef::new(feature, "curve".into()).unwrap();
assert!(PlanarProfileRef::generated(vec![], "group".into()).is_err());
for native in ["", " \t"] {
assert!(PlanarProfileRef::generated(vec![curve.clone()], native.into()).is_err());
}
let profile = ProfileRef::Planar(
PlanarProfileRef::generated(vec![curve.clone(), curve.clone()], "group".into()).unwrap(),
);
let wire = serde_json::to_value(&profile).unwrap();
assert_eq!(wire["value"]["curves"], serde_json::json!([curve, curve]));
assert_eq!(
serde_json::from_value::<ProfileRef>(wire.clone()).unwrap(),
profile
);
for (field, value) in [
("curves", serde_json::json!([])),
("native", serde_json::json!(" \t")),
] {
let mut invalid = wire.clone();
invalid["value"][field] = value;
assert!(serde_json::from_value::<ProfileRef>(invalid.clone()).is_err());
assert!(serde_json::from_value::<PlanarProfileRef>(invalid)
.unwrap_err()
.to_string()
.contains(field));
}
}
#[test]
fn a_spatial_profile_where_a_planar_one_is_required_is_refused_as_an_unknown_variant() {
let spatial = ProfileRef::spatial_sketch_profiles(
SpatialSketchId::mint("test:test:spatial-sketch#one").unwrap(),
vec![0],
)
.unwrap();
let wire = serde_json::to_value(&spatial).unwrap();
assert_eq!(wire["kind"], "spatial_sketch_profiles");
let error = serde_json::from_value::<PlanarProfileRef>(wire.clone())
.expect_err("a spatial profile is not a planar profile");
assert!(error.to_string().contains("unknown variant"), "{error}");
let section = serde_json::json!({ "kind": "profile", "value": wire });
assert!(serde_json::from_value::<crate::features::SweepSection>(section).is_err());
assert!(spatial.planar().is_none());
}