package iace import "testing" // firedSet runs the engine for the given custom tags and returns the set of // fired pattern IDs. func firedSet(customTags []string) map[string]bool { engine := NewPatternEngine() out := engine.Match(MatchInput{CustomTags: customTags}) fired := make(map[string]bool, len(out.MatchedPatterns)) for _, m := range out.MatchedPatterns { fired[m.PatternID] = true } return fired } // A warewashing narrative emits these capability + functional tags. var warewashingTags = []string{ "dom_warewashing", "steam_emission", "hot_water", "high_temperature", "corrosive_chemical", "access_door", "rotating_part", } func TestWarewashing_PatternsFireForDishwasher(t *testing.T) { fired := firedSet(warewashingTags) want := []string{"HP2200", "HP2201", "HP2202", "HP2203", "HP2204", "HP2205", "HP2206"} for _, id := range want { if !fired[id] { t.Errorf("expected warewashing pattern %s to fire for a dishwasher, but it did not", id) } } } func TestWarewashing_PatternsDoNotLeakIntoOtherMachines(t *testing.T) { // A machine with thermal + electrical + chemical capability but NOT a // dishwasher must never produce warewashing hazards (dom_warewashing gate). fired := firedSet([]string{"high_temperature", "electrical_part", "chemical_risk", "rotating_part", "moving_part"}) for _, id := range []string{"HP2200", "HP2201", "HP2202", "HP2203", "HP2204", "HP2205", "HP2206"} { if fired[id] { t.Errorf("warewashing pattern %s leaked into a non-dishwasher machine", id) } } } func TestWarewashing_WeldingAndGlueDoNotLeakIntoDishwasher(t *testing.T) { // The gate-term additions must stop the welding/flame/glue burn patterns // from firing for a dishwasher (they previously leaked via high_temperature // / electrical_part). dom_welding/dom_flame/dom_glue are absent here. fired := firedSet(warewashingTags) leak := map[string]string{ "HP530": "Lichtbogen-Verbrennung (Schweissen)", "HP532": "Schweissrauch", "HP533": "Brand durch Schweissfunken (Schweissen)", } for id, name := range leak { if fired[id] { t.Errorf("cross-domain pattern %s (%s) leaked into a dishwasher", id, name) } } } func TestWarewashing_MeasureIDsExist(t *testing.T) { lib := GetProtectiveMeasureLibrary() have := make(map[string]bool, len(lib)) for _, m := range lib { have[m.ID] = true } for _, p := range GetWarewashingPatterns() { for _, mid := range p.SuggestedMeasureIDs { if !have[mid] { t.Errorf("pattern %s references measure %s which is not in the library", p.ID, mid) } } } } func TestWarewashing_NarrativeEmitsTags(t *testing.T) { // Closes the loop: a realistic dishwasher description must emit the tags // the warewashing patterns gate on (otherwise the patterns are dead). narrative := "Gewerbliche Untertisch-Geschirrspuelmaschine mit Heisswasser-Boiler " + "und Nachspuelung ca. 85 Grad C, Spuelpumpe mit rotierenden Spuelfeldern, " + "Dampf-/Wrasenabgabe beim Oeffnen, Reiniger und Klarspueler ueber Dosiergeraet, " + "Tuer mit Sicherheitsschalter, Eingreifen in die Spuelkammer." res := ParseNarrative(narrative, "Gewerbliche Geschirrspuelmaschine") got := make(map[string]bool, len(res.CustomTags)) for _, tag := range res.CustomTags { got[tag] = true } for _, want := range []string{"dom_warewashing", "steam_emission", "hot_water", "corrosive_chemical", "access_door", "rotating_part"} { if !got[want] { t.Errorf("narrative did not emit expected tag %q (got %v)", want, res.CustomTags) } } // And it must NOT emit any welding/flame/glue domain that would re-open leaks. for _, bad := range []string{"dom_welding", "dom_flame", "dom_glue"} { if got[bad] { t.Errorf("dishwasher narrative unexpectedly emitted cross-domain tag %q", bad) } } } func TestWarewashing_NewMeasuresPresent(t *testing.T) { lib := GetProtectiveMeasureLibrary() have := make(map[string]bool, len(lib)) for _, m := range lib { have[m.ID] = true } for _, mid := range []string{"M2200", "M2201", "M2202", "M2203", "M2204", "M2205", "M2206", "M2207", "M2208"} { if !have[mid] { t.Errorf("expected warewashing measure %s to be registered in the library", mid) } } }