Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
182
backend/internal/home/in_flight_contract_test.go
Normal file
182
backend/internal/home/in_flight_contract_test.go
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
package home
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCredentialInFlightWireContractFixture(t *testing.T) {
|
||||
raw, errRead := os.ReadFile(filepath.Join("testdata", "credential_in_flight_contract.json"))
|
||||
if errRead != nil {
|
||||
t.Fatalf("ReadFile() error = %v", errRead)
|
||||
}
|
||||
fixture, errDecode := decodeInFlightContractFixture(raw)
|
||||
if errDecode != nil {
|
||||
t.Fatalf("decodeInFlightContractFixture() error = %v", errDecode)
|
||||
}
|
||||
if fixture.Part.Kind != InFlightFramePart || fixture.Part.PartIndex == nil || *fixture.Part.PartIndex != 0 || fixture.Part.PartCount == nil || *fixture.Part.PartCount != 1 {
|
||||
t.Fatalf("part = %#v", fixture.Part)
|
||||
}
|
||||
if fixture.Part.Aggregates[0].Status != InFlightAccounted || fixture.Part.Aggregates[1].Status != InFlightUnaccounted {
|
||||
t.Fatalf("statuses = %#v", fixture.Part.Aggregates)
|
||||
}
|
||||
if fixture.Overflow.Kind != InFlightFrameOverflow || fixture.Overflow.AggregateGroupCount != 100001 {
|
||||
t.Fatalf("overflow = %#v", fixture.Overflow)
|
||||
}
|
||||
assertInFlightContractFields(t)
|
||||
assertRequiredInFlightJSONKeys(t, raw, []string{"config", "part", "overflow"})
|
||||
assertInFlightFixtureKeys(t, fixture)
|
||||
}
|
||||
|
||||
func TestCredentialInFlightWireContractRejectsInvalidJSON(t *testing.T) {
|
||||
raw, errRead := os.ReadFile(filepath.Join("testdata", "credential_in_flight_contract.json"))
|
||||
if errRead != nil {
|
||||
t.Fatalf("ReadFile() error = %v", errRead)
|
||||
}
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
raw []byte
|
||||
}{
|
||||
{name: "unknown frame owner field", raw: bytes.Replace(raw, []byte(`"kind": "part"`), []byte(`"kind": "part", "node_id": "node-a"`), 1)},
|
||||
{name: "unknown aggregate owner field", raw: bytes.Replace(raw, []byte(`"credential_id": "cred-a"`), []byte(`"credential_id": "cred-a", "fingerprint": "owner"`), 1)},
|
||||
{name: "unknown detail secret field", raw: bytes.Replace(raw, []byte(`"request_id": "req-1"`), []byte(`"request_id": "req-1", "secret": "secret"`), 1)},
|
||||
{name: "unknown overflow secret field", raw: bytes.Replace(raw, []byte(`"aggregate_group_count": 100001`), []byte(`"aggregate_group_count": 100001, "api_key": "secret"`), 1)},
|
||||
{name: "trailing JSON", raw: append(append([]byte{}, raw...), []byte(` {"part": {}}`)...)},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if _, errDecode := decodeInFlightContractFixture(test.raw); errDecode == nil {
|
||||
t.Fatal("decodeInFlightContractFixture() error = nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type inFlightContractFixture struct {
|
||||
Part InFlightSnapshotFrame
|
||||
Overflow InFlightSnapshotFrame
|
||||
PartJSON json.RawMessage
|
||||
OverflowJSON json.RawMessage
|
||||
}
|
||||
|
||||
func decodeInFlightContractFixture(raw []byte) (inFlightContractFixture, error) {
|
||||
var fixture inFlightContractFixture
|
||||
var document struct {
|
||||
Config json.RawMessage `json:"config"`
|
||||
Part InFlightSnapshotFrame `json:"part"`
|
||||
Overflow InFlightSnapshotFrame `json:"overflow"`
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewReader(raw))
|
||||
decoder.DisallowUnknownFields()
|
||||
if errDecode := decoder.Decode(&document); errDecode != nil {
|
||||
return fixture, errDecode
|
||||
}
|
||||
if errDecode := decoder.Decode(&struct{}{}); errDecode == nil {
|
||||
return fixture, errors.New("unexpected trailing JSON")
|
||||
} else if errDecode != io.EOF {
|
||||
return fixture, errDecode
|
||||
}
|
||||
documentRaw := struct {
|
||||
Part json.RawMessage `json:"part"`
|
||||
Overflow json.RawMessage `json:"overflow"`
|
||||
}{}
|
||||
if errDecode := json.Unmarshal(raw, &documentRaw); errDecode != nil {
|
||||
return fixture, errDecode
|
||||
}
|
||||
fixture.Part = document.Part
|
||||
fixture.Overflow = document.Overflow
|
||||
fixture.PartJSON = documentRaw.Part
|
||||
fixture.OverflowJSON = documentRaw.Overflow
|
||||
return fixture, nil
|
||||
}
|
||||
|
||||
func assertInFlightContractFields(t *testing.T) {
|
||||
t.Helper()
|
||||
assertOrderedInFlightJSONFields(t, reflect.TypeOf(InFlightSnapshotFrame{}), []inFlightJSONField{
|
||||
{name: "Kind", tag: "kind"},
|
||||
{name: "Revision", tag: "revision"},
|
||||
{name: "ObservedAt", tag: "observed_at"},
|
||||
{name: "BarrierRevision", tag: "barrier_revision"},
|
||||
{name: "PartIndex", tag: "part_index,omitempty"},
|
||||
{name: "PartCount", tag: "part_count,omitempty"},
|
||||
{name: "DetailsTruncated", tag: "details_truncated,omitempty"},
|
||||
{name: "Aggregates", tag: "aggregates,omitempty"},
|
||||
{name: "Details", tag: "details,omitempty"},
|
||||
{name: "AggregateGroupCount", tag: "aggregate_group_count,omitempty"},
|
||||
})
|
||||
assertOrderedInFlightJSONFields(t, reflect.TypeOf(InFlightAggregate{}), []inFlightJSONField{
|
||||
{name: "CredentialID", tag: "credential_id"},
|
||||
{name: "Model", tag: "model"},
|
||||
{name: "Status", tag: "status"},
|
||||
{name: "Count", tag: "count"},
|
||||
})
|
||||
assertOrderedInFlightJSONFields(t, reflect.TypeOf(InFlightRequestDetail{}), []inFlightJSONField{
|
||||
{name: "RequestID", tag: "request_id"},
|
||||
{name: "CredentialID", tag: "credential_id"},
|
||||
{name: "Model", tag: "model"},
|
||||
{name: "RequestKind", tag: "request_kind"},
|
||||
{name: "StartedAt", tag: "started_at"},
|
||||
})
|
||||
}
|
||||
|
||||
func assertInFlightFixtureKeys(t *testing.T, fixture inFlightContractFixture) {
|
||||
t.Helper()
|
||||
assertRequiredInFlightJSONKeys(t, fixture.PartJSON, []string{"kind", "revision", "observed_at", "barrier_revision", "part_index", "part_count", "details_truncated", "aggregates", "details"})
|
||||
assertRequiredInFlightJSONKeys(t, fixture.OverflowJSON, []string{"kind", "revision", "observed_at", "barrier_revision", "aggregate_group_count"})
|
||||
|
||||
var part struct {
|
||||
Aggregates []json.RawMessage `json:"aggregates"`
|
||||
Details []json.RawMessage `json:"details"`
|
||||
}
|
||||
if errDecode := json.Unmarshal(fixture.PartJSON, &part); errDecode != nil {
|
||||
t.Fatalf("json.Unmarshal() error = %v", errDecode)
|
||||
}
|
||||
for index, aggregate := range part.Aggregates {
|
||||
assertRequiredInFlightJSONKeys(t, aggregate, []string{"credential_id", "model", "status", "count"})
|
||||
if len(aggregate) == 0 {
|
||||
t.Fatalf("aggregate %d is empty", index)
|
||||
}
|
||||
}
|
||||
for index, detail := range part.Details {
|
||||
assertRequiredInFlightJSONKeys(t, detail, []string{"request_id", "credential_id", "model", "request_kind", "started_at"})
|
||||
if len(detail) == 0 {
|
||||
t.Fatalf("detail %d is empty", index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type inFlightJSONField struct {
|
||||
name string
|
||||
tag string
|
||||
}
|
||||
|
||||
func assertOrderedInFlightJSONFields(t *testing.T, structType reflect.Type, want []inFlightJSONField) {
|
||||
t.Helper()
|
||||
if structType.NumField() != len(want) {
|
||||
t.Fatalf("%s field count = %d, want %d", structType.Name(), structType.NumField(), len(want))
|
||||
}
|
||||
for index, expected := range want {
|
||||
field := structType.Field(index)
|
||||
if field.Name != expected.name || field.Tag.Get("json") != expected.tag {
|
||||
t.Fatalf("%s field %d = (%q, %q), want (%q, %q)", structType.Name(), index, field.Name, field.Tag.Get("json"), expected.name, expected.tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertRequiredInFlightJSONKeys(t *testing.T, raw json.RawMessage, required []string) {
|
||||
t.Helper()
|
||||
var fields map[string]json.RawMessage
|
||||
if errDecode := json.Unmarshal(raw, &fields); errDecode != nil {
|
||||
t.Fatalf("json.Unmarshal() error = %v", errDecode)
|
||||
}
|
||||
for _, key := range required {
|
||||
if _, ok := fields[key]; !ok {
|
||||
t.Fatalf("required JSON key %q is missing", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue