105 lines
2.7 KiB
Go
105 lines
2.7 KiB
Go
package contracts_test
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
|
|
"github.com/santhosh-tekuri/jsonschema/v6"
|
|
)
|
|
|
|
func TestV1BundleHashesAndOfflineFixtures(t *testing.T) {
|
|
const dir = "upstream/v1"
|
|
var manifest struct {
|
|
Files map[string]string `json:"files"`
|
|
}
|
|
if err := json.Unmarshal(readV1(t, dir+"/manifest.json"), &manifest); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
compiler := jsonschema.NewCompiler()
|
|
compiler.AssertFormat()
|
|
compiler.UseLoader(offlineLoader{})
|
|
for name, want := range manifest.Files {
|
|
raw := readV1(t, filepath.Join(dir, name))
|
|
sum := sha256.Sum256(raw)
|
|
if hex.EncodeToString(sum[:]) != want {
|
|
t.Fatalf("hash mismatch: %s", name)
|
|
}
|
|
if filepath.Ext(name) == ".json" && len(name) >= 12 && name[len(name)-12:] == ".schema.json" {
|
|
var value map[string]any
|
|
if err := json.Unmarshal(raw, &value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := compiler.AddResource(value["$id"].(string), value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
if err := filepath.WalkDir(dir, func(path string, entry os.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if entry.IsDir() {
|
|
return nil
|
|
}
|
|
name, err := filepath.Rel(dir, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if name != "manifest.json" {
|
|
if _, ok := manifest.Files[name]; !ok {
|
|
t.Errorf("unhashed file %s", name)
|
|
}
|
|
}
|
|
return nil
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var fixtures []struct {
|
|
File, Schema string
|
|
Valid bool
|
|
}
|
|
if err := json.Unmarshal(readV1(t, dir+"/fixtures.json"), &fixtures); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, fixture := range fixtures {
|
|
schema, err := compiler.Compile("https://go-sip.local/contracts/v1/" + fixture.Schema)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var value any
|
|
if err := json.Unmarshal(readV1(t, dir+"/"+fixture.File), &value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := schema.Validate(value); (err == nil) != fixture.Valid {
|
|
t.Fatalf("%s: %v", fixture.File, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestV1PythonGoJCSGolden(t *testing.T) {
|
|
var vectors []struct{ Name, Input, Canonical, SHA256 string }
|
|
if err := json.Unmarshal(readV1(t, "upstream/v1/jcs-golden.json"), &vectors); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, vector := range vectors {
|
|
t.Run(vector.Name, func(t *testing.T) {
|
|
canonical, err := jsoncanonicalizer.Transform([]byte(vector.Input))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(canonical) != vector.Canonical {
|
|
t.Fatalf("cross-language canonical bytes differ: %s", canonical)
|
|
}
|
|
sum := sha256.Sum256(canonical)
|
|
if hex.EncodeToString(sum[:]) != vector.SHA256 {
|
|
t.Fatal("cross-language digest mismatch")
|
|
}
|
|
})
|
|
}
|
|
}
|