Sprint 14~22 — egui 리본 UI + OcctKernel B-rep + 가로보/신축이음 + 선형 좌표 + USD 익스포트 + WASM + CI/CD + 테스트 4층
Sprint 14: egui TopBottomPanel 리본 + CollapsingHeader SidePanel (상부구조·추가부재·선형·프로젝트) Sprint 15: IncrementalDb 전 Feature 타입 확장 (girder→7종), dirty-tracking 20 unit tests Sprint 16: Gitea + GitHub Actions CI/CD (check/test/clippy/fmt + 멀티플랫폼 릴리스) Sprint 17: AlignmentTransform + AlignmentScene — 선형 국소 프레임 → 세계 좌표 변환 Sprint 18: OcctKernel 교각(16각형 기둥+코핑) + 교대(흉벽+푸팅+날개벽) B-rep Sprint 19: CrossBeamIR + ExpansionJointIR — IR/DSL/kernel/scene 전 계층, sweep_profile_flat_x Sprint 20: 테스트 4층 — Layer1 insta 스냅샷(7종), Layer2 기하 불변량(19), Layer3 두-커널(7), Layer4 proptest(7) — 61 tests pass Sprint 21: cimery-usd PureRustKernel 실제 기하 변환 + BridgeExporter 증분 캐시 Sprint 22: viewer wasm feature + wasm-bindgen/web-sys + GitHub Actions Cloudflare Pages 배포 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
219
cimery/crates/kernel/tests/layer1_snapshots.rs
Normal file
219
cimery/crates/kernel/tests/layer1_snapshots.rs
Normal file
@@ -0,0 +1,219 @@
|
||||
//! Layer 1: IR serialization snapshots (Sprint 20).
|
||||
//!
|
||||
//! Uses `insta` to capture stable JSON representations of IR structs.
|
||||
//! On first run these create `.snap.new` files — run `cargo insta review` to approve.
|
||||
//! Snapshots live in `tests/snapshots/` and are committed to version control.
|
||||
//!
|
||||
//! Purpose: catch accidental schema changes that break saved project files.
|
||||
|
||||
use cimery_core::{
|
||||
AbutmentType, BearingType, ColumnShape, CrossBeamSection, ExpansionJointType,
|
||||
MaterialGrade, PierType, SectionType,
|
||||
};
|
||||
use cimery_ir::{
|
||||
AbutmentIR, BearingIR, CapBeamIR, CrossBeamIR, DeckSlabIR, ExpansionJointIR,
|
||||
FeatureId, GirderIR, PierIR, PscISectionParams, SectionParams, WingWallIR,
|
||||
};
|
||||
|
||||
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
/// GirderIR with a deterministic fixed ID for stable snapshots.
|
||||
fn snapshot_girder() -> GirderIR {
|
||||
GirderIR {
|
||||
id: fixed_id("girder-1"),
|
||||
station_start: 100.0,
|
||||
station_end: 140.0,
|
||||
offset_from_alignment: 0.0,
|
||||
section_type: SectionType::PscI,
|
||||
section: SectionParams::PscI(PscISectionParams::kds_standard()),
|
||||
count: 5,
|
||||
spacing: 2500.0,
|
||||
material: MaterialGrade::C50,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_deck_slab() -> DeckSlabIR {
|
||||
DeckSlabIR {
|
||||
id: fixed_id("deck-1"),
|
||||
station_start: 100.0,
|
||||
station_end: 140.0,
|
||||
width_left: 5_500.0,
|
||||
width_right: 5_500.0,
|
||||
thickness: 220.0,
|
||||
haunch_depth: 100.0,
|
||||
cross_slope: 2.0,
|
||||
material: MaterialGrade::C40,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_bearing() -> BearingIR {
|
||||
BearingIR {
|
||||
id: fixed_id("bearing-1"),
|
||||
station: 100.0,
|
||||
bearing_type: BearingType::Elastomeric,
|
||||
plan_length: 350.0,
|
||||
plan_width: 350.0,
|
||||
total_height: 90.0,
|
||||
capacity_vertical:2_500.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_pier() -> PierIR {
|
||||
PierIR {
|
||||
id: fixed_id("pier-1"),
|
||||
station: 120.0,
|
||||
skew_angle: 0.0,
|
||||
pier_type: PierType::SingleColumn,
|
||||
column_shape: ColumnShape::Circular,
|
||||
column_count: 1,
|
||||
column_spacing: 0.0,
|
||||
column_diameter: 1_500.0,
|
||||
column_depth: 0.0,
|
||||
column_height: 8_000.0,
|
||||
cap_beam: CapBeamIR {
|
||||
length: 13_000.0,
|
||||
width: 1_200.0,
|
||||
depth: 1_400.0,
|
||||
cantilever_left: 1_000.0,
|
||||
cantilever_right:1_000.0,
|
||||
},
|
||||
material: MaterialGrade::C40,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_abutment() -> AbutmentIR {
|
||||
AbutmentIR {
|
||||
id: fixed_id("abutment-1"),
|
||||
station: 100.0,
|
||||
skew_angle: 0.0,
|
||||
abutment_type: AbutmentType::ReverseT,
|
||||
breast_wall_height: 5_000.0,
|
||||
breast_wall_thickness: 800.0,
|
||||
breast_wall_width: 12_000.0,
|
||||
footing_length: 4_000.0,
|
||||
footing_width: 13_000.0,
|
||||
footing_thickness: 1_000.0,
|
||||
wing_wall_left: WingWallIR { length: 4_000.0, height: 4_000.0, thickness: 500.0 },
|
||||
wing_wall_right: WingWallIR { length: 4_000.0, height: 4_000.0, thickness: 500.0 },
|
||||
material: MaterialGrade::C40,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_cross_beam() -> CrossBeamIR {
|
||||
CrossBeamIR {
|
||||
id: fixed_id("cb-1"),
|
||||
station: 110.0,
|
||||
section: CrossBeamSection::HSection,
|
||||
web_height: 1_260.0,
|
||||
web_thickness: 12.0,
|
||||
flange_width: 300.0,
|
||||
flange_thickness: 16.0,
|
||||
bay_count: 4,
|
||||
girder_spacing: 2_500.0,
|
||||
material: MaterialGrade::Ss400,
|
||||
}
|
||||
}
|
||||
|
||||
fn snapshot_expansion_joint() -> ExpansionJointIR {
|
||||
ExpansionJointIR {
|
||||
id: fixed_id("ej-1"),
|
||||
station: 100.0,
|
||||
joint_type: ExpansionJointType::RubberType,
|
||||
gap_width: 50.0,
|
||||
total_width: 11_000.0,
|
||||
depth: 100.0,
|
||||
movement_range: 30.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a FeatureId from a deterministic UUID-v5-like string (not actually v5,
|
||||
/// just a fixed nil-offset trick for snapshot stability).
|
||||
fn fixed_id(tag: &str) -> FeatureId {
|
||||
use std::str::FromStr;
|
||||
// Seed with a stable tag-based UUID string (each test feature has its own).
|
||||
let s = match tag {
|
||||
"girder-1" => "00000000-0000-0000-0000-000000000001",
|
||||
"deck-1" => "00000000-0000-0000-0000-000000000002",
|
||||
"bearing-1" => "00000000-0000-0000-0000-000000000003",
|
||||
"pier-1" => "00000000-0000-0000-0000-000000000004",
|
||||
"abutment-1" => "00000000-0000-0000-0000-000000000005",
|
||||
"cb-1" => "00000000-0000-0000-0000-000000000006",
|
||||
"ej-1" => "00000000-0000-0000-0000-000000000007",
|
||||
_ => "00000000-0000-0000-0000-000000000000",
|
||||
};
|
||||
FeatureId(uuid::Uuid::from_str(s).unwrap())
|
||||
}
|
||||
|
||||
// ─── Snapshot tests ───────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn snapshot_girder_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_girder()).unwrap();
|
||||
insta::assert_snapshot!("girder_ir_json", json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_deck_slab_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_deck_slab()).unwrap();
|
||||
insta::assert_snapshot!("deck_slab_ir_json", json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_bearing_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_bearing()).unwrap();
|
||||
insta::assert_snapshot!("bearing_ir_json", json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_pier_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_pier()).unwrap();
|
||||
insta::assert_snapshot!("pier_ir_json", json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_abutment_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_abutment()).unwrap();
|
||||
insta::assert_snapshot!("abutment_ir_json", json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_cross_beam_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_cross_beam()).unwrap();
|
||||
insta::assert_snapshot!("cross_beam_ir_json", json);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn snapshot_expansion_joint_ir() {
|
||||
let json = serde_json::to_string_pretty(&snapshot_expansion_joint()).unwrap();
|
||||
insta::assert_snapshot!("expansion_joint_ir_json", json);
|
||||
}
|
||||
|
||||
// ─── Round-trip sanity ────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn girder_json_roundtrip() {
|
||||
let ir = snapshot_girder();
|
||||
let json = serde_json::to_string(&ir).unwrap();
|
||||
let ir2: GirderIR = serde_json::from_str(&json).unwrap();
|
||||
assert!((ir.span_m() - ir2.span_m()).abs() < f64::EPSILON);
|
||||
assert_eq!(ir.count, ir2.count);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cross_beam_json_roundtrip() {
|
||||
let ir = snapshot_cross_beam();
|
||||
let json = serde_json::to_string(&ir).unwrap();
|
||||
let ir2: CrossBeamIR = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(ir.bay_count, ir2.bay_count);
|
||||
assert!((ir.girder_spacing - ir2.girder_spacing).abs() < f64::EPSILON);
|
||||
assert!((ir.total_length_mm() - ir2.total_length_mm()).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expansion_joint_json_roundtrip() {
|
||||
let ir = snapshot_expansion_joint();
|
||||
let json = serde_json::to_string(&ir).unwrap();
|
||||
let ir2: ExpansionJointIR = serde_json::from_str(&json).unwrap();
|
||||
assert!((ir.gap_width - ir2.gap_width).abs() < f64::EPSILON);
|
||||
assert!((ir.total_width - ir2.total_width).abs() < f64::EPSILON);
|
||||
}
|
||||
Reference in New Issue
Block a user