// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package lint import ( "os" "os/exec" "path/filepath" "strings" "testing" "sourcedock.dev/petrbalvin/gasm-devkit/arch" "sourcedock.dev/petrbalvin/gasm-devkit/parser" ) // TestGoRuntimeCorpus parses and lints every runtime .s file the local Go // toolchain ships for all four supported architectures. This is the // real-world regression net: it exercises the full breadth of each // architecture's syntax (macros, addressing modes, branch aliases) against // production assembly. It is skipped when the toolchain source is absent. // // The bar is zero parse errors and zero error-severity diagnostics; i.e. no // false "unknown instruction" / "undefined label" findings on code the real // assembler accepts. Advisory warnings are reported but not fatal, since they // are heuristics that may legitimately differ across Go versions. func TestGoRuntimeCorpus(t *testing.T) { out, err := exec.Command("go", "env", "GOROOT").Output() if err != nil { t.Skipf("cannot locate GOROOT: %v", err) } dir := filepath.Join(strings.TrimSpace(string(out)), "src", "runtime") var files []string for _, suffix := range []string{"_amd64.s", "_arm64.s", "_riscv64.s", "_loong64.s"} { matches, _ := filepath.Glob(filepath.Join(dir, "*"+suffix)) files = append(files, matches...) } if len(files) == 0 { t.Skip("Go toolchain source (src/runtime/*.s) not present") } warnings := 0 for _, path := range files { src, err := os.ReadFile(path) if err != nil { t.Fatalf("read %s: %v", path, err) } f, errs := parser.Parse(path, string(src)) if len(errs) > 0 { t.Errorf("parse %s: %v", filepath.Base(path), errs) continue } diags := File(f, Config{Arch: arch.FromFilename(path)}) for _, d := range diags { if d.Severity == Error { t.Errorf("%s:%d: error %s: %s", filepath.Base(path), d.Pos.Line, d.Code, d.Message) } else { warnings++ } } } if warnings > 0 { t.Logf("%d advisory warnings across %d files (non-fatal)", warnings, len(files)) } }