You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/internal/testkit/testkit_test.go

153 lines
5.0 KiB

package testkit_test
import (
"bytes"
"encoding/hex"
"encoding/json"
"testing"
"g.activething.com/go/DateKeys/internal/testkit"
"g.activething.com/go/DateKeys/profile"
)
func TestEdits(t *testing.T) {
base := []byte("0123456789")
for _, tc := range []struct {
out string
want string // JSON of Splice(base, out)
}{
{"0123456789", `[]`},
{"01X3456789", `[[2,1,"58"]]`},
{"012", `[[3,7,""]]`},
{"", `[[0,10,""]]`},
{"01234567890", `[[10,0,"30"]]`},
{"0123XY456789", `[[4,0,"5859"]]`},
} {
edits := testkit.Splice(base, []byte(tc.out))
if edits == nil {
edits = []testkit.Edit{}
}
b, err := json.Marshal(edits)
if err != nil || string(b) != tc.want {
t.Errorf("Splice(%q) = %s, %v; want %s", tc.out, b, err, tc.want)
}
var back []testkit.Edit
if err := json.Unmarshal(b, &back); err != nil {
t.Fatal(err)
}
out, err := testkit.ApplyEdits(base, back)
if err != nil || string(out) != tc.out {
t.Errorf("ApplyEdits(%s) = %q, %v; want %q", b, out, err, tc.out)
}
}
// Several edits refer to offsets of the base.
out, err := testkit.ApplyEdits(base, []testkit.Edit{{At: 1, Delete: 1, Insert: []byte("ab")}, {At: 5, Delete: 2}, {At: 10, Insert: []byte("!")}})
if err != nil || string(out) != "0ab234789!" {
t.Fatalf("got %q, %v", out, err)
}
for _, bad := range [][]testkit.Edit{
{{At: 5, Delete: 1}, {At: 2, Delete: 1}}, // out of order
{{At: 2, Delete: 3}, {At: 4, Delete: 1}}, // overlapping
{{At: 9, Delete: 2}}, // beyond the base
{{At: -1}},
} {
if _, err := testkit.ApplyEdits(base, bad); err == nil {
t.Errorf("ApplyEdits accepted %v", bad)
}
}
for _, bad := range []string{`[1,2]`, `[1,2,"zz"]`, `["1",2,""]`, `{}`} {
var e testkit.Edit
if err := json.Unmarshal([]byte(bad), &e); err == nil {
t.Errorf("Edit accepted %s", bad)
}
}
}
// The re-encodings of the point mutations (spec §12.2) change only what their
// names say, and x + p fits for XPlusPRound only among the known rounds.
func TestPointReencodings(t *testing.T) {
sig := testkit.Release(testkit.XPlusPRound).Signature
xp, err := testkit.AddModulus(sig, 0)
if err != nil {
t.Fatal(err)
}
if xp[0]&0xe0 != sig[0]&0xe0 || bytes.Equal(xp, sig) || !bytes.Equal(testkit.ReduceCoordinate(xp, 0), sig) {
t.Fatalf("x + p of %x is %x", sig, xp)
}
for _, r := range testkit.Rounds {
if _, err := testkit.AddModulus(testkit.Release(r).Signature, 0); (err == nil) != (r == testkit.XPlusPRound) {
t.Errorf("round %d: x + p fits: %v", r, err == nil)
}
}
key := profile.Quicknet().PublicKey
for _, at := range []int{0, testkit.CoordinateLen} {
k, err := testkit.AddModulus(key, at)
if err != nil {
t.Fatalf("coordinate at %d of the Quicknet key: %v", at, err)
}
other := testkit.CoordinateLen - at
if !bytes.Equal(k[other:other+testkit.CoordinateLen], key[other:other+testkit.CoordinateLen]) || !bytes.Equal(testkit.ReduceCoordinate(k, at), key) {
t.Fatalf("coordinate at %d: %x", at, k)
}
}
for _, at := range []int{-48, 1, testkit.CoordinateLen} {
if _, err := testkit.AddModulus(sig, at); err == nil {
t.Errorf("offset %d of a G1 point accepted", at)
}
}
if n := testkit.Negated(sig); n[0]^sig[0] != testkit.FlagSort || !bytes.Equal(n[1:], sig[1:]) || !bytes.Equal(testkit.Negated(n), sig) {
t.Fatalf("negated %x", n)
}
if i := testkit.InfinityWithPayload(sig); i[0] != 0xc0|sig[0]&0x1f || !bytes.Equal(i[1:], sig[1:]) {
t.Fatalf("infinity with payload %x", i)
}
if i := testkit.Infinity(96); len(i) != 96 || i[0] != 0xc0 || !bytes.Equal(i[1:], make([]byte, 95)) {
t.Fatalf("infinity %x", i)
}
}
// The schema vectors of testdata/vectors/cbor.json replay: the decoder of each
// schema gives exactly the recorded result.
func TestSchemaVectors(t *testing.T) {
var f testkit.CBORVectorFile
if err := testkit.ReadJSON("../../testdata/vectors/cbor.json", &f); err != nil {
t.Fatal(err)
}
blocks := map[string]int{}
for _, v := range f.Schemas {
b, err := hex.DecodeString(v.Hex)
if err != nil {
t.Fatal(err)
}
if got := testkit.Result(testkit.DecodeSchema(v.Schema, b)); got != v.Result {
t.Errorf("%s %q: got %s, want %s", v.Block, v.Name, got, v.Result)
}
blocks[v.Block]++
}
for _, b := range []string{testkit.SchemaProfile, testkit.SchemaHeader, testkit.SchemaControl, testkit.SchemaDKKBody, "verification_metadata", "extension"} {
if blocks[b] < 5 {
t.Errorf("block %s has %d vectors", b, blocks[b])
}
}
if err := testkit.DecodeSchema("nope", nil); err == nil {
t.Error("unknown schema accepted")
}
}
// The committed vector files are what the generators compute now.
func TestVectorFilesAreCurrent(t *testing.T) {
want, err := testkit.CBORVectors()
if err != nil {
t.Fatal(err)
}
var got testkit.CBORVectorFile
if err := testkit.ReadJSON("../../testdata/vectors/cbor.json", &got); err != nil {
t.Fatal(err)
}
a, _ := json.Marshal(want)
b, _ := json.Marshal(got)
if !bytes.Equal(a, b) {
t.Error("testdata/vectors/cbor.json is stale: run go run ./internal/testkit/genfixtures -out testdata")
}
}

Powered by TurnKey Linux.