package datekeys_test import ( "errors" "fmt" "os" "strings" "testing" datekeys "g.activething.com/go/DateKeys" ) // The catalogue matches spec ยง69 exactly, in order. func TestCatalogueMatchesSpec(t *testing.T) { spec, err := os.ReadFile("spec/DateKeys_Protocol_Specification_v" + datekeys.SpecVersion + ".md") if err != nil { t.Fatal(err) } s := string(spec) start := strings.Index(s, "## 69. Errores normativos") end := strings.Index(s, "## 70.") if start < 0 || end < start { t.Fatal("section 69 not found") } var want []string for _, line := range strings.Split(s[start:end], "\n") { if line = strings.TrimSpace(line); strings.HasPrefix(line, "ERR_") { want = append(want, line) } } var got []string for _, e := range datekeys.All() { got = append(got, e.Code()) } if strings.Join(got, ",") != strings.Join(want, ",") { t.Fatalf("catalogue\n got %v\nwant %v", got, want) } } func TestCode(t *testing.T) { err := fmt.Errorf("capsule: step 8: %w", fmt.Errorf("agewrap: %w", datekeys.ErrRoundMismatch)) if datekeys.Code(err) != "ERR_ROUND_MISMATCH" || !errors.Is(err, datekeys.ErrRoundMismatch) || errors.Is(err, datekeys.ErrIntegrity) { t.Fatal("wrapping") } // The failure of a relay kept as text, as provider/drand.Client keeps // it, adds no code: the error wraps exactly one normative error. relays := fmt.Errorf("drand: no relay returned a verified release for round 1000: %v: %w", fmt.Errorf("relay: %w", datekeys.ErrRoundMismatch), datekeys.ErrReleaseUnavailable) if datekeys.Code(relays) != "ERR_RELEASE_UNAVAILABLE" || errors.Is(relays, datekeys.ErrRoundMismatch) || !strings.Contains(relays.Error(), "ERR_ROUND_MISMATCH") { t.Fatal("a failure kept as text") } // No error of this module wraps two codes. For one from elsewhere, such // as the error of a caller's release source, Code returns the first in // the tree. joined := fmt.Errorf("source: %w: %w", datekeys.ErrReleaseUnavailable, errors.Join(errors.New("x"), datekeys.ErrReleaseInvalid)) if datekeys.Code(joined) != "ERR_RELEASE_UNAVAILABLE" { t.Fatal("joined errors") } if datekeys.Code(errors.New("plain")) != "" || datekeys.Code(nil) != "" { t.Fatal("non-DateKeys errors have no code") } if datekeys.ErrIntegrity.Error() != "ERR_INTEGRITY" { t.Fatal("message") } data := fmt.Errorf("capsule: step 4: %w", datekeys.ErrExtensionDataInvalid) if datekeys.Code(data) != "ERR_EXTENSION_DATA_INVALID" || errors.Is(data, datekeys.ErrExtensionCriticalUnknown) { t.Fatal("ERR_EXTENSION_DATA_INVALID") } }