package wordkey import ( "encoding/hex" "slices" "strings" "testing" "g.activething.com/go/DateKeys/profile" ) func TestNormalize(t *testing.T) { nbsp, tab := string(rune(0xa0)), string(rune(9)) in := " Ábaco" + nbsp + "ÁRBOL" + tab + "niño ΣΑΣ İ " want := []string{"abaco", "arbol", "nino", "σασ", "i"} if got := Normalize(in); !slices.Equal(got, want) { t.Fatalf("Normalize = %q, want %q", got, want) } if got := Normalize(" "); len(got) != 0 { t.Fatalf("Normalize of spaces = %q", got) } // The lower case of Unicode 18.0.0, not that of the runtime: U+A7CB, // added in Unicode 16.0, lowers to U+0264, which Go 1.26 does not know. if got := Normalize(string(rune(0xA7CB))); !slices.Equal(got, []string{string(rune(0x0264))}) { t.Fatalf("Normalize of U+A7CB = %q", got) } } func TestCheck(t *testing.T) { if err := Check(Normalize("Perro LUNA casa verde trén mar")); err != nil { t.Fatal(err) } const six = "perro luna casa verde tren mar" for _, tc := range []struct{ text, want string }{ {"uno dos tres", "not 3"}, {"a b c d e f g h", "not 0"}, {"perro perro perro perro perro perro", "not 1"}, {"de la casa al mar en tren verde", "not 4"}, {six + string(rune(0x200B)), "invisible character U+200B"}, {six + string(rune(0x0001)), "control character U+0001"}, {six + string(rune(0x0378)), "U+0378, unassigned"}, } { if err := Check(Normalize(tc.text)); err == nil || !strings.Contains(err.Error(), tc.want) { t.Errorf("Check(%q) = %v, want %q", tc.text, err, tc.want) } } } // The vector of spec §38.1, which wordkey.test.ts of datekeys-ts checks too. func TestKeyVector(t *testing.T) { chain, _ := hex.DecodeString(profile.QuicknetChainHash) capsuleID, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f") words := Normalize("perro luna casa verde tren mar") raw, err := Key(words, chain, 1000, capsuleID) if err != nil { t.Fatal(err) } if got := hex.EncodeToString(raw); got != "fceec4d8ca8de86c85a1f26ed49f82a2b38431bd0ce36db995ae7dfd49b96e41" { t.Fatalf("Key = %s", got) } id, err := Identity(words, chain, 1000, capsuleID) if err != nil { t.Fatal(err) } otherCapsule := slices.Clone(capsuleID) otherCapsule[15] ^= 1 for _, o := range []struct { name string round uint64 id []byte }{{"round", 1001, capsuleID}, {"capsule_id", 1000, otherCapsule}} { other, err := Identity(words, chain, o.round, o.id) if err != nil { t.Fatal(err) } if id.Recipient().String() == other.Recipient().String() { t.Errorf("the %s does not change the key", o.name) } } }