Files
tinygo/compileopts/finalizer_coverage_test.go
T
Felipe Gené 31fff2c9a3 runtime: run syscall/js finalizers on wasm without a manual GC (#5545)
* runtime: run syscall/js finalizers on wasm without a manual GC

* runtime: address review feedback on finalizer idle GC

* runtime: clear a finished task's args pointer so its arguments are collectable

* runtime: skip the finalizer scan with a per-block registration bit

* runtime: guard the finalizer registration bitmap with gcLock

* testdata: cover finalizer invariants on every scheduler

* main_test: limit the finalizer scheduler variants to linux and darwin

* testdata: wait for the finalizer queue to drain before asserting

* testdata: make the finalizer counters atomic and wait for a known drain count

* runtime: add finalizer bookkeeping asserts under runtime_asserts

* runtime: address finalizer GC review feedback

* testdata: strengthen blocked stack finalizer test

* runtime: fix finalizer cleanup edge cases

* runtime: decouple wasm export scheduling from finalizers

* runtime: avoid redundant wakeups for re-entrant wasm exports

* runtime: simplify finalizer comments
2026-08-26 20:03:44 +02:00

66 lines
1.7 KiB
Go

package compileopts
import (
"go/build/constraint"
"os"
"path/filepath"
"strings"
"testing"
)
// TestFinalizerRunnerSchedulerCoverage verifies that each scheduler selects one runner file.
// It uses validSchedulerOptions so new schedulers are included.
func TestFinalizerRunnerSchedulerCoverage(t *testing.T) {
files := []string{
"gc_finalizer_sched.go",
"gc_finalizer_sched_none.go",
"gc_finalizer_sched_other.go",
}
exprs := make([]constraint.Expr, len(files))
for i, name := range files {
exprs[i] = readBuildConstraint(t, filepath.Join("..", "src", "runtime", name))
}
for _, sched := range validSchedulerOptions {
// The finalizer table exists under block GCs.
// gc.conservative satisfies the GC condition in every constraint.
tags := map[string]bool{
"gc.conservative": true,
"scheduler." + sched: true,
}
var matched []string
for i, expr := range exprs {
if expr.Eval(func(tag string) bool { return tags[tag] }) {
matched = append(matched, files[i])
}
}
if len(matched) != 1 {
t.Errorf("scheduler.%s: spawnFinalizerRunner defined in %d files %v, want exactly 1",
sched, len(matched), matched)
}
}
}
func readBuildConstraint(t *testing.T, path string) constraint.Expr {
t.Helper()
data, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
if constraint.IsGoBuild(line) {
expr, err := constraint.Parse(line)
if err != nil {
t.Fatalf("%s: %v", path, err)
}
return expr
}
if line != "" && !strings.HasPrefix(line, "//") {
break // reached code before any //go:build line
}
}
t.Fatalf("%s: no //go:build line found", path)
return nil
}