Ctrl K
ComunidadGuías…

internal/home/in_flight_contract_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
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)
		}
	}
}