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.
118 lines
3.7 KiB
118 lines
3.7 KiB
package capsule_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"testing"
|
|
|
|
"g.activething.com/go/DateKeys/capsule"
|
|
"g.activething.com/go/DateKeys/extension"
|
|
"g.activething.com/go/DateKeys/internal/testkit"
|
|
)
|
|
|
|
const mutationsFile = "../testdata/vectors/mutations.json"
|
|
|
|
// build returns a capsule made by testkit.Build and the options to open it.
|
|
func build(t *testing.T, b testkit.Build) ([]byte, capsule.OpenOptions) {
|
|
t.Helper()
|
|
if b.Plaintext == nil {
|
|
b.Plaintext = []byte("malicious creator")
|
|
}
|
|
out, err := b.Make()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return out.DKC, capsule.OpenOptions{Registry: testkit.Registry(), Source: testkit.NewSource(testkit.Release(1000)), Now: testkit.Fixed(testkit.Genesis().AddDate(1, 0, 0))}
|
|
}
|
|
|
|
// Spec §64: every mutation of the corpus (testkit.Mutations), built afresh,
|
|
// fails with its exact normative error at its exact step, or opens with its
|
|
// verdicts, and a failure before the release request causes no request. The
|
|
// thirty-three mutations of the first two lists of spec §64 are there once
|
|
// for each format, and those of the lists of formats 2 and 3 once.
|
|
func TestMutationCorpus(t *testing.T) {
|
|
e, err := testkit.NewMutationEnv(fixtureDir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
n := 0
|
|
for _, m := range testkit.Mutations() {
|
|
if m.Spec {
|
|
n++
|
|
}
|
|
t.Run(m.Name, func(t *testing.T) {
|
|
in, err := m.Make(e)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := m.Check(in); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
})
|
|
}
|
|
if want := 3*testkit.SpecMutationsPerFormat + testkit.Format2SpecMutations + testkit.Format3SpecMutations; n != want {
|
|
t.Fatalf("spec §64 gives %d mutations, the corpus has %d", want, n)
|
|
}
|
|
}
|
|
|
|
// The exported corpus, testdata/vectors/mutations.json, holds every mutation
|
|
// of the corpus in order, and replaying each case from the file alone gives
|
|
// exactly the recorded error and step. The capsules that are not built with
|
|
// randomness are the ones the corpus derives from the fixtures.
|
|
func TestExportedMutationCorpus(t *testing.T) {
|
|
var f testkit.MutationFile
|
|
if err := testkit.ReadJSON(mutationsFile, &f); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
e, err := testkit.NewMutationEnv(fixtureDir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
muts := testkit.Mutations()
|
|
if len(f.Cases) != len(muts) {
|
|
t.Fatalf("%d exported cases, the corpus has %d mutations", len(f.Cases), len(muts))
|
|
}
|
|
for i, c := range f.Cases {
|
|
m := muts[i]
|
|
t.Run(c.Name, func(t *testing.T) {
|
|
if c.Name != m.Name || c.Spec != m.Spec || c.Error != m.Code() || c.Step != m.Step || c.Network != m.Network || c.Frozen != m.Random ||
|
|
(c.Verdicts != nil) != (m.Verdicts != nil) {
|
|
t.Fatalf("exported case %+v does not match mutation %q", c, m.Name)
|
|
}
|
|
if err := c.Check(fixtureDir); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if m.Random {
|
|
if c.DKC.Base != "" {
|
|
t.Fatal("a frozen capsule must not depend on a fixture")
|
|
}
|
|
return
|
|
}
|
|
want, err := m.Make(e)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := c.Input(fixtureDir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(got.DKC, want.DKC) || !bytes.Equal(got.DKK, want.DKK) {
|
|
t.Fatal("the exported capsule or .dkk differs from the one the mutation derives")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Known critical extensions are accepted when the application declares them.
|
|
func TestKnownCriticalExtensions(t *testing.T) {
|
|
crit := []extension.Extension{{ID: "org.example.must-understand", Version: 1}}
|
|
for _, b := range []testkit.Build{{HeaderCritical: crit}, {ControlCritical: crit}} {
|
|
dkc, o := build(t, b)
|
|
o.Extensions = extension.Set{"org.example.must-understand": {1}}
|
|
var out bytes.Buffer
|
|
if _, err := capsule.Open(context.Background(), &out, bytes.NewReader(dkc), o); err != nil || out.String() != "malicious creator" {
|
|
t.Fatalf("known critical extension rejected: %v", err)
|
|
}
|
|
}
|
|
}
|