da27bc64
build: adopt Go 1.26 idioms
a73x 2026-07-26 10:00
Commit message
internal/agent/hostinfo/hostinfo.go
| Old | New | ||
|---|---|---|---|
| @@ -89,7 +89,7 @@ func memAvailableMB(si *syscall.Sysinfo_t) int64 { | |||
| 89 | // parseOSRelease extracts ID, PRETTY_NAME, VERSION_ID from /etc/os-release | 89 | // parseOSRelease extracts ID, PRETTY_NAME, VERSION_ID from /etc/os-release |
| 90 | // (KEY=VALUE lines, values optionally double-quoted). | 90 | // (KEY=VALUE lines, values optionally double-quoted). |
| 91 | func parseOSRelease(s string) (id, pretty, version string) { | 91 | func parseOSRelease(s string) (id, pretty, version string) { |
| 92 | for _, line := range strings.Split(s, "\n") { | 92 | for line := range strings.SplitSeq(s, "\n") { |
| 93 | k, v, ok := strings.Cut(strings.TrimSpace(line), "=") | 93 | k, v, ok := strings.Cut(strings.TrimSpace(line), "=") |
| 94 | if !ok { | 94 | if !ok { |
| 95 | continue | 95 | continue |
| @@ -110,7 +110,7 @@ func parseOSRelease(s string) (id, pretty, version string) { | |||
| 110 | // parseCPUModel returns the first "model name" value from /proc/cpuinfo, or "" | 110 | // parseCPUModel returns the first "model name" value from /proc/cpuinfo, or "" |
| 111 | // (e.g. on arm, which uses different fields). | 111 | // (e.g. on arm, which uses different fields). |
| 112 | func parseCPUModel(s string) string { | 112 | func parseCPUModel(s string) string { |
| 113 | for _, line := range strings.Split(s, "\n") { | 113 | for line := range strings.SplitSeq(s, "\n") { |
| 114 | if k, v, ok := strings.Cut(line, ":"); ok && strings.TrimSpace(k) == "model name" { | 114 | if k, v, ok := strings.Cut(line, ":"); ok && strings.TrimSpace(k) == "model name" { |
| 115 | return strings.TrimSpace(v) | 115 | return strings.TrimSpace(v) |
| 116 | } | 116 | } |
| @@ -121,7 +121,7 @@ func parseCPUModel(s string) string { | |||
| 121 | // parseMemAvailableKB returns the MemAvailable value in kB and whether it was | 121 | // parseMemAvailableKB returns the MemAvailable value in kB and whether it was |
| 122 | // present. | 122 | // present. |
| 123 | func parseMemAvailableKB(s string) (int64, bool) { | 123 | func parseMemAvailableKB(s string) (int64, bool) { |
| 124 | for _, line := range strings.Split(s, "\n") { | 124 | for line := range strings.SplitSeq(s, "\n") { |
| 125 | if !strings.HasPrefix(line, "MemAvailable:") { | 125 | if !strings.HasPrefix(line, "MemAvailable:") { |
| 126 | continue | 126 | continue |
| 127 | } | 127 | } |
internal/agent/imagecache/imagecache_test.go
| Old | New | ||
|---|---|---|---|
| @@ -239,10 +239,10 @@ func TestConcurrentEnsureFetchesOnce(t *testing.T) { | |||
| 239 | sum := sha256.Sum256(body) | 239 | sum := sha256.Sum256(body) |
| 240 | sha := hex.EncodeToString(sum[:]) | 240 | sha := hex.EncodeToString(sum[:]) |
| 241 | 241 | ||
| 242 | var downloads int32 | 242 | var downloads atomic.Int32 |
| 243 | release := make(chan struct{}) | 243 | release := make(chan struct{}) |
| 244 | srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 244 | srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 245 | atomic.AddInt32(&downloads, 1) | 245 | downloads.Add(1) |
| 246 | <-release // hold every request open so the callers genuinely overlap | 246 | <-release // hold every request open so the callers genuinely overlap |
| 247 | w.Write(body) | 247 | w.Write(body) |
| 248 | })) | 248 | })) |
| @@ -253,7 +253,7 @@ func TestConcurrentEnsureFetchesOnce(t *testing.T) { | |||
| 253 | const callers = 4 | 253 | const callers = 4 |
| 254 | paths := make(chan string, callers) | 254 | paths := make(chan string, callers) |
| 255 | errs := make(chan error, callers) | 255 | errs := make(chan error, callers) |
| 256 | for i := 0; i < callers; i++ { | 256 | for range callers { |
| 257 | go func() { | 257 | go func() { |
| 258 | p, err := c.Ensure(context.Background(), srv.URL, sha) | 258 | p, err := c.Ensure(context.Background(), srv.URL, sha) |
| 259 | if err != nil { | 259 | if err != nil { |
| @@ -265,13 +265,13 @@ func TestConcurrentEnsureFetchesOnce(t *testing.T) { | |||
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | // Let them all arrive at the singleflight, then let the one download finish. | 267 | // Let them all arrive at the singleflight, then let the one download finish. |
| 268 | require.Eventually(t, func() bool { return atomic.LoadInt32(&downloads) >= 1 }, | 268 | require.Eventually(t, func() bool { return downloads.Load() >= 1 }, |
| 269 | 2*time.Second, 10*time.Millisecond, "no caller reached the server") | 269 | 2*time.Second, 10*time.Millisecond, "no caller reached the server") |
| 270 | time.Sleep(100 * time.Millisecond) // any un-deduplicated caller would arrive by now | 270 | time.Sleep(100 * time.Millisecond) // any un-deduplicated caller would arrive by now |
| 271 | close(release) | 271 | close(release) |
| 272 | 272 | ||
| 273 | want := filepath.Join(c.dir, sha+".raw") | 273 | want := filepath.Join(c.dir, sha+".raw") |
| 274 | for i := 0; i < callers; i++ { | 274 | for range callers { |
| 275 | select { | 275 | select { |
| 276 | case err := <-errs: | 276 | case err := <-errs: |
| 277 | t.Fatalf("Ensure failed: %v", err) | 277 | t.Fatalf("Ensure failed: %v", err) |
| @@ -281,7 +281,7 @@ func TestConcurrentEnsureFetchesOnce(t *testing.T) { | |||
| 281 | t.Fatal("Ensure never returned") | 281 | t.Fatal("Ensure never returned") |
| 282 | } | 282 | } |
| 283 | } | 283 | } |
| 284 | assert.Equal(t, int32(1), atomic.LoadInt32(&downloads), | 284 | assert.Equal(t, int32(1), downloads.Load(), |
| 285 | "concurrent Ensure calls for one image must share a single download") | 285 | "concurrent Ensure calls for one image must share a single download") |
| 286 | 286 | ||
| 287 | data, err := os.ReadFile(want) | 287 | data, err := os.ReadFile(want) |
internal/agent/reconcile/quota_test.go
| Old | New | ||
|---|---|---|---|
| @@ -64,7 +64,7 @@ func TestQuotaRefusalIsNonTerminal(t *testing.T) { | |||
| 64 | 64 | ||
| 65 | // vm2 (2 vcpus) would push the host to 4 > 2 — blocked. Repeat well past | 65 | // vm2 (2 vcpus) would push the host to 4 > 2 — blocked. Repeat well past |
| 66 | // MaxCreateAttempts (3): quota refusal must NOT consume the retry budget. | 66 | // MaxCreateAttempts (3): quota refusal must NOT consume the retry budget. |
| 67 | for i := 0; i < 5; i++ { | 67 | for range 5 { |
| 68 | f.step(snap(2, vm("vm1", withRes(2, 512, 5)), vm("vm2", withRes(2, 512, 5)))) | 68 | f.step(snap(2, vm("vm1", withRes(2, 512, 5)), vm("vm2", withRes(2, 512, 5)))) |
| 69 | } | 69 | } |
| 70 | assert.Equal(t, []string{"vm1"}, f.prov.booted, "vm2 still blocked, vm1 untouched") | 70 | assert.Equal(t, []string{"vm1"}, f.prov.booted, "vm2 still blocked, vm1 untouched") |
| @@ -94,7 +94,7 @@ func TestQuotaFreedByQuarantineEventuallyBootsTheWaitingVM(t *testing.T) { | |||
| 94 | // vm1 and releases its compute, so tick 2 always admits vm2. The third is | 94 | // vm1 and releases its compute, so tick 2 always admits vm2. The third is |
| 95 | // slack, not a flake bound. | 95 | // slack, not a flake bound. |
| 96 | var rep *pb.ActualStateReport | 96 | var rep *pb.ActualStateReport |
| 97 | for i := 0; i < 3; i++ { | 97 | for range 3 { |
| 98 | rep = f.step(snap(2, | 98 | rep = f.step(snap(2, |
| 99 | tombstoned(vm("vm1", withRes(2, 512, 5))), | 99 | tombstoned(vm("vm1", withRes(2, 512, 5))), |
| 100 | vm("vm2", withRes(2, 512, 5)))) | 100 | vm("vm2", withRes(2, 512, 5)))) |
internal/agent/reconcile/reconcile_test.go
| Old | New | ||
|---|---|---|---|
| @@ -338,7 +338,7 @@ func TestFenceRefusesLowerEpochWithoutActing(t *testing.T) { | |||
| 338 | func TestCreateRetryIsBoundedThenTerminalFailed(t *testing.T) { | 338 | func TestCreateRetryIsBoundedThenTerminalFailed(t *testing.T) { |
| 339 | f := setup(t) | 339 | f := setup(t) |
| 340 | f.prov.prepErr = assert.AnError | 340 | f.prov.prepErr = assert.AnError |
| 341 | for i := 0; i < 3; i++ { | 341 | for range 3 { |
| 342 | f.step(snap(1, vm("vm1"))) | 342 | f.step(snap(1, vm("vm1"))) |
| 343 | } | 343 | } |
| 344 | f.prov.prepErr = nil // even if the cause clears... | 344 | f.prov.prepErr = nil // even if the cause clears... |
| @@ -460,7 +460,7 @@ func TestUndeleteClearsQuarantineSoNextDeleteGetsFullGrace(t *testing.T) { | |||
| 460 | func TestEditedSpecResetsCreateAttempts(t *testing.T) { | 460 | func TestEditedSpecResetsCreateAttempts(t *testing.T) { |
| 461 | f := setup(t) | 461 | f := setup(t) |
| 462 | f.prov.prepErr = assert.AnError | 462 | f.prov.prepErr = assert.AnError |
| 463 | for i := 0; i < 3; i++ { | 463 | for range 3 { |
| 464 | f.step(snap(1, vm("vm1"))) | 464 | f.step(snap(1, vm("vm1"))) |
| 465 | } | 465 | } |
| 466 | f.prov.prepErr = nil | 466 | f.prov.prepErr = nil |
internal/agent/reconcile/worker_test.go
| Old | New | ||
|---|---|---|---|
| @@ -86,7 +86,7 @@ func TestVMsReconcileConcurrently(t *testing.T) { | |||
| 86 | 86 | ||
| 87 | stepNoWait(t, f, snap(1, vm("vm1"), vm("vm2"))) | 87 | stepNoWait(t, f, snap(1, vm("vm1"), vm("vm2"))) |
| 88 | 88 | ||
| 89 | for i := 0; i < 2; i++ { | 89 | for range 2 { |
| 90 | select { | 90 | select { |
| 91 | case <-arrived: | 91 | case <-arrived: |
| 92 | case <-time.After(2 * time.Second): | 92 | case <-time.After(2 * time.Second): |
| @@ -179,7 +179,7 @@ func TestCreateConcurrencyIsCapped(t *testing.T) { | |||
| 179 | f.eng.Step(context.Background(), snap(1, vm("vm1"), vm("vm2"), vm("vm3"))) | 179 | f.eng.Step(context.Background(), snap(1, vm("vm1"), vm("vm2"), vm("vm3"))) |
| 180 | 180 | ||
| 181 | // Two VMs take the available slots. | 181 | // Two VMs take the available slots. |
| 182 | for i := 0; i < 2; i++ { | 182 | for range 2 { |
| 183 | select { | 183 | select { |
| 184 | case <-entered: | 184 | case <-entered: |
| 185 | case <-time.After(2 * time.Second): | 185 | case <-time.After(2 * time.Second): |
| @@ -207,7 +207,7 @@ func TestCreateConcurrencyZeroIsUnlimited(t *testing.T) { | |||
| 207 | f.eng.Images = wedge(arrived, release) | 207 | f.eng.Images = wedge(arrived, release) |
| 208 | 208 | ||
| 209 | f.eng.Step(context.Background(), snap(1, vm("vm1"), vm("vm2"), vm("vm3"))) | 209 | f.eng.Step(context.Background(), snap(1, vm("vm1"), vm("vm2"), vm("vm3"))) |
| 210 | for i := 0; i < 3; i++ { | 210 | for range 3 { |
| 211 | select { | 211 | select { |
| 212 | case <-arrived: | 212 | case <-arrived: |
| 213 | case <-time.After(2 * time.Second): | 213 | case <-time.After(2 * time.Second): |
internal/agent/seed/seed.go
| Old | New | ||
|---|---|---|---|
| @@ -136,7 +136,7 @@ func vendorDataDoc(p Params) string { | |||
| 136 | // cloud-init ssh_keys map (ed25519_private / ed25519_certificate). | 136 | // cloud-init ssh_keys map (ed25519_private / ed25519_certificate). |
| 137 | func writeBlockScalar(b *strings.Builder, indent, key, content string) { | 137 | func writeBlockScalar(b *strings.Builder, indent, key, content string) { |
| 138 | b.WriteString(indent + key + ": |\n") | 138 | b.WriteString(indent + key + ": |\n") |
| 139 | for _, line := range strings.Split(strings.TrimRight(content, "\n"), "\n") { | 139 | for line := range strings.SplitSeq(strings.TrimRight(content, "\n"), "\n") { |
| 140 | b.WriteString(indent + " " + line + "\n") | 140 | b.WriteString(indent + " " + line + "\n") |
| 141 | } | 141 | } |
| 142 | } | 142 | } |
| @@ -149,7 +149,7 @@ func writeFileBlock(b *strings.Builder, path, content string) { | |||
| 149 | b.WriteString(" - path: " + path + "\n") | 149 | b.WriteString(" - path: " + path + "\n") |
| 150 | b.WriteString(" permissions: '0644'\n") | 150 | b.WriteString(" permissions: '0644'\n") |
| 151 | b.WriteString(" content: |\n") | 151 | b.WriteString(" content: |\n") |
| 152 | for _, line := range strings.Split(strings.TrimRight(content, "\n"), "\n") { | 152 | for line := range strings.SplitSeq(strings.TrimRight(content, "\n"), "\n") { |
| 153 | b.WriteString(" " + line + "\n") | 153 | b.WriteString(" " + line + "\n") |
| 154 | } | 154 | } |
| 155 | } | 155 | } |
internal/agent/serialpump/serialpump_test.go
| Old | New | ||
|---|---|---|---|
| @@ -114,8 +114,7 @@ func TestInputForwardedToSocket(t *testing.T) { | |||
| 114 | guest := ch.conn(t) | 114 | guest := ch.conn(t) |
| 115 | 115 | ||
| 116 | viewer, _, in := pipeViewer() | 116 | viewer, _, in := pipeViewer() |
| 117 | ctx, cancel := context.WithCancel(context.Background()) | 117 | ctx := t.Context() |
| 118 | defer cancel() | ||
| 119 | go m.Attach(ctx, "vm1", viewer, nil) //nolint:errcheck | 118 | go m.Attach(ctx, "vm1", viewer, nil) //nolint:errcheck |
| 120 | 119 | ||
| 121 | _, err := in.Write([]byte("ls\r")) | 120 | _, err := in.Write([]byte("ls\r")) |
| @@ -141,8 +140,7 @@ func TestOnReadyFiresBeforeBacklog(t *testing.T) { | |||
| 141 | 140 | ||
| 142 | viewer, out, _ := pipeViewer() | 141 | viewer, out, _ := pipeViewer() |
| 143 | ready := make(chan struct{}) | 142 | ready := make(chan struct{}) |
| 144 | ctx, cancel := context.WithCancel(context.Background()) | 143 | ctx := t.Context() |
| 145 | defer cancel() | ||
| 146 | go m.Attach(ctx, "vm1", viewer, func() error { close(ready); return nil }) //nolint:errcheck | 144 | go m.Attach(ctx, "vm1", viewer, func() error { close(ready); return nil }) //nolint:errcheck |
| 147 | <-ready // onReady before any viewer write (protocol: reply frame precedes raw bytes) | 145 | <-ready // onReady before any viewer write (protocol: reply frame precedes raw bytes) |
| 148 | assert.Equal(t, "X", string(readN(t, out, 1))) | 146 | assert.Equal(t, "X", string(readN(t, out, 1))) |
| @@ -166,8 +164,7 @@ func TestRingIsBounded(t *testing.T) { | |||
| 166 | }, 5*time.Second, 10*time.Millisecond) | 164 | }, 5*time.Second, 10*time.Millisecond) |
| 167 | 165 | ||
| 168 | viewer, out, _ := pipeViewer() | 166 | viewer, out, _ := pipeViewer() |
| 169 | ctx, cancel := context.WithCancel(context.Background()) | 167 | ctx := t.Context() |
| 170 | defer cancel() | ||
| 171 | go m.Attach(ctx, "vm1", viewer, nil) //nolint:errcheck | 168 | go m.Attach(ctx, "vm1", viewer, nil) //nolint:errcheck |
| 172 | // Backlog is only the LAST 16 bytes. | 169 | // Backlog is only the LAST 16 bytes. |
| 173 | assert.Equal(t, "456789ABCDEFGHIJ", string(readN(t, out, 16))) | 170 | assert.Equal(t, "456789ABCDEFGHIJ", string(readN(t, out, 16))) |
| @@ -223,7 +220,7 @@ func TestSlowViewerIsDroppedNotBlocking(t *testing.T) { | |||
| 223 | // channel overflows, the pump drops the viewer, and Attach's next channel | 220 | // channel overflows, the pump drops the viewer, and Attach's next channel |
| 224 | // receive observes the close and errors out. | 221 | // receive observes the close and errors out. |
| 225 | junk := make([]byte, 4096) | 222 | junk := make([]byte, 4096) |
| 226 | for i := 0; i < 256; i++ { | 223 | for range 256 { |
| 227 | _, err := guest.Write(junk) | 224 | _, err := guest.Write(junk) |
| 228 | require.NoError(t, err) | 225 | require.NoError(t, err) |
| 229 | } | 226 | } |
| @@ -255,8 +252,7 @@ func TestFanOutToTwoViewers(t *testing.T) { | |||
| 255 | v2, out2, _ := pipeViewer() | 252 | v2, out2, _ := pipeViewer() |
| 256 | ctx1, cancel1 := context.WithCancel(context.Background()) | 253 | ctx1, cancel1 := context.WithCancel(context.Background()) |
| 257 | defer cancel1() | 254 | defer cancel1() |
| 258 | ctx2, cancel2 := context.WithCancel(context.Background()) | 255 | ctx2 := t.Context() |
| 259 | defer cancel2() | ||
| 260 | go m.Attach(ctx1, "vm1", v1, nil) //nolint:errcheck | 256 | go m.Attach(ctx1, "vm1", v1, nil) //nolint:errcheck |
| 261 | go m.Attach(ctx2, "vm1", v2, nil) //nolint:errcheck | 257 | go m.Attach(ctx2, "vm1", v2, nil) //nolint:errcheck |
| 262 | 258 | ||
internal/agent/syncclient/client_test.go
| Old | New | ||
|---|---|---|---|
| @@ -37,7 +37,7 @@ func (noopProv) Running(string) bool { retur | |||
| 37 | type noopNet struct{} | 37 | type noopNet struct{} |
| 38 | 38 | ||
| 39 | func (noopNet) CreateTap(context.Context, string, string) error { return nil } | 39 | func (noopNet) CreateTap(context.Context, string, string) error { return nil } |
| 40 | func (noopNet) DeleteTap(context.Context, string) error { return nil } | 40 | func (noopNet) DeleteTap(context.Context, string) error { return nil } |
| 41 | func (noopNet) ReserveIP(string) (string, error) { | 41 | func (noopNet) ReserveIP(string) (string, error) { |
| 42 | return "10.77.1.2", nil | 42 | return "10.77.1.2", nil |
| 43 | } | 43 | } |
| @@ -58,7 +58,7 @@ func TestAdvertisedCapacityComputesOnce(t *testing.T) { | |||
| 58 | return &pb.Capacity{Vcpus: 8, MemMb: 16384, DiskGb: 500} | 58 | return &pb.Capacity{Vcpus: 8, MemMb: 16384, DiskGb: 500} |
| 59 | } | 59 | } |
| 60 | c := &Client{MaxVCPUs: 2} // cap vCPUs to prove the clamp runs each call | 60 | c := &Client{MaxVCPUs: 2} // cap vCPUs to prove the clamp runs each call |
| 61 | for i := 0; i < 5; i++ { | 61 | for range 5 { |
| 62 | got := c.advertisedCapacity("/state") | 62 | got := c.advertisedCapacity("/state") |
| 63 | require.Equal(t, int64(2), got.GetVcpus()) | 63 | require.Equal(t, int64(2), got.GetVcpus()) |
| 64 | require.Equal(t, int64(16384), got.GetMemMb()) | 64 | require.Equal(t, int64(16384), got.GetMemMb()) |
| @@ -220,8 +220,7 @@ func TestReconnectAfterDrop(t *testing.T) { | |||
| 220 | require.NoError(t, h.st.CreateVM(store.VM{ID: "vm1", HostID: hostID, Name: "a", | 220 | require.NoError(t, h.st.CreateVM(store.VM{ID: "vm1", HostID: hostID, Name: "a", |
| 221 | ImageURL: "u", ImageSHA256: "s", VCPUs: 1, MemMB: 512, DiskGB: 5, PowerState: "stopped"})) | 221 | ImageURL: "u", ImageSHA256: "s", VCPUs: 1, MemMB: 512, DiskGB: 5, PowerState: "stopped"})) |
| 222 | 222 | ||
| 223 | ctx, cancel := context.WithCancel(context.Background()) | 223 | ctx := t.Context() |
| 224 | defer cancel() | ||
| 225 | go c.Run(ctx) | 224 | go c.Run(ctx) |
| 226 | 225 | ||
| 227 | // First connection: wait for the host to register a report. | 226 | // First connection: wait for the host to register a report. |
internal/agent/syncclient/leak_test.go
| Old | New | ||
|---|---|---|---|
| @@ -88,8 +88,7 @@ func TestSessionNoWorkerLeakAcrossReconnects(t *testing.T) { | |||
| 88 | defer stop() | 88 | defer stop() |
| 89 | c := newClient(t, addr, fp, "host-x", "host-x.deadbeef") | 89 | c := newClient(t, addr, fp, "host-x", "host-x.deadbeef") |
| 90 | 90 | ||
| 91 | ctx, cancel := context.WithCancel(context.Background()) | 91 | ctx := t.Context() |
| 92 | defer cancel() | ||
| 93 | 92 | ||
| 94 | // Each session connects, gets one snapshot, then the server drops it, so | 93 | // Each session connects, gets one snapshot, then the server drops it, so |
| 95 | // session() returns promptly. The parent ctx is never cancelled — precisely | 94 | // session() returns promptly. The parent ctx is never cancelled — precisely |
| @@ -110,7 +109,7 @@ func TestSessionNoWorkerLeakAcrossReconnects(t *testing.T) { | |||
| 110 | base := settleGoroutines(0, 3*time.Second) // target 0 => returns settled count | 109 | base := settleGoroutines(0, 3*time.Second) // target 0 => returns settled count |
| 111 | 110 | ||
| 112 | const cycles = 10 | 111 | const cycles = 10 |
| 113 | for i := 0; i < cycles; i++ { | 112 | for range cycles { |
| 114 | runOne() | 113 | runOne() |
| 115 | } | 114 | } |
| 116 | 115 | ||
internal/arch/execwalk_test.go
| Old | New | ||
|---|---|---|---|
| @@ -1,6 +1,7 @@ | |||
| 1 | package arch | 1 | package arch |
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "slices" | ||
| 4 | "sort" | 5 | "sort" |
| 5 | "strings" | 6 | "strings" |
| 6 | "testing" | 7 | "testing" |
| @@ -66,12 +67,7 @@ func TestExecViolationsDetectsWrappers(t *testing.T) { | |||
| 66 | // package that wraps os/exec and is imported by the guarded plane. | 67 | // package that wraps os/exec and is imported by the guarded plane. |
| 67 | func execViolations(graph map[string][]string, module, prefix string, allowed map[string]bool) map[string][]string { | 68 | func execViolations(graph map[string][]string, module, prefix string, allowed map[string]bool) map[string][]string { |
| 68 | importsExec := func(pkg string) bool { | 69 | importsExec := func(pkg string) bool { |
| 69 | for _, d := range graph[pkg] { | 70 | return slices.Contains(graph[pkg], "os/exec") |
| 70 | if d == "os/exec" { | ||
| 71 | return true | ||
| 72 | } | ||
| 73 | } | ||
| 74 | return false | ||
| 75 | } | 71 | } |
| 76 | 72 | ||
| 77 | out := map[string][]string{} | 73 | out := map[string][]string{} |
internal/cloudinit/multipart.go
| Old | New | ||
|---|---|---|---|
| @@ -251,7 +251,7 @@ func appendToMultipart(userData, key string) (string, error) { | |||
| 251 | 251 | ||
| 252 | // firstNonBlankLine returns the first line with non-whitespace content, trimmed. | 252 | // firstNonBlankLine returns the first line with non-whitespace content, trimmed. |
| 253 | func firstNonBlankLine(s string) string { | 253 | func firstNonBlankLine(s string) string { |
| 254 | for _, line := range strings.Split(s, "\n") { | 254 | for line := range strings.SplitSeq(s, "\n") { |
| 255 | if t := strings.TrimSpace(line); t != "" { | 255 | if t := strings.TrimSpace(line); t != "" { |
| 256 | return t | 256 | return t |
| 257 | } | 257 | } |
internal/mcpserver/sshrun.go
| Old | New | ||
|---|---|---|---|
| @@ -83,8 +83,7 @@ func (r *Runner) Exec(ctx context.Context, vmName, cmd string, timeout time.Dura | |||
| 83 | case err = <-done: | 83 | case err = <-done: |
| 84 | } | 84 | } |
| 85 | res := ExecResult{Stdout: stdout.String(), Stderr: stderr.String(), Truncated: stdout.truncated || stderr.truncated} | 85 | res := ExecResult{Stdout: stdout.String(), Stderr: stderr.String(), Truncated: stdout.truncated || stderr.truncated} |
| 86 | var exitErr *ssh.ExitError | 86 | if exitErr, ok := errors.AsType[*ssh.ExitError](err); ok { |
| 87 | if errors.As(err, &exitErr) { | ||
| 88 | res.ExitCode = exitErr.ExitStatus() | 87 | res.ExitCode = exitErr.ExitStatus() |
| 89 | return res, nil | 88 | return res, nil |
| 90 | } | 89 | } |
internal/mcpserver/tools.go
| Old | New | ||
|---|---|---|---|
| @@ -182,10 +182,7 @@ func (t *Tools) VMCreate(ctx context.Context, in VMCreateIn) (VMCreateOut, error | |||
| 182 | // cloud-init is transparent as long as the new key is a CA-signed cert. | 182 | // cloud-init is transparent as long as the new key is a CA-signed cert. |
| 183 | // Give the command the time left in the shared budget (floored so a | 183 | // Give the command the time left in the shared budget (floored so a |
| 184 | // nearly-exhausted budget still gets a real chance). | 184 | // nearly-exhausted budget still gets a real chance). |
| 185 | remaining := time.Until(deadline) | 185 | remaining := max(time.Until(deadline), 30*time.Second) |
| 186 | if remaining < 30*time.Second { | ||
| 187 | remaining = 30 * time.Second | ||
| 188 | } | ||
| 189 | res, execErr := t.Runner.Exec(ctx, created.Name, "cloud-init status --wait", remaining) | 186 | res, execErr := t.Runner.Exec(ctx, created.Name, "cloud-init status --wait", remaining) |
| 190 | if execErr == nil { | 187 | if execErr == nil { |
| 191 | if res.ExitCode != 0 { | 188 | if res.ExitCode != 0 { |
internal/mcpserver/tools_test.go
| Old | New | ||
|---|---|---|---|
| @@ -254,7 +254,6 @@ func TestExecUnknownVM(t *testing.T) { | |||
| 254 | 254 | ||
| 255 | func TestExecNotReadyVMRejectedWithoutCallingRunner(t *testing.T) { | 255 | func TestExecNotReadyVMRejectedWithoutCallingRunner(t *testing.T) { |
| 256 | for _, lifecycle := range []string{"creating", "stopped", "failed", "deleting", ""} { | 256 | for _, lifecycle := range []string{"creating", "stopped", "failed", "deleting", ""} { |
| 257 | lifecycle := lifecycle | ||
| 258 | t.Run(lifecycle, func(t *testing.T) { | 257 | t.Run(lifecycle, func(t *testing.T) { |
| 259 | api := &fakeToolsAPI{vms: []client.VM{{ID: "abc123", Name: "web-1", Lifecycle: lifecycle}}} | 258 | api := &fakeToolsAPI{vms: []client.VM{{ID: "abc123", Name: "web-1", Lifecycle: lifecycle}}} |
| 260 | run := &fakeRunner{} | 259 | run := &fakeRunner{} |
internal/server/api/api_test.go
| Old | New | ||
|---|---|---|---|
| @@ -3,6 +3,7 @@ package api | |||
| 3 | import ( | 3 | import ( |
| 4 | "bytes" | 4 | "bytes" |
| 5 | "encoding/json" | 5 | "encoding/json" |
| 6 | "maps" | ||
| 6 | "net/http" | 7 | "net/http" |
| 7 | "net/http/httptest" | 8 | "net/http/httptest" |
| 8 | "strings" | 9 | "strings" |
| @@ -388,9 +389,7 @@ func TestCreateVMResourceValidation(t *testing.T) { | |||
| 388 | for _, tc := range tests { | 389 | for _, tc := range tests { |
| 389 | t.Run(tc.name, func(t *testing.T) { | 390 | t.Run(tc.name, func(t *testing.T) { |
| 390 | body := map[string]any{"host_id": out["host_id"]} | 391 | body := map[string]any{"host_id": out["host_id"]} |
| 391 | for k, v := range tc.body { | 392 | maps.Copy(body, tc.body) |
| 392 | body[k] = v | ||
| 393 | } | ||
| 394 | resp := do(t, "POST", ts.URL+"/api/v1/vms", "admintok", body) | 393 | resp := do(t, "POST", ts.URL+"/api/v1/vms", "admintok", body) |
| 395 | assert.Equal(t, tc.wantStatus, resp.StatusCode) | 394 | assert.Equal(t, tc.wantStatus, resp.StatusCode) |
| 396 | }) | 395 | }) |
| @@ -548,7 +547,7 @@ func TestEnrollRateLimited(t *testing.T) { | |||
| 548 | ts, _, _ := testServer(t) | 547 | ts, _, _ := testServer(t) |
| 549 | 548 | ||
| 550 | var got429 bool | 549 | var got429 bool |
| 551 | for i := 0; i < enrollBurst+3; i++ { | 550 | for range enrollBurst + 3 { |
| 552 | resp := do(t, "POST", ts.URL+"/api/v1/enroll", "", map[string]string{ | 551 | resp := do(t, "POST", ts.URL+"/api/v1/enroll", "", map[string]string{ |
| 553 | "token": "bogus", "name": "x", "os": "linux", "arch": "amd64", "provisioner": "cloudhv"}) | 552 | "token": "bogus", "name": "x", "os": "linux", "arch": "amd64", "provisioner": "cloudhv"}) |
| 554 | if resp.StatusCode == http.StatusTooManyRequests { | 553 | if resp.StatusCode == http.StatusTooManyRequests { |
internal/server/api/ratelimit_test.go
| Old | New | ||
|---|---|---|---|
| @@ -14,7 +14,7 @@ func TestLimiterRefillAndCap(t *testing.T) { | |||
| 14 | now := time.Unix(1_750_000_000, 0) | 14 | now := time.Unix(1_750_000_000, 0) |
| 15 | l := newIPLimiter(func() time.Time { return now }) | 15 | l := newIPLimiter(func() time.Time { return now }) |
| 16 | 16 | ||
| 17 | for i := 0; i < enrollBurst; i++ { | 17 | for i := range enrollBurst { |
| 18 | assert.True(t, l.allow("10.0.0.1"), "burst request %d", i) | 18 | assert.True(t, l.allow("10.0.0.1"), "burst request %d", i) |
| 19 | } | 19 | } |
| 20 | assert.False(t, l.allow("10.0.0.1"), "burst exhausted") | 20 | assert.False(t, l.allow("10.0.0.1"), "burst exhausted") |
| @@ -25,7 +25,7 @@ func TestLimiterRefillAndCap(t *testing.T) { | |||
| 25 | 25 | ||
| 26 | // A long idle period refills to the cap, not beyond. | 26 | // A long idle period refills to the cap, not beyond. |
| 27 | now = now.Add(24 * time.Hour) | 27 | now = now.Add(24 * time.Hour) |
| 28 | for i := 0; i < enrollBurst; i++ { | 28 | for i := range enrollBurst { |
| 29 | assert.True(t, l.allow("10.0.0.1"), "cap request %d", i) | 29 | assert.True(t, l.allow("10.0.0.1"), "cap request %d", i) |
| 30 | } | 30 | } |
| 31 | assert.False(t, l.allow("10.0.0.1"), "cap enforced") | 31 | assert.False(t, l.allow("10.0.0.1"), "cap enforced") |
| @@ -38,7 +38,7 @@ func TestLimiterPruneAndFailOpen(t *testing.T) { | |||
| 38 | now := time.Unix(1_750_000_000, 0) | 38 | now := time.Unix(1_750_000_000, 0) |
| 39 | l := newIPLimiter(func() time.Time { return now }) | 39 | l := newIPLimiter(func() time.Time { return now }) |
| 40 | 40 | ||
| 41 | for i := 0; i < maxLimiterEntries; i++ { | 41 | for i := range maxLimiterEntries { |
| 42 | l.allow(fmt.Sprintf("10.%d.%d.%d", i>>16&0xff, i>>8&0xff, i&0xff)) | 42 | l.allow(fmt.Sprintf("10.%d.%d.%d", i>>16&0xff, i>>8&0xff, i&0xff)) |
| 43 | } | 43 | } |
| 44 | assert.Len(t, l.buckets, maxLimiterEntries) | 44 | assert.Len(t, l.buckets, maxLimiterEntries) |
| @@ -73,7 +73,7 @@ func TestBucketKeyGroupsIPv6BySlash64(t *testing.T) { | |||
| 73 | func TestLimiterSharesBucketAcrossSameSlash64(t *testing.T) { | 73 | func TestLimiterSharesBucketAcrossSameSlash64(t *testing.T) { |
| 74 | now := time.Unix(1_750_000_000, 0) | 74 | now := time.Unix(1_750_000_000, 0) |
| 75 | l := newIPLimiter(func() time.Time { return now }) | 75 | l := newIPLimiter(func() time.Time { return now }) |
| 76 | for i := 0; i < enrollBurst; i++ { | 76 | for range enrollBurst { |
| 77 | assert.True(t, l.allow(bucketKey("2001:db8::1"))) | 77 | assert.True(t, l.allow(bucketKey("2001:db8::1"))) |
| 78 | } | 78 | } |
| 79 | assert.False(t, l.allow(bucketKey("2001:db8::2")), "same /64: bucket shared") | 79 | assert.False(t, l.allow(bucketKey("2001:db8::2")), "same /64: bucket shared") |
internal/server/api/snapshot_hub_test.go
| Old | New | ||
|---|---|---|---|
| @@ -38,14 +38,14 @@ func TestSnapshotHubCloseIdempotent(t *testing.T) { | |||
| 38 | // and a wake drives exactly one recompute regardless of how many clients are | 38 | // and a wake drives exactly one recompute regardless of how many clients are |
| 39 | // attached (M clients must NOT cause M builds). | 39 | // attached (M clients must NOT cause M builds). |
| 40 | func TestSnapshotHubSingleBuildFanout(t *testing.T) { | 40 | func TestSnapshotHubSingleBuildFanout(t *testing.T) { |
| 41 | var builds int64 | 41 | var builds atomic.Int64 |
| 42 | build := func() ([]byte, error) { | 42 | build := func() ([]byte, error) { |
| 43 | n := atomic.AddInt64(&builds, 1) | 43 | n := builds.Add(1) |
| 44 | return []byte(fmt.Sprintf("snap-%d", n)), nil | 44 | return []byte(fmt.Sprintf("snap-%d", n)), nil |
| 45 | } | 45 | } |
| 46 | notif := newNotifier() | 46 | notif := newNotifier() |
| 47 | h := newSnapshotHub(build, notif) // computes the initial snapshot (build #1) | 47 | h := newSnapshotHub(build, notif) // computes the initial snapshot (build #1) |
| 48 | require.Equal(t, int64(1), atomic.LoadInt64(&builds)) | 48 | require.Equal(t, int64(1), builds.Load()) |
| 49 | go h.run() | 49 | go h.run() |
| 50 | defer h.Close() | 50 | defer h.Close() |
| 51 | 51 | ||
| @@ -53,7 +53,7 @@ func TestSnapshotHubSingleBuildFanout(t *testing.T) { | |||
| 53 | // triggering their own build. | 53 | // triggering their own build. |
| 54 | const n = 3 | 54 | const n = 3 |
| 55 | chans := make([]<-chan []byte, n) | 55 | chans := make([]<-chan []byte, n) |
| 56 | for i := 0; i < n; i++ { | 56 | for i := range n { |
| 57 | ch, unsub := h.subscribe() | 57 | ch, unsub := h.subscribe() |
| 58 | defer unsub() | 58 | defer unsub() |
| 59 | chans[i] = ch | 59 | chans[i] = ch |
| @@ -67,13 +67,13 @@ func TestSnapshotHubSingleBuildFanout(t *testing.T) { | |||
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | // Still exactly one build despite three subscribers. | 69 | // Still exactly one build despite three subscribers. |
| 70 | assert.Equal(t, int64(1), atomic.LoadInt64(&builds), "subscribing must not build") | 70 | assert.Equal(t, int64(1), builds.Load(), "subscribing must not build") |
| 71 | 71 | ||
| 72 | // One wake ⇒ exactly one recompute, fanned identically to all three. | 72 | // One wake ⇒ exactly one recompute, fanned identically to all three. |
| 73 | // (The 1s ticker cannot fire within this sub-second window, so builds is | 73 | // (The 1s ticker cannot fire within this sub-second window, so builds is |
| 74 | // driven solely by the wake here.) | 74 | // driven solely by the wake here.) |
| 75 | notif.notify() | 75 | notif.notify() |
| 76 | waitFor(t, time.Second, func() bool { return atomic.LoadInt64(&builds) == 2 }) | 76 | waitFor(t, time.Second, func() bool { return builds.Load() == 2 }) |
| 77 | for i, ch := range chans { | 77 | for i, ch := range chans { |
| 78 | select { | 78 | select { |
| 79 | case b := <-ch: | 79 | case b := <-ch: |
| @@ -82,16 +82,16 @@ func TestSnapshotHubSingleBuildFanout(t *testing.T) { | |||
| 82 | t.Fatalf("subscriber %d got no wake snapshot", i) | 82 | t.Fatalf("subscriber %d got no wake snapshot", i) |
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| 85 | assert.Equal(t, int64(2), atomic.LoadInt64(&builds), | 85 | assert.Equal(t, int64(2), builds.Load(), |
| 86 | "one wake must drive exactly one build regardless of client count") | 86 | "one wake must drive exactly one build regardless of client count") |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | // TestSnapshotHubSuppressesUnchanged pins change-suppression: identical bytes | 89 | // TestSnapshotHubSuppressesUnchanged pins change-suppression: identical bytes |
| 90 | // on recompute produce no push to subscribers. | 90 | // on recompute produce no push to subscribers. |
| 91 | func TestSnapshotHubSuppressesUnchanged(t *testing.T) { | 91 | func TestSnapshotHubSuppressesUnchanged(t *testing.T) { |
| 92 | var builds int64 | 92 | var builds atomic.Int64 |
| 93 | build := func() ([]byte, error) { | 93 | build := func() ([]byte, error) { |
| 94 | atomic.AddInt64(&builds, 1) | 94 | builds.Add(1) |
| 95 | return []byte("constant"), nil // never changes | 95 | return []byte("constant"), nil // never changes |
| 96 | } | 96 | } |
| 97 | notif := newNotifier() | 97 | notif := newNotifier() |
| @@ -110,7 +110,7 @@ func TestSnapshotHubSuppressesUnchanged(t *testing.T) { | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | notif.notify() | 112 | notif.notify() |
| 113 | waitFor(t, time.Second, func() bool { return atomic.LoadInt64(&builds) >= 2 }) | 113 | waitFor(t, time.Second, func() bool { return builds.Load() >= 2 }) |
| 114 | // Bytes are unchanged, so nothing new must be delivered. | 114 | // Bytes are unchanged, so nothing new must be delivered. |
| 115 | select { | 115 | select { |
| 116 | case b := <-ch: | 116 | case b := <-ch: |
| @@ -123,9 +123,9 @@ func TestSnapshotHubSuppressesUnchanged(t *testing.T) { | |||
| 123 | // slow (never-draining) subscriber's channel holds only the newest snapshot and | 123 | // slow (never-draining) subscriber's channel holds only the newest snapshot and |
| 124 | // the central loop never blocks on it. | 124 | // the central loop never blocks on it. |
| 125 | func TestSnapshotHubLatestWins(t *testing.T) { | 125 | func TestSnapshotHubLatestWins(t *testing.T) { |
| 126 | var n int64 | 126 | var n atomic.Int64 |
| 127 | build := func() ([]byte, error) { | 127 | build := func() ([]byte, error) { |
| 128 | return []byte(fmt.Sprintf("v%d", atomic.AddInt64(&n, 1))), nil | 128 | return []byte(fmt.Sprintf("v%d", n.Add(1))), nil |
| 129 | } | 129 | } |
| 130 | notif := newNotifier() | 130 | notif := newNotifier() |
| 131 | h := newSnapshotHub(build, notif) | 131 | h := newSnapshotHub(build, notif) |
| @@ -138,12 +138,12 @@ func TestSnapshotHubLatestWins(t *testing.T) { | |||
| 138 | ch, unsub := h.subscribe() | 138 | ch, unsub := h.subscribe() |
| 139 | defer unsub() | 139 | defer unsub() |
| 140 | 140 | ||
| 141 | for i := 0; i < 5; i++ { | 141 | for i := range 5 { |
| 142 | notif.notify() | 142 | notif.notify() |
| 143 | waitFor(t, time.Second, func() bool { return atomic.LoadInt64(&n) >= int64(i+2) }) | 143 | waitFor(t, time.Second, func() bool { return n.Load() >= int64(i+2) }) |
| 144 | } | 144 | } |
| 145 | // The lone buffered value must be the LATEST, not a stale early one. | 145 | // The lone buffered value must be the LATEST, not a stale early one. |
| 146 | last := fmt.Sprintf("v%d", atomic.LoadInt64(&n)) | 146 | last := fmt.Sprintf("v%d", n.Load()) |
| 147 | select { | 147 | select { |
| 148 | case b := <-ch: | 148 | case b := <-ch: |
| 149 | assert.Equal(t, last, string(b), "slow subscriber must hold the newest snapshot") | 149 | assert.Equal(t, last, string(b), "slow subscriber must hold the newest snapshot") |
internal/server/store/store.go
| Old | New | ||
|---|---|---|---|
| @@ -537,8 +537,7 @@ func (s *Store) CreateVM(vm VM) error { | |||
| 537 | // vms_tenant_name — a name collision within the tenant. Matched by | 537 | // vms_tenant_name — a name collision within the tenant. Matched by |
| 538 | // errno, not message text: the message embeds the index's column list | 538 | // errno, not message text: the message embeds the index's column list |
| 539 | // and silently breaks on the next index change (review finding). | 539 | // and silently breaks on the next index change (review finding). |
| 540 | var serr *sqlite.Error | 540 | if serr, ok := errors.AsType[*sqlite.Error](err); ok { |
| 541 | if errors.As(err, &serr) { | ||
| 542 | switch serr.Code() { | 541 | switch serr.Code() { |
| 543 | case 2067: // SQLITE_CONSTRAINT_UNIQUE | 542 | case 2067: // SQLITE_CONSTRAINT_UNIQUE |
| 544 | return ErrNameTaken | 543 | return ErrNameTaken |
internal/server/store/store_test.go
| Old | New | ||
|---|---|---|---|
| @@ -440,7 +440,7 @@ func TestSnapshotIsAtomicUnderConcurrentWrites(t *testing.T) { | |||
| 440 | done := make(chan struct{}) | 440 | done := make(chan struct{}) |
| 441 | go func() { | 441 | go func() { |
| 442 | defer close(done) | 442 | defer close(done) |
| 443 | for i := 0; i < 300; i++ { | 443 | for range 300 { |
| 444 | id := random.Hex(8) | 444 | id := random.Hex(8) |
| 445 | _ = s.CreateVM(VM{ID: id, HostID: h.ID, Name: "vm-" + id, | 445 | _ = s.CreateVM(VM{ID: id, HostID: h.ID, Name: "vm-" + id, |
| 446 | ImageURL: "http://x/i", ImageSHA256: "abc", | 446 | ImageURL: "http://x/i", ImageSHA256: "abc", |
| @@ -449,7 +449,7 @@ func TestSnapshotIsAtomicUnderConcurrentWrites(t *testing.T) { | |||
| 449 | } | 449 | } |
| 450 | }() | 450 | }() |
| 451 | 451 | ||
| 452 | for i := 0; i < 100; i++ { | 452 | for i := range 100 { |
| 453 | _, alloc, vms, err := s.Snapshot() | 453 | _, alloc, vms, err := s.Snapshot() |
| 454 | require.NoError(t, err) | 454 | require.NoError(t, err) |
| 455 | derived := map[string]Alloc{} | 455 | derived := map[string]Alloc{} |
internal/server/syncsvc/syncsvc_test.go
| Old | New | ||
|---|---|---|---|
| @@ -310,7 +310,7 @@ func TestNoGoroutineLeakOnDisconnect(t *testing.T) { | |||
| 310 | 310 | ||
| 311 | // Warm to steady state: open several connections, read a snapshot, close. | 311 | // Warm to steady state: open several connections, read a snapshot, close. |
| 312 | const warm = 5 | 312 | const warm = 5 |
| 313 | for i := 0; i < warm; i++ { | 313 | for range warm { |
| 314 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | 314 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 315 | conn, err := quic.DialAddr(ctx, f.addr, transport.ClientTLS(f.fp), | 315 | conn, err := quic.DialAddr(ctx, f.addr, transport.ClientTLS(f.fp), |
| 316 | &quic.Config{MaxIdleTimeout: 5 * time.Second}) | 316 | &quic.Config{MaxIdleTimeout: 5 * time.Second}) |
| @@ -331,7 +331,7 @@ func TestNoGoroutineLeakOnDisconnect(t *testing.T) { | |||
| 331 | before := runtime.NumGoroutine() | 331 | before := runtime.NumGoroutine() |
| 332 | 332 | ||
| 333 | const n = 5 | 333 | const n = 5 |
| 334 | for i := 0; i < n; i++ { | 334 | for range n { |
| 335 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | 335 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 336 | conn, err := quic.DialAddr(ctx, f.addr, transport.ClientTLS(f.fp), | 336 | conn, err := quic.DialAddr(ctx, f.addr, transport.ClientTLS(f.fp), |
| 337 | &quic.Config{MaxIdleTimeout: 5 * time.Second}) | 337 | &quic.Config{MaxIdleTimeout: 5 * time.Second}) |
| @@ -391,7 +391,7 @@ func TestStalledReaderDoesNotPinServer(t *testing.T) { | |||
| 391 | // the server keeps trying to write snapshots until the window fills and the | 391 | // the server keeps trying to write snapshots until the window fills and the |
| 392 | // next write hits the 300ms deadline. | 392 | // next write hits the 300ms deadline. |
| 393 | go func() { | 393 | go func() { |
| 394 | for i := 0; i < 100; i++ { | 394 | for range 100 { |
| 395 | f.hub.Poke(f.host.ID) | 395 | f.hub.Poke(f.host.ID) |
| 396 | time.Sleep(20 * time.Millisecond) | 396 | time.Sleep(20 * time.Millisecond) |
| 397 | } | 397 | } |
internal/server/syncsvc/tracker_test.go
| Old | New | ||
|---|---|---|---|
| @@ -110,7 +110,7 @@ func TestStatusTrackerWriteThroughAtomic(t *testing.T) { | |||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | var wg sync.WaitGroup | 112 | var wg sync.WaitGroup |
| 113 | for i := 0; i < 300; i++ { | 113 | for range 300 { |
| 114 | wg.Add(2) | 114 | wg.Add(2) |
| 115 | go func() { defer wg.Done(); writer("ready") }() | 115 | go func() { defer wg.Done(); writer("ready") }() |
| 116 | go func() { defer wg.Done(); writer("failed") }() | 116 | go func() { defer wg.Done(); writer("failed") }() |
internal/shape/build.go
| Old | New | ||
|---|---|---|---|
| @@ -17,8 +17,8 @@ func Build(raw []rawPackage) Model { | |||
| 17 | // null — the viewer's JS iterates this field and would crash on null. | 17 | // null — the viewer's JS iterates this field and would crash on null. |
| 18 | imps := make([]string, 0, len(r.Imports)) | 18 | imps := make([]string, 0, len(r.Imports)) |
| 19 | for _, imp := range r.Imports { | 19 | for _, imp := range r.Imports { |
| 20 | if strings.HasPrefix(imp, module+"/") { | 20 | if after, ok := strings.CutPrefix(imp, module+"/"); ok { |
| 21 | imps = append(imps, strings.TrimPrefix(imp, module+"/")) | 21 | imps = append(imps, after) |
| 22 | } | 22 | } |
| 23 | } | 23 | } |
| 24 | sort.Strings(imps) | 24 | sort.Strings(imps) |
internal/transport/apicheck_test.go
| Old | New | ||
|---|---|---|---|
| @@ -49,8 +49,7 @@ func TestQUICAPISurface(t *testing.T) { | |||
| 49 | var _ func(context.Context) (quic.Connection, error) = lis.Accept | 49 | var _ func(context.Context) (quic.Connection, error) = lis.Accept |
| 50 | } | 50 | } |
| 51 | // Client-side: reading the peer's application close code. | 51 | // Client-side: reading the peer's application close code. |
| 52 | var appErr *quic.ApplicationError | 52 | if appErr, ok := errors.AsType[*quic.ApplicationError](error(nil)); ok { |
| 53 | if errors.As(error(nil), &appErr) { | ||
| 54 | var _ quic.ApplicationErrorCode = appErr.ErrorCode | 53 | var _ quic.ApplicationErrorCode = appErr.ErrorCode |
| 55 | } | 54 | } |
| 56 | } | 55 | } |