package profile_test import ( "errors" "maps" "testing" datekeys "g.activething.com/go/DateKeys" "g.activething.com/go/DateKeys/internal/cbortest" "g.activething.com/go/DateKeys/profile" ) // Spec §11, §58: the Provider Profile is the closed map of keys 0 to 10, all // required, in ascending order. func TestDecodeStructure(t *testing.T) { b, _ := profile.Quicknet().CanonicalCBOR() m, err := cbortest.UnmarshalMap(b) if err != nil { t.Fatal(err) } encode := func(v any) []byte { out, err := cbortest.Marshal(v) if err != nil { t.Fatal(err) } return out } with := func(edit func(m map[uint64]any)) []byte { c := maps.Clone(m) edit(c) return encode(c) } for name, in := range map[string][]byte{ "missing scheme": with(func(c map[uint64]any) { delete(c, 9) }), "key 11 for key 10": with(func(c map[uint64]any) { c[11] = c[10]; delete(c, 10) }), "twelve entries": with(func(c map[uint64]any) { c[11] = uint64(0) }), "chain hash of 31": with(func(c map[uint64]any) { c[5] = make([]byte, 31) }), "genesis seed of 33": with(func(c map[uint64]any) { c[10] = make([]byte, 33) }), "public key as text": with(func(c map[uint64]any) { c[6] = "key" }), "profile_id as bytes": with(func(c map[uint64]any) { c[2] = []byte("datekeys:quicknet:v1") }), "text key after key 1": encode(cbortest.Pairs{uint64(0), profile.TypeTag, uint64(1), uint64(1), "2", "datekeys:quicknet:v1"}), "null period": with(func(c map[uint64]any) { c[7] = nil }), "invalid UTF-8 network": with(func(c map[uint64]any) { c[4] = "quick\xffnet" }), } { if _, err := profile.Decode(in); !errors.Is(err, datekeys.ErrNonCanonicalCBOR) { t.Errorf("%s: %v", name, err) } } // The encoder refuses a name that is not valid UTF-8, with the same code: // it cannot be written as a CBOR text string. p := profile.Quicknet() p.Network = "quick\xffnet" if _, err := p.CanonicalCBOR(); !errors.Is(err, datekeys.ErrNonCanonicalCBOR) { t.Fatalf("invalid UTF-8 encoded: %v", err) } }