package crypto import ( "testing" ) func TestGenerate(t *testing.T) { params := DefaultParams(Security128) tags := []string{"word", "punct", "space"} kp, err := Generate(params, tags, testFactory) if err != nil { t.Fatalf("Generate: %v", err) } if kp.Public.Basis == nil { t.Error("basis should not be nil") } if kp.Public.SporeHash == "" { t.Error("spore hash should not be empty") } if kp.Private.Lattice == nil { t.Error("private lattice should not be nil") } if kp.Private.ConstraintFactory == nil { t.Error("constraint factory should not be nil") } } func TestGenerateDimension(t *testing.T) { params := DefaultParams(Security128) tags := []string{"word", "punct"} kp, err := Generate(params, tags, testFactory) if err != nil { t.Fatalf("Generate: %v", err) } // N=256, 2 tags, 128 nodes per tag = 256 total. if kp.Private.Lattice.Size() != 256 { t.Errorf("lattice size = %d, want 256", kp.Private.Lattice.Size()) } if kp.Public.Basis.Dimension != 256 { t.Errorf("basis dimension = %d, want 256", kp.Public.Basis.Dimension) } } func TestGenerateHasOccupancy(t *testing.T) { params := DefaultParams(Security128) tags := []string{"word", "punct"} kp, err := Generate(params, tags, testFactory) if err != nil { t.Fatalf("Generate: %v", err) } occ := occupiedCount(kp.Private.Lattice) if occ == 0 { t.Error("generated lattice should have occupied nodes") } // Should have meaningful occupancy (seeded ~50%). if occ < kp.Private.Lattice.Size()/4 { t.Errorf("occupancy too low: %d / %d", occ, kp.Private.Lattice.Size()) } } func TestGenerateInvalidParams(t *testing.T) { _, err := Generate(Params{}, []string{"word"}, testFactory) if err == nil { t.Error("expected error with invalid params") } } func TestGenerateNoTags(t *testing.T) { _, err := Generate(DefaultParams(Security128), nil, testFactory) if err == nil { t.Error("expected error with no tags") } } func TestGenerateNilFactory(t *testing.T) { _, err := Generate(DefaultParams(Security128), []string{"word"}, nil) if err == nil { t.Error("expected error with nil factory") } } func TestCloneLattice(t *testing.T) { l := buildMatureLattice() srcOcc := occupiedCount(l) srcSize := l.Size() clone := cloneLattice(l, testFactory) if clone.Size() != srcSize { t.Errorf("clone size = %d, want %d", clone.Size(), srcSize) } cloneOcc := occupiedCount(clone) if cloneOcc != srcOcc { t.Errorf("clone occupancy = %d, want %d", cloneOcc, srcOcc) } // Mutating the clone should not affect the original. clone.Nodes()[0].Dissolve() if occupiedCount(l) != srcOcc { t.Error("dissolving clone node affected original lattice") } } func TestCloneLatticeNeighbors(t *testing.T) { l := buildMatureLattice() clone := cloneLattice(l, testFactory) // Check that neighbor relationships are preserved. for i, n := range l.Nodes() { srcNbCount := len(n.Neighbors()) cloneNbCount := len(clone.Nodes()[i].Neighbors()) if srcNbCount != cloneNbCount { t.Errorf("node %d: src neighbors=%d, clone neighbors=%d", i, srcNbCount, cloneNbCount) } } }