From 610ee9bab0591964d8a7491e68599d3b7c9cf2b6 Mon Sep 17 00:00:00 2001
From: Julian Sommer <115516918+juliansommer@users.noreply.github.com>
Date: Wed, 30 Sep 2026 11:44:17 +1000
Subject: [PATCH] chore: use slices.Sorted
---
cmd/spinifex/cmd/admin_account_quota.go | 9 +++------
cmd/spinifex/cmd/admin_kv.go | 7 ++-----
cmd/spinifex/cmd/admin_kv_compare.go | 7 ++-----
internal/awsmodel/model.go | 7 +------
internal/awsmodel/page.go | 10 +++-------
spinifex/cloud/oci/fake.go | 14 ++++----------
spinifex/daemon/daemon.go | 6 +-----
.../gateway/conditionkeys_completeness_test.go | 7 +++----
spinifex/gateway/ec2.go | 1 +
spinifex/gateway/ec2_dryrun_test.go | 7 ++-----
spinifex/gateway/ec2_emptyresult_test.go | 4 ++++
spinifex/gateway/ecrapi/tags.go | 9 +++------
spinifex/handlers/ec2/instance/service_impl.go | 10 ++--------
spinifex/handlers/eks/addon_catalog.go | 7 ++-----
spinifex/loadgen/loadgen.go | 9 +++------
spinifex/loadgen/ops.go | 9 ++-------
spinifex/resource/resource_test.go | 8 ++------
spinifex/services/awsgw/awsgw.go | 7 +++----
spinifex/services/northstar/bootstrap.go | 10 +++-------
spinifex/systemd/reconcile.go | 9 ++-------
spinifex/utils/nats_trace.go | 8 +++-----
spinifex/vm/manager.go | 7 ++-----
spinifex/vm/manager_deps_test.go | 13 +++----------
spinifex/vm/mock/mock.go | 13 +++----------
tests/bench/ebsctl/compare.go | 9 +++------
tests/e2e/ddil/scenarios/coverage_drift_test.go | 10 +++-------
tests/e2e/harness/account.go | 10 +++-------
tests/e2e/harness/guest_data.go | 7 +++----
tests/e2e/kvquorum/node_loss_test.go | 8 +++-----
tests/e2e/manifest-lint/lint.go | 8 +++-----
tests/e2e/manifest-lint/subjects.go | 9 +++------
tests/e2e/single/guestchurn_test.go | 8 +++-----
tests/integration/conformance.go | 8 +++-----
tests/integration/conformance_policy.go | 10 +++-------
34 files changed, 89 insertions(+), 196 deletions(-)
diff --git a/cmd/spinifex/cmd/admin_account_quota.go b/cmd/spinifex/cmd/admin_account_quota.go
index 21b816caf..0d1f8f923 100644
--- a/cmd/spinifex/cmd/admin_account_quota.go
+++ b/cmd/spinifex/cmd/admin_account_quota.go
@@ -3,7 +3,8 @@ package cmd
import (
"context"
"fmt"
- "sort"
+ "maps"
+ "slices"
"strconv"
"github.com/mulgadc/spinifex/spinifex/gateway"
@@ -166,11 +167,7 @@ func printAccountQuota(resp *gateway.AccountQuotaResponse) {
fmt.Printf("%-16s %10s %s\n", "DIMENSION", "LIMIT", "SOURCE")
fmt.Printf("%-16s %10s %s\n", "---------", "-----", "------")
- names := make([]string, 0, len(resp.Limits))
- for name := range resp.Limits {
- names = append(names, name)
- }
- sort.Strings(names)
+ names := slices.Sorted(maps.Keys(resp.Limits))
for _, name := range names {
limit := strconv.Itoa(resp.Limits[name])
if resp.Limits[name] == handlers_quota.Unlimited {
diff --git a/cmd/spinifex/cmd/admin_kv.go b/cmd/spinifex/cmd/admin_kv.go
index 3dfb5c4a7..bc5baf73c 100644
--- a/cmd/spinifex/cmd/admin_kv.go
+++ b/cmd/spinifex/cmd/admin_kv.go
@@ -11,6 +11,7 @@ import (
"fmt"
"io"
"io/fs"
+ "maps"
"os"
"path/filepath"
"slices"
@@ -420,11 +421,7 @@ func hashStoredMsg(m *jetstream.RawStreamMsg) string {
field([]byte(m.Subject))
binary.BigEndian.PutUint64(n[:], uint64(m.Time.UnixNano()))
h.Write(n[:])
- keys := make([]string, 0, len(m.Header))
- for k := range m.Header {
- keys = append(keys, k)
- }
- sort.Strings(keys)
+ keys := slices.Sorted(maps.Keys(m.Header))
for _, k := range keys {
field([]byte(k))
for _, v := range m.Header[k] {
diff --git a/cmd/spinifex/cmd/admin_kv_compare.go b/cmd/spinifex/cmd/admin_kv_compare.go
index 876776215..db47f8e3f 100644
--- a/cmd/spinifex/cmd/admin_kv_compare.go
+++ b/cmd/spinifex/cmd/admin_kv_compare.go
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
+ "maps"
"os"
"slices"
"sort"
@@ -153,11 +154,7 @@ func compareNodeDigests(nodes []nodeDigest) (kvCompareResult, error) {
byName[d.Name] = append(byName[d.Name], v)
}
}
- names := make([]string, 0, len(byName))
- for name := range byName {
- names = append(names, name)
- }
- sort.Strings(names)
+ names := slices.Sorted(maps.Keys(byName))
var res kvCompareResult
for _, name := range names {
diff --git a/internal/awsmodel/model.go b/internal/awsmodel/model.go
index 348d10f84..81adc8242 100644
--- a/internal/awsmodel/model.go
+++ b/internal/awsmodel/model.go
@@ -131,12 +131,7 @@ var modelCache sync.Map
// Services returns the supported service identifiers in stable order.
func Services() []Service {
- services := make([]Service, 0, len(modelFiles))
- for service := range modelFiles {
- services = append(services, service)
- }
- slices.Sort(services)
- return services
+ return slices.Sorted(maps.Keys(modelFiles))
}
// Load parses and indexes the embedded model for service. Each service is
diff --git a/internal/awsmodel/page.go b/internal/awsmodel/page.go
index 299beade9..7644443af 100644
--- a/internal/awsmodel/page.go
+++ b/internal/awsmodel/page.go
@@ -4,8 +4,9 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "maps"
"regexp"
- "sort"
+ "slices"
"strconv"
"strings"
"unicode/utf8"
@@ -253,12 +254,7 @@ func validateFrontmatter(owner string, page PageMetadata) error {
// key rather than by first use, so adding an operation cannot renumber a note
// that is already published.
func noteOrder(notes map[string]string) []string {
- keys := make([]string, 0, len(notes))
- for key := range notes {
- keys = append(keys, key)
- }
- sort.Strings(keys)
- return keys
+ return slices.Sorted(maps.Keys(notes))
}
// checkNotes rejects a note nothing references and a reference to a note that
diff --git a/spinifex/cloud/oci/fake.go b/spinifex/cloud/oci/fake.go
index ddd790120..efefc15b9 100644
--- a/spinifex/cloud/oci/fake.go
+++ b/spinifex/cloud/oci/fake.go
@@ -3,7 +3,9 @@ package oci
import (
"context"
"fmt"
+ "maps"
"net/netip"
+ "slices"
"sync"
)
@@ -71,22 +73,14 @@ func (f *Fake) SeedPublicIP(p PublicIP) {
func (f *Fake) PrivateIPs() []PrivateIP {
f.mu.Lock()
defer f.mu.Unlock()
- out := make([]PrivateIP, 0, len(f.privateIPs))
- for _, p := range f.privateIPs {
- out = append(out, p)
- }
- return out
+ return slices.Collect(maps.Values(f.privateIPs))
}
// PublicIPs returns a snapshot.
func (f *Fake) PublicIPs() []PublicIP {
f.mu.Lock()
defer f.mu.Unlock()
- out := make([]PublicIP, 0, len(f.publicIPs))
- for _, p := range f.publicIPs {
- out = append(out, p)
- }
- return out
+ return slices.Collect(maps.Values(f.publicIPs))
}
// FailOp stages err for the next call to op. Locked, so a test may stage one
diff --git a/spinifex/daemon/daemon.go b/spinifex/daemon/daemon.go
index 39d03987e..5794427b6 100644
--- a/spinifex/daemon/daemon.go
+++ b/spinifex/daemon/daemon.go
@@ -2371,11 +2371,7 @@ func (d *Daemon) nodeRunningVMs() ([]*vm.VM, error) {
if err != nil {
return nil, err
}
- vms := make([]*vm.VM, 0, len(running))
- for _, v := range running {
- vms = append(vms, v)
- }
- return vms, nil
+ return slices.Collect(maps.Values(running)), nil
}
// connectNATS connects to NATS with infinite retry (cap 60s backoff). Tests
diff --git a/spinifex/gateway/conditionkeys_completeness_test.go b/spinifex/gateway/conditionkeys_completeness_test.go
index 8e65fb99f..0c61d85ef 100644
--- a/spinifex/gateway/conditionkeys_completeness_test.go
+++ b/spinifex/gateway/conditionkeys_completeness_test.go
@@ -7,8 +7,10 @@ package gateway
import (
"crypto/tls"
"encoding/json"
+ "maps"
"net/http"
"net/http/httptest"
+ "slices"
"testing"
"github.com/mulgadc/bluebottle/pkg/iampolicy"
@@ -117,10 +119,7 @@ func TestRequestConditionKeys_EveryEmittedKeyIsUsableInAPolicy(t *testing.T) {
// The door's key set as a whole, so a key gained or lost here is a deliberate
// change made at both doors rather than a drift between them.
func TestRequestConditionKeys_MatchesTheDoorKeySet(t *testing.T) {
- emitted := make([]string, 0, len(gatewayDoorKeys))
- for key := range emittedKeys(t) {
- emitted = append(emitted, key)
- }
+ emitted := slices.Collect(maps.Keys(emittedKeys(t)))
assert.ElementsMatch(t, gatewayDoorKeys, emitted,
"the AWS gateway door key set changed: update predastore's mirror in "+
"internal/gate/conditionkeys_completeness_test.go and the door table in bluebottle's door_test.go")
diff --git a/spinifex/gateway/ec2.go b/spinifex/gateway/ec2.go
index 3cb16f668..22d28611a 100644
--- a/spinifex/gateway/ec2.go
+++ b/spinifex/gateway/ec2.go
@@ -118,6 +118,7 @@ var ec2ListsAsSet = map[reflect.Type][]string{
reflect.TypeFor[ec2.RevokeSecurityGroupEgressOutput](): {"UnknownIpPermissions"},
reflect.TypeFor[ec2.NetworkInterface](): {"Ipv4Prefixes", "Ipv6Prefixes"},
reflect.TypeFor[ec2.Vpc](): {"Ipv6CidrBlockAssociationSet"},
+ reflect.TypeFor[ec2.Subnet](): {"Tags"},
}
// marshalEC2Response renders an EC2 handler's output into the action's XML
diff --git a/spinifex/gateway/ec2_dryrun_test.go b/spinifex/gateway/ec2_dryrun_test.go
index 9027f062b..f1053e6d4 100644
--- a/spinifex/gateway/ec2_dryrun_test.go
+++ b/spinifex/gateway/ec2_dryrun_test.go
@@ -4,6 +4,7 @@
package gateway
import (
+ "maps"
"net/http"
"net/http/httptest"
"reflect"
@@ -43,11 +44,7 @@ func serveEC2(gw *GatewayConfig, body string) *httptest.ResponseRecorder {
func TestEC2Request_DryRunAnswersEveryAction(t *testing.T) {
gw := &GatewayConfig{DisableLogging: true, Region: authzRegion, IAMService: allowAllIAMService()}
- actions := make([]string, 0, len(ec2Actions))
- for action := range ec2Actions {
- actions = append(actions, action)
- }
- slices.Sort(actions)
+ actions := slices.Sorted(maps.Keys(ec2Actions))
for _, action := range actions {
t.Run(action, func(t *testing.T) {
diff --git a/spinifex/gateway/ec2_emptyresult_test.go b/spinifex/gateway/ec2_emptyresult_test.go
index 02e9a77c0..30177f49a 100644
--- a/spinifex/gateway/ec2_emptyresult_test.go
+++ b/spinifex/gateway/ec2_emptyresult_test.go
@@ -180,4 +180,8 @@ func TestEC2_NetworkListsAWSOmitsWhenEmpty(t *testing.T) {
Ipv6CidrBlockAssociationSet: []*ec2.VpcIpv6CidrBlockAssociation{},
}})
assert.Contains(t, created, "")
+
+ subnet := render[ec2.CreateSubnetInput](t, "CreateSubnet", ec2.CreateSubnetOutput{Subnet: &ec2.Subnet{SubnetId: aws.String("subnet-1")}})
+ assert.NotContains(t, subnet, "tagSet")
+ assert.Contains(t, subnet, "")
}
diff --git a/spinifex/gateway/ecrapi/tags.go b/spinifex/gateway/ecrapi/tags.go
index 14b0f9743..8fbad162b 100644
--- a/spinifex/gateway/ecrapi/tags.go
+++ b/spinifex/gateway/ecrapi/tags.go
@@ -4,7 +4,8 @@ import (
"context"
"encoding/json"
"errors"
- "sort"
+ "maps"
+ "slices"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecr"
@@ -123,11 +124,7 @@ func ListTagsForResource(ctx context.Context, nc *nats.Conn, accountID string, b
if err != nil {
return nil, err
}
- keys := make([]string, 0, len(meta.Tags))
- for k := range meta.Tags {
- keys = append(keys, k)
- }
- sort.Strings(keys)
+ keys := slices.Sorted(maps.Keys(meta.Tags))
tags := make([]*ecr.Tag, 0, len(keys))
for _, k := range keys {
tags = append(tags, &ecr.Tag{Key: aws.String(k), Value: aws.String(meta.Tags[k])})
diff --git a/spinifex/handlers/ec2/instance/service_impl.go b/spinifex/handlers/ec2/instance/service_impl.go
index ce4651fe0..0316634bf 100644
--- a/spinifex/handlers/ec2/instance/service_impl.go
+++ b/spinifex/handlers/ec2/instance/service_impl.go
@@ -2116,10 +2116,7 @@ func (s *InstanceServiceImpl) DescribeInstances(ctx context.Context, input *ec2.
}
})
- reservations := make([]*ec2.Reservation, 0, len(reservationMap))
- for _, reservation := range reservationMap {
- reservations = append(reservations, reservation)
- }
+ reservations := slices.Collect(maps.Values(reservationMap))
slog.InfoContext(ctx, "DescribeInstances completed", "count", len(reservations))
return &ec2.DescribeInstancesOutput{Reservations: reservations}, nil
@@ -2242,10 +2239,7 @@ func (s *InstanceServiceImpl) describeInstancesFromKV(ctx context.Context, input
reservationMap[resID].Instances = append(reservationMap[resID].Instances, projected)
}
- reservations := make([]*ec2.Reservation, 0, len(reservationMap))
- for _, reservation := range reservationMap {
- reservations = append(reservations, reservation)
- }
+ reservations := slices.Collect(maps.Values(reservationMap))
slog.InfoContext(ctx, opName+" completed", "count", len(reservations))
return &ec2.DescribeInstancesOutput{Reservations: reservations}, nil
diff --git a/spinifex/handlers/eks/addon_catalog.go b/spinifex/handlers/eks/addon_catalog.go
index 29980b02b..90146a64e 100644
--- a/spinifex/handlers/eks/addon_catalog.go
+++ b/spinifex/handlers/eks/addon_catalog.go
@@ -2,6 +2,7 @@ package handlers_eks
import (
"fmt"
+ "maps"
"slices"
)
@@ -111,11 +112,7 @@ func (s AddonSpec) supportsVersion(version string) bool {
// catalogSpecs returns the catalog entries sorted by name for stable output.
func catalogSpecs() []AddonSpec {
- names := make([]string, 0, len(addonCatalog))
- for n := range addonCatalog {
- names = append(names, n)
- }
- slices.Sort(names)
+ names := slices.Sorted(maps.Keys(addonCatalog))
out := make([]AddonSpec, 0, len(names))
for _, n := range names {
out = append(out, addonCatalog[n])
diff --git a/spinifex/loadgen/loadgen.go b/spinifex/loadgen/loadgen.go
index 0a878bd16..61e1921e8 100644
--- a/spinifex/loadgen/loadgen.go
+++ b/spinifex/loadgen/loadgen.go
@@ -12,7 +12,9 @@ import (
"context"
"errors"
"fmt"
+ "maps"
"math"
+ "slices"
"sort"
"sync"
"time"
@@ -503,10 +505,5 @@ func Summary(report *Report) string {
}
func sortedOps(ops map[string]OpStats) []string {
- names := make([]string, 0, len(ops))
- for name := range ops {
- names = append(names, name)
- }
- sort.Strings(names)
- return names
+ return slices.Sorted(maps.Keys(ops))
}
diff --git a/spinifex/loadgen/ops.go b/spinifex/loadgen/ops.go
index 126d7fe24..fb560e5ac 100644
--- a/spinifex/loadgen/ops.go
+++ b/spinifex/loadgen/ops.go
@@ -3,8 +3,8 @@ package loadgen
import (
"context"
"fmt"
+ "maps"
"slices"
- "sort"
"strings"
"github.com/aws/aws-sdk-go/aws"
@@ -103,12 +103,7 @@ var DefaultOps = []string{"DescribeInstances", "DescribeVpcs", "DescribeVolumes"
// OpNames lists every operation the registry knows, for the usage text.
func OpNames() []string {
- names := make([]string, 0, len(registry))
- for name := range registry {
- names = append(names, name)
- }
- sort.Strings(names)
- return names
+ return slices.Sorted(maps.Keys(registry))
}
// ResolveOps turns names into operations, rejecting an unknown one rather than
diff --git a/spinifex/resource/resource_test.go b/spinifex/resource/resource_test.go
index 7c1736c5f..29dfa2177 100644
--- a/spinifex/resource/resource_test.go
+++ b/spinifex/resource/resource_test.go
@@ -2,6 +2,7 @@ package resource_test
import (
"encoding/json"
+ "maps"
"slices"
"testing"
"time"
@@ -202,10 +203,5 @@ func TestObjectJSON_RoundTrips(t *testing.T) {
}
func sortedKeys(m map[string]json.RawMessage) []string {
- keys := make([]string, 0, len(m))
- for k := range m {
- keys = append(keys, k)
- }
- slices.Sort(keys)
- return keys
+ return slices.Sorted(maps.Keys(m))
}
diff --git a/spinifex/services/awsgw/awsgw.go b/spinifex/services/awsgw/awsgw.go
index 79c830a44..29a9a7bb3 100644
--- a/spinifex/services/awsgw/awsgw.go
+++ b/spinifex/services/awsgw/awsgw.go
@@ -6,10 +6,12 @@ import (
"crypto/x509"
"fmt"
"log/slog"
+ "maps"
"net"
"net/http"
"os"
"path/filepath"
+ "slices"
"strings"
"time"
@@ -443,10 +445,7 @@ func launchService(config *config.ClusterConfig) error {
// nodeIDs is the configured cluster node set, in the same namespace as the
// daemon reply header, so a fan-out's completeness can be judged by
// responder identity rather than by count.
- nodeIDs := make([]string, 0, len(config.Nodes))
- for nodeID := range config.Nodes {
- nodeIDs = append(nodeIDs, nodeID)
- }
+ nodeIDs := slices.Collect(maps.Keys(config.Nodes))
gw := gateway.GatewayConfig{
Debug: nodeConfig.AWSGW.Debug,
diff --git a/spinifex/services/northstar/bootstrap.go b/spinifex/services/northstar/bootstrap.go
index 756ae7c35..d70ba99b7 100644
--- a/spinifex/services/northstar/bootstrap.go
+++ b/spinifex/services/northstar/bootstrap.go
@@ -3,7 +3,8 @@ package northstar
import (
"fmt"
"log/slog"
- "sort"
+ "maps"
+ "slices"
"strings"
"time"
@@ -150,10 +151,5 @@ func ensureZone(s3cfg *nsconfig.S3Config, seed nsconfig.BaseZoneSeed) error {
// nodeNames returns the sorted node keys of the cluster, for diagnostics.
func nodeNames(cluster *config.ClusterConfig) []string {
- names := make([]string, 0, len(cluster.Nodes))
- for name := range cluster.Nodes {
- names = append(names, name)
- }
- sort.Strings(names)
- return names
+ return slices.Sorted(maps.Keys(cluster.Nodes))
}
diff --git a/spinifex/systemd/reconcile.go b/spinifex/systemd/reconcile.go
index 47583cb84..192a8e4a5 100644
--- a/spinifex/systemd/reconcile.go
+++ b/spinifex/systemd/reconcile.go
@@ -9,12 +9,12 @@ package systemd
import (
"errors"
"fmt"
+ "maps"
"os"
"os/exec"
"path/filepath"
"regexp"
"slices"
- "sort"
"strconv"
"strings"
"time"
@@ -98,12 +98,7 @@ var systemctlDaemonReload = func() error {
}
func sortedUnitNames() []string {
- names := make([]string, 0, len(Units))
- for n := range Units {
- names = append(names, n)
- }
- sort.Strings(names)
- return names
+ return slices.Sorted(maps.Keys(Units))
}
// Reconcile compares each embedded unit (Units, generated from
diff --git a/spinifex/utils/nats_trace.go b/spinifex/utils/nats_trace.go
index 1401ff137..174772da6 100644
--- a/spinifex/utils/nats_trace.go
+++ b/spinifex/utils/nats_trace.go
@@ -2,6 +2,8 @@ package utils
import (
"context"
+ "maps"
+ "slices"
"github.com/nats-io/nats.go"
"go.opentelemetry.io/otel"
@@ -22,11 +24,7 @@ type natsHeaderCarrier nats.Header
func (c natsHeaderCarrier) Get(key string) string { return nats.Header(c).Get(key) }
func (c natsHeaderCarrier) Set(key, value string) { nats.Header(c).Set(key, value) }
func (c natsHeaderCarrier) Keys() []string {
- keys := make([]string, 0, len(c))
- for k := range c {
- keys = append(keys, k)
- }
- return keys
+ return slices.Collect(maps.Keys(c))
}
// InjectTraceContext writes ctx's span context into hdr (traceparent/tracestate).
diff --git a/spinifex/vm/manager.go b/spinifex/vm/manager.go
index 2251f0de6..6e96267b3 100644
--- a/spinifex/vm/manager.go
+++ b/spinifex/vm/manager.go
@@ -2,6 +2,7 @@ package vm
import (
"maps"
+ "slices"
"sync"
"time"
)
@@ -191,11 +192,7 @@ func (m *Manager) ForEach(fn func(*VM)) {
func (m *Manager) Snapshot() []*VM {
m.mu.Lock()
defer m.mu.Unlock()
- out := make([]*VM, 0, len(m.vms))
- for _, v := range m.vms {
- out = append(out, v)
- }
- return out
+ return slices.Collect(maps.Values(m.vms))
}
// SnapshotMap returns a copy of the id→VM map for serialization outside the lock.
diff --git a/spinifex/vm/manager_deps_test.go b/spinifex/vm/manager_deps_test.go
index c18709a5c..b5e116eb0 100644
--- a/spinifex/vm/manager_deps_test.go
+++ b/spinifex/vm/manager_deps_test.go
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"maps"
+ "slices"
"sync"
"github.com/mulgadc/spinifex/spinifex/types"
@@ -76,11 +77,7 @@ func (f *fakeStateStore) DeleteStoppedInstance(id string) error {
func (f *fakeStateStore) ListStoppedInstances() ([]*VM, error) {
f.mu.Lock()
defer f.mu.Unlock()
- out := make([]*VM, 0, len(f.stopped))
- for _, v := range f.stopped {
- out = append(out, v)
- }
- return out, nil
+ return slices.Collect(maps.Values(f.stopped)), nil
}
// ClaimStoppedInstance mimics the real atomic-delete claim for tests: under
@@ -107,11 +104,7 @@ func (f *fakeStateStore) WriteTerminatedInstance(id string, v *VM) error {
func (f *fakeStateStore) ListTerminatedInstances() ([]*VM, error) {
f.mu.Lock()
defer f.mu.Unlock()
- out := make([]*VM, 0, len(f.terminated))
- for _, v := range f.terminated {
- out = append(out, v)
- }
- return out, nil
+ return slices.Collect(maps.Values(f.terminated)), nil
}
func (f *fakeStateStore) DeleteTerminatedInstance(id string) error {
diff --git a/spinifex/vm/mock/mock.go b/spinifex/vm/mock/mock.go
index 1633ade04..58475a28f 100644
--- a/spinifex/vm/mock/mock.go
+++ b/spinifex/vm/mock/mock.go
@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"maps"
+ "slices"
"sync"
"github.com/mulgadc/spinifex/spinifex/kvstore"
@@ -170,11 +171,7 @@ func (s *StateStore) ListStoppedInstances() ([]*vm.VM, error) {
if s.ListStoppedErr != nil {
return nil, s.ListStoppedErr
}
- out := make([]*vm.VM, 0, len(s.Stopped))
- for _, v := range s.Stopped {
- out = append(out, v)
- }
- return out, nil
+ return slices.Collect(maps.Values(s.Stopped)), nil
}
// ClaimStoppedInstance mimics the real atomic delete-as-claim: under the
@@ -237,11 +234,7 @@ func (s *StateStore) ListTerminatedInstances() ([]*vm.VM, error) {
if s.ListTerminatedErr != nil {
return nil, s.ListTerminatedErr
}
- out := make([]*vm.VM, 0, len(s.Terminated))
- for _, v := range s.Terminated {
- out = append(out, v)
- }
- return out, nil
+ return slices.Collect(maps.Values(s.Terminated)), nil
}
func (s *StateStore) DeleteTerminatedInstance(id string) error {
diff --git a/tests/bench/ebsctl/compare.go b/tests/bench/ebsctl/compare.go
index 0bbbc3841..59afc2e0b 100644
--- a/tests/bench/ebsctl/compare.go
+++ b/tests/bench/ebsctl/compare.go
@@ -3,8 +3,10 @@ package ebsctl
import (
"encoding/json"
"fmt"
+ "maps"
"math/rand/v2"
"os"
+ "slices"
"sort"
"strconv"
"strings"
@@ -74,12 +76,7 @@ func unionOps(a, b *RunResult) []string {
for name := range b.Operations {
seen[name] = struct{}{}
}
- out := make([]string, 0, len(seen))
- for name := range seen {
- out = append(out, name)
- }
- sort.Strings(out)
- return out
+ return slices.Sorted(maps.Keys(seen))
}
// seriesFor picks the api or settle series from op, or nil if op is nil or
diff --git a/tests/e2e/ddil/scenarios/coverage_drift_test.go b/tests/e2e/ddil/scenarios/coverage_drift_test.go
index 09eb243fe..b4c3f8f21 100644
--- a/tests/e2e/ddil/scenarios/coverage_drift_test.go
+++ b/tests/e2e/ddil/scenarios/coverage_drift_test.go
@@ -6,11 +6,12 @@ import (
"go/ast"
"go/parser"
"go/token"
+ "maps"
"os"
"path/filepath"
"regexp"
"runtime"
- "sort"
+ "slices"
"strings"
"testing"
)
@@ -117,12 +118,7 @@ func lettersFromDoc(path string) ([]string, error) {
}
func sortedKeys(m map[string]struct{}) []string {
- out := make([]string, 0, len(m))
- for k := range m {
- out = append(out, k)
- }
- sort.Strings(out)
- return out
+ return slices.Sorted(maps.Keys(m))
}
// setDiff returns elements in a that are not in b (both inputs must be sorted).
diff --git a/tests/e2e/harness/account.go b/tests/e2e/harness/account.go
index 9ed44bba3..5be8cdf3f 100644
--- a/tests/e2e/harness/account.go
+++ b/tests/e2e/harness/account.go
@@ -3,7 +3,8 @@
package harness
import (
- "sort"
+ "maps"
+ "slices"
"sync"
"testing"
)
@@ -59,10 +60,5 @@ func (a *AccountCarousel) Get(name string) *Profile {
func (a *AccountCarousel) Names() []string {
a.mu.RLock()
defer a.mu.RUnlock()
- out := make([]string, 0, len(a.profiles))
- for k := range a.profiles {
- out = append(out, k)
- }
- sort.Strings(out)
- return out
+ return slices.Sorted(maps.Keys(a.profiles))
}
diff --git a/tests/e2e/harness/guest_data.go b/tests/e2e/harness/guest_data.go
index 88dec1bc9..04e77615e 100644
--- a/tests/e2e/harness/guest_data.go
+++ b/tests/e2e/harness/guest_data.go
@@ -5,8 +5,10 @@ package harness
import (
"context"
"fmt"
+ "maps"
"os/exec"
"regexp"
+ "slices"
"strconv"
"strings"
"testing"
@@ -115,10 +117,7 @@ func WaitForNewGuestDisk(t *testing.T, tgt SSHTarget, before map[string]struct{}
return nil
}
}
- names := make([]string, 0, len(now))
- for name := range now {
- names = append(names, name)
- }
+ names := slices.Collect(maps.Keys(now))
return fmt.Errorf("no new disk yet (visible: %s)", strings.Join(names, ","))
}, timeout, 2*time.Second)
return found
diff --git a/tests/e2e/kvquorum/node_loss_test.go b/tests/e2e/kvquorum/node_loss_test.go
index d2beafaef..680d835f3 100644
--- a/tests/e2e/kvquorum/node_loss_test.go
+++ b/tests/e2e/kvquorum/node_loss_test.go
@@ -4,6 +4,8 @@ package kvquorum
import (
"fmt"
+ "maps"
+ "slices"
"sort"
"strings"
"testing"
@@ -180,10 +182,6 @@ func peerNames(reports []kvutil.BucketReport) string {
seen[p] = struct{}{}
}
}
- out := make([]string, 0, len(seen))
- for p := range seen {
- out = append(out, p)
- }
- sort.Strings(out)
+ out := slices.Sorted(maps.Keys(seen))
return strings.Join(out, ",")
}
diff --git a/tests/e2e/manifest-lint/lint.go b/tests/e2e/manifest-lint/lint.go
index 1946947e9..ed2c1218a 100644
--- a/tests/e2e/manifest-lint/lint.go
+++ b/tests/e2e/manifest-lint/lint.go
@@ -21,7 +21,9 @@ package manifestlint
import (
"bufio"
+ "maps"
"os"
+ "slices"
"sort"
"strings"
)
@@ -75,11 +77,7 @@ func WriteBaseline(path string, keys []string) error {
for _, k := range keys {
uniq[k] = true
}
- out := make([]string, 0, len(uniq))
- for k := range uniq {
- out = append(out, k)
- }
- sort.Strings(out)
+ out := slices.Sorted(maps.Keys(uniq))
var b strings.Builder
b.WriteString("# manifest-lint baseline — pre-existing drift accepted by the ratchet.\n")
diff --git a/tests/e2e/manifest-lint/subjects.go b/tests/e2e/manifest-lint/subjects.go
index d6479e950..4e445a08d 100644
--- a/tests/e2e/manifest-lint/subjects.go
+++ b/tests/e2e/manifest-lint/subjects.go
@@ -5,9 +5,11 @@ import (
"go/ast"
"go/parser"
"go/token"
+ "maps"
"os"
"path/filepath"
"regexp"
+ "slices"
"sort"
"strconv"
"strings"
@@ -137,12 +139,7 @@ func serviceDirs(m *manifestcheck.Manifest) []string {
set[p] = true
}
}
- out := make([]string, 0, len(set))
- for d := range set {
- out = append(out, d)
- }
- sort.Strings(out)
- return out
+ return slices.Sorted(maps.Keys(set))
}
// scanSubjectsInDir walks dir recursively, parsing every non-test .go file and
diff --git a/tests/e2e/single/guestchurn_test.go b/tests/e2e/single/guestchurn_test.go
index ae2a62647..47d6549d5 100644
--- a/tests/e2e/single/guestchurn_test.go
+++ b/tests/e2e/single/guestchurn_test.go
@@ -4,8 +4,10 @@ package single
import (
"fmt"
+ "maps"
"net"
"os/exec"
+ "slices"
"strconv"
"strings"
"testing"
@@ -692,11 +694,7 @@ func guestMACSet(t *testing.T, tgt harness.SSHTarget) map[string]struct{} {
// setKeys returns the keys of a string set as a slice for log/Detail output.
func setKeys(m map[string]struct{}) []string {
- keys := make([]string, 0, len(m))
- for k := range m {
- keys = append(keys, k)
- }
- return keys
+ return slices.Collect(maps.Keys(m))
}
// describeENI returns the single ENI record for eniID, erroring if absent.
diff --git a/tests/integration/conformance.go b/tests/integration/conformance.go
index 374cfc725..cee3835e6 100644
--- a/tests/integration/conformance.go
+++ b/tests/integration/conformance.go
@@ -6,8 +6,10 @@ import (
"bytes"
"fmt"
"io"
+ "maps"
"net/http"
"net/url"
+ "slices"
"sort"
"strings"
"sync"
@@ -210,11 +212,7 @@ func (c *conformanceCollector) report(policy conformancePolicy, mode conformance
for service := range policy.promoted {
checkedServices[service] = true
}
- services := make([]awsmodel.Service, 0, len(checkedServices))
- for service := range checkedServices {
- services = append(services, service)
- }
- sort.Slice(services, func(i, j int) bool { return services[i] < services[j] })
+ services := slices.Sorted(maps.Keys(checkedServices))
for _, service := range services {
fmt.Fprintf(&report, "CHECKED %s success=%d errors=%d unmodelled_errors=%d promoted=%t\n",
service, c.checkedByService[service], c.errorCheckedByService[service], c.errorUnmodelledByService[service], policy.isPromoted(service))
diff --git a/tests/integration/conformance_policy.go b/tests/integration/conformance_policy.go
index 486016a6b..8b9a85bd2 100644
--- a/tests/integration/conformance_policy.go
+++ b/tests/integration/conformance_policy.go
@@ -6,8 +6,9 @@ import (
_ "embed"
"encoding/json"
"fmt"
+ "maps"
"os"
- "sort"
+ "slices"
"strings"
"github.com/mulgadc/spinifex/internal/awsmodel"
@@ -89,12 +90,7 @@ func (p conformancePolicy) isRequestPromoted(service awsmodel.Service) bool {
}
func (p conformancePolicy) services() []awsmodel.Service {
- services := make([]awsmodel.Service, 0, len(p.promoted))
- for service := range p.promoted {
- services = append(services, service)
- }
- sort.Slice(services, func(i, j int) bool { return services[i] < services[j] })
- return services
+ return slices.Sorted(maps.Keys(p.promoted))
}
func conformanceModeFromEnvironment() (conformanceMode, error) {