From f07588a716ccff915e55feaf08c8b03b3d81bf3f Mon Sep 17 00:00:00 2001 From: Catty Steve <4795515+Catty2014@user.noreply.gitee.com> Date: Tue, 28 Apr 2026 19:12:53 +0800 Subject: [PATCH] test: add Go UPM system tests for bare prebake --- tests/upm/test_go.py | 150 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 tests/upm/test_go.py diff --git a/tests/upm/test_go.py b/tests/upm/test_go.py new file mode 100644 index 0000000..250895d --- /dev/null +++ b/tests/upm/test_go.py @@ -0,0 +1,150 @@ +"""Go UPM system tests — go install + go mod download via bare prebake.""" + +import os +import subprocess +import pytest +from probes import binary_exists + + +def _yml(actions_yaml): + return """\ +version: "1.0" +environment: + builder: "baremetal" +bootstrap: + user: "vulcan" +security: + drop_after: never +dependencies: + config: + repology_endpoint: none + system: + pacman: + packages: + user: + go: +""" + _indent(actions_yaml, 6) + + +def _indent(text, spaces): + pad = " " * spaces + return "\n".join(pad + line if line.strip() else line + for line in text.splitlines()) + + +def _query(cmd, timeout=60): + try: + r = subprocess.run(cmd, capture_output=True, text=True, + timeout=timeout, env={**os.environ, "HOME": "/root"}) + return {"success": r.returncode == 0, "stdout": r.stdout, "stderr": r.stderr} + except Exception as e: + return {"success": False, "stdout": "", "stderr": str(e)} + + +def _run_prebake(run_baker, config_path, timeout, operation, expected): + r = run_baker("prebake", config_path, timeout=timeout, + env={"RUST_LOG": os.environ.get("RUST_LOG", "info")}) + full_log = "[stdout]\n{}\n[stderr]\n{}".format(r["stdout"], r["stderr"]) + return r, full_log + + +def _check(r, full_log, operation, expected): + if r["success"]: + return + diagnosis = "" + try: + from llm import judge_log + j = judge_log(operation, expected, full_log) + diagnosis = "\n LLM diagnosis: [{}] {}".format(j.verdict, j.reason) + except Exception: + pass + pytest.fail("{} failed ({} chars):\n{}\n{}".format( + operation, len(full_log), full_log, diagnosis)) + + +def _gopath_bin(name): + """Return the expected $GOPATH/bin path or $HOME/go/bin fallback.""" + gopath = os.environ.get("GOPATH", "") + home = os.environ.get("HOME", "/root") + if not gopath: + gopath = os.path.join(home, "go") + return os.path.join(gopath, "bin", name) + + +# ── go install ────────────────────────────────────────────────────── + +def test_go_install(run_baker, work_dir): + """go install a small known tool, verify binary exists.""" + cfg = os.path.join(work_dir, "go.yml") + with open(cfg, "w") as f: + f.write(_yml("""\ +proxy: "https://goproxy.cn,direct" +packages: ["golang.org/x/tools/cmd/goimports@latest"] +""")) + + r, log = _run_prebake(run_baker, cfg, timeout=300, + operation="go install goimports", + expected="goimports binary appears in GOPATH/bin") + _check(r, log, "go install", "goimports installed") + + bin_path = _gopath_bin("goimports") + assert binary_exists(bin_path), f"goimports not found at {bin_path}" + + +# ── go mod download ───────────────────────────────────────────────── + +def test_go_mod_download(run_baker, work_dir): + """Create a minimal go.mod, download deps, verify cache populated.""" + mod_dir = os.path.join(work_dir, "testmod") + os.makedirs(mod_dir, exist_ok=True) + with open(os.path.join(mod_dir, "go.mod"), "w") as f: + f.write("module test\n\ngo 1.21\n\nrequire golang.org/x/text v0.14.0\n") + + cfg = os.path.join(work_dir, "go.yml") + with open(cfg, "w") as f: + f.write(_yml("""\ +proxy: "https://goproxy.cn,direct" +modules: ["{mod}"] +""".format(mod=os.path.join(mod_dir, "go.mod")))) + + r, log = _run_prebake(run_baker, cfg, timeout=180, + operation="go mod download", + expected="GOMODCACHE has x/text cached") + _check(r, log, "go mod download", "dependencies downloaded to module cache") + + # Check GOMODCACHE or default $GOPATH/pkg/mod + gomodcache = os.environ.get("GOMODCACHE", "") + if not gomodcache: + gopath = os.environ.get("GOPATH", + os.path.join(os.environ.get("HOME", "/root"), "go")) + gomodcache = os.path.join(gopath, "pkg", "mod") + cache_dir = os.path.join(gomodcache, "golang.org", "x") + assert os.path.isdir(cache_dir), f"no module cache at {cache_dir}" + + +# ── go install + mod download ─────────────────────────────────────── + +def test_go_full(run_baker, work_dir): + """go install a tool AND download project deps.""" + mod_dir = os.path.join(work_dir, "testmod2") + os.makedirs(mod_dir, exist_ok=True) + with open(os.path.join(mod_dir, "go.mod"), "w") as f: + f.write("module test\n\ngo 1.21\n") + + cfg = os.path.join(work_dir, "go.yml") + with open(cfg, "w") as f: + f.write(_yml("""\ +proxy: "https://goproxy.cn,direct" +packages: ["golang.org/x/tools/cmd/goimports@latest"] +modules: ["{mod}"] +env: + GOMODCACHE: "/tmp/gocache" +""".format(mod=os.path.join(mod_dir, "go.mod")))) + + r, log = _run_prebake(run_baker, cfg, timeout=300, + operation="go install + go mod download", + expected="goimports installed, module cache populated") + _check(r, log, "go full", "tool installed + deps downloaded") + + assert binary_exists(_gopath_bin("goimports")), "goimports missing" + assert os.path.isdir("/tmp/gocache"), "GOMODCACHE not created"