Require candidate decoders for artifact codecs
This commit is contained in:
@@ -21,6 +21,7 @@ const (
|
||||
var schemaAssets embed.FS
|
||||
|
||||
var _ contracts.ArtifactCodec[dnd.CombatTurnList] = (*Codec)(nil)
|
||||
var _ contracts.CandidateArtifactCodec[dnd.CombatTurnList] = (*Codec)(nil)
|
||||
|
||||
type Codec struct{}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ const (
|
||||
var schemaAssets embed.FS
|
||||
|
||||
var _ contracts.ArtifactCodec[dnd.EnemyEventList] = (*Codec)(nil)
|
||||
var _ contracts.CandidateArtifactCodec[dnd.EnemyEventList] = (*Codec)(nil)
|
||||
|
||||
type Codec struct{}
|
||||
|
||||
|
||||
@@ -82,13 +82,16 @@ func TestCodecDefensivelyOwnsValuesAndDefersSemanticValidation(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
decoded, err := codec.Decode(content)
|
||||
decoded, err := codec.DecodeCandidate(content)
|
||||
if err != nil || !reflect.DeepEqual(decoded, candidate) {
|
||||
t.Fatalf("Decode() = %#v, %v; want semantic candidate preservation", decoded, err)
|
||||
t.Fatalf("DecodeCandidate() = %#v, %v; want semantic candidate preservation", decoded, err)
|
||||
}
|
||||
decoded.Events[0].SourceRefs[0].SourceID = "changed"
|
||||
if candidate.Events[0].SourceRefs[0].SourceID != "" {
|
||||
t.Fatal("Decode() retained caller-owned source references")
|
||||
t.Fatal("DecodeCandidate() retained caller-owned source references")
|
||||
}
|
||||
if decoded, err := codec.Decode(content); err != nil || !reflect.DeepEqual(decoded, candidate) {
|
||||
t.Fatalf("Decode() = %#v, %v; want durable decode behavior", decoded, err)
|
||||
}
|
||||
|
||||
first := codec.Schema()
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
var schemaAssets embed.FS
|
||||
|
||||
var _ contracts.ArtifactCodec[dnd.SceneDescriptionList] = (*Codec)(nil)
|
||||
var _ contracts.CandidateArtifactCodec[dnd.SceneDescriptionList] = (*Codec)(nil)
|
||||
|
||||
type Codec struct{}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ const (
|
||||
var schemaAssets embed.FS
|
||||
|
||||
var _ contracts.ArtifactCodec[dnd.SpellList] = (*Codec)(nil)
|
||||
var _ contracts.CandidateArtifactCodec[dnd.SpellList] = (*Codec)(nil)
|
||||
|
||||
type Codec struct{}
|
||||
|
||||
|
||||
@@ -114,6 +114,10 @@ func TestCodecEncodesIncompleteCandidateWithoutWeakeningFinalEncoding(t *testing
|
||||
if !json.Valid(content) {
|
||||
t.Fatalf("EncodeCandidate() = %q, want JSON", content)
|
||||
}
|
||||
decoded, err := codec.DecodeCandidate(content)
|
||||
if err != nil || !reflect.DeepEqual(decoded, candidate) {
|
||||
t.Fatalf("DecodeCandidate() = %#v, %v; want %#v", decoded, err, candidate)
|
||||
}
|
||||
result, err := spellshape.New(spellshape.Options{}).Validate(context.Background(), contracts.TypedValidationRequest[dnd.SpellList]{Value: candidate})
|
||||
if err != nil || result.Approved || result.ReasonCode != spellshape.ReasonCode {
|
||||
t.Fatalf("shape validation = %#v, %v; want candidate rejection", result, err)
|
||||
@@ -121,6 +125,9 @@ func TestCodecEncodesIncompleteCandidateWithoutWeakeningFinalEncoding(t *testing
|
||||
if _, err := codec.Encode(candidate); err == nil || !strings.Contains(err.Error(), "spell_casts must be present") {
|
||||
t.Fatalf("Encode() error = %v, want strict final shape error", err)
|
||||
}
|
||||
if _, err := codec.Decode(content); err == nil || !strings.Contains(err.Error(), "spell_casts must be present") {
|
||||
t.Fatalf("Decode() error = %v, want strict final shape error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodecSchemaIsMutationSafe(t *testing.T) {
|
||||
|
||||
@@ -164,3 +164,7 @@ func (seriatimArtifactCodec) Decode(content []byte) (seriatimArtifact, error) {
|
||||
err := json.Unmarshal(content, &value)
|
||||
return value, err
|
||||
}
|
||||
|
||||
func (codec seriatimArtifactCodec) DecodeCandidate(content []byte) (seriatimArtifact, error) {
|
||||
return codec.Decode(content)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user