# pylint: disable=import-outside-toplevel, protected-access """ Comprehensive tests for warbler_cda.melt_layer module. Tests the MeltLayer and MagmaStore for cluster retirement. """ class TestMagmaStore: """Test MagmaStore class.""" def test_magma_store_initialization(self): """MagmaStore should initialize with empty glyphs list.""" from warbler_cda.melt_layer import MagmaStore store = MagmaStore() assert not store.glyphs def test_add_glyph(self): """add_glyph should append glyph to store.""" from warbler_cda.melt_layer import MagmaStore store = MagmaStore() glyph = {"id": "glyph-1", "summary": "test"} store.add_glyph(glyph) assert len(store.glyphs) == 1 assert store.glyphs[0] == glyph def test_add_multiple_glyphs(self): """add_glyph should handle multiple glyphs.""" from warbler_cda.melt_layer import MagmaStore store = MagmaStore() for i in range(5): store.add_glyph({"id": f"glyph-{i}"}) assert len(store.glyphs) == 5 def test_select_hot(self): """select_hot should return most recent glyphs.""" from warbler_cda.melt_layer import MagmaStore store = MagmaStore() import time now = int(time.time()) for i in range(10): created_epoch = now - (9 - i) * 3600 store.add_glyph({"id": f"glyph-{i}", "created_epoch": created_epoch}) hot = store.select_hot(limit=3) assert len(hot) == 3 # Should be highest heat glyphs (most recent) assert hot[0]["id"] == "glyph-9" assert hot[1]["id"] == "glyph-8" assert hot[2]["id"] == "glyph-7" def test_select_hot_limit_exceeds_size(self): """select_hot should handle limit larger than store size.""" from warbler_cda.melt_layer import MagmaStore store = MagmaStore() store.add_glyph({"id": "glyph-1"}) store.add_glyph({"id": "glyph-2"}) hot = store.select_hot(limit=10) assert len(hot) == 2 class TestMeltLayer: """Test MeltLayer class.""" def test_melt_layer_initialization(self): """MeltLayer should initialize with magma store.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) assert melt.magma_store == store assert melt.embed_fn is not None def test_melt_layer_custom_embed_fn(self): """MeltLayer should accept custom embedding function.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() def custom_embed(frags): # frags is already a list of text strings return [0.5, 0.5, 0.5] melt = MeltLayer(magma_store=store, embed_fn=custom_embed) # Call the embed function with empty list to verify it works assert melt.embed_fn([]) == [0.5, 0.5, 0.5] def test_retire_cluster_empty(self): """retire_cluster should handle empty cluster.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) cluster = {"fragments": []} glyph = melt.retire_cluster(cluster) assert "id" in glyph assert glyph["compressed_summary"] == "(empty cluster)" assert len(store.glyphs) == 1 def test_retire_cluster_with_fragments(self): """retire_cluster should process fragments into glyph.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) cluster = { "fragments": [ {"id": "f1", "text": "Fragment one"}, {"id": "f2", "text": "Fragment two"} ] } glyph = melt.retire_cluster(cluster) assert glyph["id"].startswith("mglyph_") assert glyph["source_ids"] == ["f1", "f2"] assert "Fragment one" in glyph["compressed_summary"] assert "embedding" in glyph assert "affect" in glyph assert glyph["resolution_state"] == "retired" assert "provenance_hash" in glyph assert "created_epoch" in glyph def test_glyph_id_deterministic(self): """_glyph_id should be deterministic for same summary.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) id1 = melt._glyph_id("test summary") id2 = melt._glyph_id("test summary") assert id1 == id2 assert id1.startswith("mglyph_") def test_glyph_id_different_summaries(self): """_glyph_id should produce different IDs for different summaries.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) id1 = melt._glyph_id("summary one") id2 = melt._glyph_id("summary two") assert id1 != id2 def test_summarize_empty(self): """_summarize should handle empty fragments.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) summary = melt._summarize([]) assert summary == "(empty cluster)" def test_summarize_single_fragment(self): """_summarize should handle single fragment.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) fragments = [{"text": "Single fragment text"}] summary = melt._summarize(fragments) assert "Single fragment text" in summary def test_summarize_multiple_fragments(self): """_summarize should join multiple fragments.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) fragments = [ {"text": "Fragment one"}, {"text": "Fragment two"}, {"text": "Fragment three"} ] summary = melt._summarize(fragments) assert "Fragment one" in summary assert "|" in summary # Separator def test_summarize_truncation(self): """_summarize should truncate long summaries.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) # Create very long fragments fragments = [{"text": "A" * 200} for _ in range(10)] summary = melt._summarize(fragments) # Should be truncated to 180 chars assert len(summary) <= 180 def test_prov_hash_deterministic(self): """_prov_hash should be deterministic.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) fragments = [{"text": "test"}] hash1 = melt._prov_hash(fragments) hash2 = melt._prov_hash(fragments) assert hash1 == hash2 assert hash1.startswith("sha256:") def test_prov_hash_different_fragments(self): """_prov_hash should produce different hashes for different fragments.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) fragments1 = [{"text": "test1"}] fragments2 = [{"text": "test2"}] hash1 = melt._prov_hash(fragments1) hash2 = melt._prov_hash(fragments2) assert hash1 != hash2 class TestIntegration: """Integration tests for melt layer workflow.""" def test_full_retirement_workflow(self): """Test complete cluster retirement workflow.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() def embed_fn(frags): # frags is already a list of text strings return [0.1, 0.2, 0.3] melt = MeltLayer(magma_store=store, embed_fn=embed_fn) # Retire cluster cluster = { "fragments": [ {"id": "f1", "text": "First fragment"}, {"id": "f2", "text": "Second fragment"} ] } glyph = melt.retire_cluster(cluster) # Verify glyph structure assert glyph["id"].startswith("mglyph_") assert len(glyph["source_ids"]) == 2 assert "First fragment" in glyph["compressed_summary"] assert glyph["embedding"] == [0.1, 0.2, 0.3] assert glyph["resolution_state"] == "retired" # Verify stored in magma assert len(store.glyphs) == 1 assert store.glyphs[0] == glyph def test_multiple_retirements(self): """Test multiple cluster retirements.""" from warbler_cda.melt_layer import MeltLayer, MagmaStore store = MagmaStore() melt = MeltLayer(magma_store=store) # Retire multiple clusters for i in range(5): cluster = { "fragments": [{"id": f"f{i}", "text": f"Fragment {i}"}] } melt.retire_cluster(cluster) assert len(store.glyphs) == 5 # Select hot glyphs hot = store.select_hot(limit=3) assert len(hot) == 3