fix(hash): repair the tests after #14093 and #14215 merged in reverse order

The plan documented in both PRs had #14215 land first, then #14093's
compose-go bump delete the transient TestServiceHashContinuity. Merged
in the opposite order, main's pkg/compose tests no longer even compile:
richServiceFixture sets fields the container-spec layering turned into
promoted embeds (struct literals require go1.27 for that), and once
compilable two tests fail by construction.

- richServiceFixture is built by assignment;
- TestServiceHashContinuity is deleted, exactly as its own comment
  prescribes: the layered compose-go is the reorder it existed to
  outlive, its proof duty (pinned == historical bytes) is done, and
  TestHashGoldenValues carries the continuity contract alone — it
  PASSES on the layered compose-go, confirming the pinning preserved
  every historical hash through the layering;
- pull_refresh_after, newly exposed at the service root, is appended
  to serviceHashKeyOrder: the fallback already emitted it in that
  exact position, so no hash moves — listing it only freezes the
  layout and satisfies the coverage walker.

Signed-off-by: Nicolas De Loof <[email protected]>
This commit is contained in:
Nicolas De Loof
2026-09-22 11:03:06 +02:00
committed by Guillaume Lours
parent 0c68d08f26
commit 6b419bc7a1
2 changed files with 31 additions and 44 deletions
+4
View File
@@ -141,6 +141,10 @@ var serviceHashKeyOrder = []string{
"pre_start",
"post_start",
"pre_stop",
// appended when the compose-go container-spec layering exposed it (the
// merge order made the fallback place it here already: listing it is a
// no-op for every hash, it only freezes the position)
"pull_refresh_after",
}
// trimServiceHashFields removes the attributes deliberately excluded from the
+27 -44
View File
@@ -23,7 +23,6 @@ import (
"testing"
"github.com/compose-spec/compose-go/v2/types"
"github.com/opencontainers/go-digest"
"gotest.tools/v3/assert"
)
@@ -45,52 +44,36 @@ func serviceConfig(replicas int) types.ServiceConfig {
}
}
// TestServiceHashContinuity proves the pinned serializer reproduces the
// historical bytes: while compose-go's struct order still matches the frozen
// list — true on this branch's compose-go — the pinned hash and the plain
// struct-marshal hash are byte-identical. The compose-go upgrade that first
// reorders the struct (the container-spec layering) deletes this test in the
// same commit: from that point the frozen list carries continuity alone,
// locked by TestHashGoldenValues.
func TestServiceHashContinuity(t *testing.T) {
svc := richServiceFixture()
pinned, err := ServiceHash(svc)
assert.NilError(t, err)
raw, err := json.Marshal(trimServiceHashFields(svc))
assert.NilError(t, err)
legacy := digest.SHA256.FromBytes(raw).Encoded()
assert.Equal(t, pinned, legacy)
t.Logf("GOLDEN service=%s", pinned)
}
func richServiceFixture() types.ServiceConfig {
replicas := 3
return types.ServiceConfig{
Name: "web",
Image: "nginx:latest",
Command: types.ShellCommand{"nginx", "-g", "daemon off;"},
User: "nobody",
Tty: true,
StdinOpen: true,
Restart: types.RestartPolicyAlways,
Environment: types.MappingWithEquals{"A": strPtr("1"), "B": nil},
Labels: types.Labels{"com.example": "v"},
Annotations: types.Mapping{"note": "x"},
CapAdd: []string{"NET_ADMIN"},
ExtraHosts: types.HostsList{"alpha": []string{"10.0.0.1"}},
Deploy: &types.DeployConfig{Replicas: &replicas},
Ports: []types.ServicePortConfig{
{Target: 80, Published: "8080", Protocol: "tcp"},
},
HealthCheck: &types.HealthCheckConfig{
Test: types.HealthCheckTest{"CMD", "true"},
},
Volumes: []types.ServiceVolumeConfig{
{Type: types.VolumeTypeVolume, Source: "data", Target: "/data"},
},
Networks: map[string]*types.ServiceNetworkConfig{"default": nil},
// built by assignment: most of these are fields promoted from the
// embedded ContainerSpec since the compose-go layering, which struct
// literals cannot set before go1.27
var svc types.ServiceConfig
svc.Name = "web"
svc.Image = "nginx:latest"
svc.Command = types.ShellCommand{"nginx", "-g", "daemon off;"}
svc.User = "nobody"
svc.Tty = true
svc.StdinOpen = true
svc.Restart = types.RestartPolicyAlways
svc.Environment = types.MappingWithEquals{"A": strPtr("1"), "B": nil}
svc.Labels = types.Labels{"com.example": "v"}
svc.Annotations = types.Mapping{"note": "x"}
svc.CapAdd = []string{"NET_ADMIN"}
svc.ExtraHosts = types.HostsList{"alpha": []string{"10.0.0.1"}}
svc.Deploy = &types.DeployConfig{Replicas: &replicas}
svc.Ports = []types.ServicePortConfig{
{Target: 80, Published: "8080", Protocol: "tcp"},
}
svc.HealthCheck = &types.HealthCheckConfig{
Test: types.HealthCheckTest{"CMD", "true"},
}
svc.Volumes = []types.ServiceVolumeConfig{
{Type: types.VolumeTypeVolume, Source: "data", Target: "/data"},
}
svc.Networks = map[string]*types.ServiceNetworkConfig{"default": nil}
return svc
}
func strPtr(s string) *string { return &s }