test(installer): add OpenSSH distro harness
Все проверки выполнены успешно
CI / test (push) Successful in 3m33s
Docker / Build and publish worker image (push) Successful in 18m37s
Все проверки выполнены успешно
CI / test (push) Successful in 3m33s
Docker / Build and publish worker image (push) Successful in 18m37s
Этот коммит содержится в:
243
internal/sshinstall/plan_test.go
Обычный файл
243
internal/sshinstall/plan_test.go
Обычный файл
@@ -0,0 +1,243 @@
|
||||
package sshinstall
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGoArch(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"x86_64": "amd64",
|
||||
"X86_64": "amd64",
|
||||
"amd64": "amd64",
|
||||
"aarch64": "arm64",
|
||||
"arm64": "arm64",
|
||||
"armv7l": "armv6l",
|
||||
"armv6l": "armv6l",
|
||||
"i686": "386",
|
||||
"i386": "386",
|
||||
"loongarch64": "loong64",
|
||||
"mips": "mips",
|
||||
"mipsel": "mipsle",
|
||||
"mips64": "mips64",
|
||||
"mips64el": "mips64le",
|
||||
"ppc64": "ppc64",
|
||||
"ppc64le": "ppc64le",
|
||||
"riscv64": "riscv64",
|
||||
"s390x": "s390x",
|
||||
}
|
||||
for in, want := range cases {
|
||||
got, err := GoArch(in)
|
||||
if err != nil || got != want {
|
||||
t.Fatalf("GoArch(%q) = %q, %v; want %q", in, got, err, want)
|
||||
}
|
||||
}
|
||||
for _, bad := range []string{"", "sparc", "x86", "mips64el-le"} {
|
||||
if _, err := GoArch(bad); err == nil {
|
||||
t.Fatalf("GoArch(%q) succeeded", bad)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestToolchainTableConsistentWithGoArch keeps GoArch and toolchainSHA in
|
||||
// sync: every `uname -m` mapping must resolve to a pinned checksum, and
|
||||
// every pinned checksum must be reachable through some `uname -m` value.
|
||||
func TestToolchainTableConsistentWithGoArch(t *testing.T) {
|
||||
// unameExamples maps a Go archive suffix to a real `uname -m` value
|
||||
// that GoArch accepts for it.
|
||||
unameExamples := map[string]string{
|
||||
"amd64": "x86_64",
|
||||
"arm64": "aarch64",
|
||||
"armv6l": "armv7l",
|
||||
"386": "i686",
|
||||
"loong64": "loongarch64",
|
||||
"mips": "mips",
|
||||
"mipsle": "mipsel",
|
||||
"mips64": "mips64",
|
||||
"mips64le": "mips64el",
|
||||
"ppc64": "ppc64",
|
||||
"ppc64le": "ppc64le",
|
||||
"riscv64": "riscv64",
|
||||
"s390x": "s390x",
|
||||
}
|
||||
for archSuffix, unameValue := range unameExamples {
|
||||
tc, err := ToolchainFor(archSuffix, DefaultGoVersion)
|
||||
if err != nil {
|
||||
t.Fatalf("GoArch(%q) = %q has no pinned checksum: %v", unameValue, archSuffix, err)
|
||||
}
|
||||
if tc.SHA256 == "" || tc.Arch != "linux-"+archSuffix {
|
||||
t.Fatalf("ToolchainFor(%q) = %+v", archSuffix, tc)
|
||||
}
|
||||
}
|
||||
for suffix := range toolchainSHA {
|
||||
arch := strings.TrimPrefix(suffix, "linux-")
|
||||
if _, ok := unameExamples[arch]; !ok {
|
||||
t.Fatalf("checksum %q is not reachable through any GoArch `uname -m` mapping", suffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolchainFor(t *testing.T) {
|
||||
tc, err := ToolchainFor("amd64", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tc.Version != DefaultGoVersion {
|
||||
t.Fatalf("version = %q, want %q", tc.Version, DefaultGoVersion)
|
||||
}
|
||||
if tc.Arch != "linux-amd64" {
|
||||
t.Fatalf("arch = %q, want linux-amd64", tc.Arch)
|
||||
}
|
||||
if tc.URL != "https://go.dev/dl/go1.26.0.linux-amd64.tar.gz" {
|
||||
t.Fatalf("url = %q", tc.URL)
|
||||
}
|
||||
if len(tc.SHA256) != 64 {
|
||||
t.Fatalf("sha = %q, want 64 hex chars", tc.SHA256)
|
||||
}
|
||||
for _, c := range tc.SHA256 {
|
||||
hexDigit := c >= '0' && c <= '9' || c >= 'a' && c <= 'f'
|
||||
if !hexDigit {
|
||||
t.Fatalf("sha %q contains non-lowercase-hex char", tc.SHA256)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolchainForArm64Pinned(t *testing.T) {
|
||||
tc, err := ToolchainFor("arm64", DefaultGoVersion)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if tc.SHA256 == "" || tc.Arch != "linux-arm64" {
|
||||
t.Fatalf("arm64 toolchain not pinned: %+v", tc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolchainForRejectsUnpinnedVersion(t *testing.T) {
|
||||
if _, err := ToolchainFor("amd64", "1.27.0"); err == nil {
|
||||
t.Fatal("unpinned Go version accepted")
|
||||
}
|
||||
if _, err := ToolchainFor("sparc", ""); err == nil {
|
||||
t.Fatal("unknown architecture accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanSourceAlpine(t *testing.T) {
|
||||
d := Detect("ID=alpine\n", prober("/sbin/openrc"))
|
||||
p, err := PlanSource(d, SourceOptions{UnameM: "x86_64"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Repo != DefaultRepo || p.Branch != DefaultBranch {
|
||||
t.Fatalf("plan defaults wrong: %+v", p)
|
||||
}
|
||||
if p.Toolchain.Arch != "linux-amd64" {
|
||||
t.Fatalf("toolchain = %+v", p.Toolchain)
|
||||
}
|
||||
if len(p.Packages) != 5 || p.Packages[0] != "git" {
|
||||
t.Fatalf("alpine packages = %v", p.Packages)
|
||||
}
|
||||
if p.InitSystem != InitOpenRC {
|
||||
t.Fatalf("init = %q, want openrc", p.InitSystem)
|
||||
}
|
||||
steps := p.Steps()
|
||||
if len(steps) != 6 {
|
||||
t.Fatalf("steps = %d, want 6", len(steps))
|
||||
}
|
||||
if steps[0].Kind != StepInstallPackages || steps[1].Kind != StepInstallToolchain {
|
||||
t.Fatalf("step order wrong: %+v", steps)
|
||||
}
|
||||
if !strings.Contains(steps[1].Detail, "Go 1.26.0") || !strings.Contains(steps[1].Detail, "linux-amd64") {
|
||||
t.Fatalf("toolchain step detail = %q", steps[1].Detail)
|
||||
}
|
||||
if !strings.Contains(steps[5].Detail, "openrc") {
|
||||
t.Fatalf("install step detail = %q", steps[5].Detail)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanSourceUbuntuArch(t *testing.T) {
|
||||
ubuntu := Detect("ID=ubuntu\n", prober("/usr/lib/systemd/system"))
|
||||
p, err := PlanSource(ubuntu, SourceOptions{UnameM: "aarch64"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Toolchain.Arch != "linux-arm64" || p.InitSystem != InitSystemd {
|
||||
t.Fatalf("ubuntu plan = %+v", p)
|
||||
}
|
||||
|
||||
arch := Detect("ID=arch\n", prober("/usr/lib/systemd/system"))
|
||||
p, err = PlanSource(arch, SourceOptions{UnameM: "x86_64"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Packages[0] != "git" || p.InitSystem != InitSystemd {
|
||||
t.Fatalf("arch plan = %+v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanSourceExplicitOverrides(t *testing.T) {
|
||||
d := Detect("ID=ubuntu\n", nil)
|
||||
p, err := PlanSource(d, SourceOptions{
|
||||
Repo: "https://example.test/worker.git",
|
||||
Branch: "release-1.0",
|
||||
GoArch: "arm64",
|
||||
BuildDir: "/srv/rsmon",
|
||||
GoModuleProxy: "https://proxy.golang.org,direct",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Repo != "https://example.test/worker.git" || p.Branch != "release-1.0" ||
|
||||
p.BuildDir != "/srv/rsmon" || p.GoModuleProxy != "https://proxy.golang.org,direct" {
|
||||
t.Fatalf("overrides not applied: %+v", p)
|
||||
}
|
||||
if p.Toolchain.Arch != "linux-arm64" {
|
||||
t.Fatalf("toolchain = %+v", p.Toolchain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanSourceErrors(t *testing.T) {
|
||||
unknown := Detect("ID=weirdos\n", nil)
|
||||
if _, err := PlanSource(unknown, SourceOptions{UnameM: "x86_64"}); err == nil {
|
||||
t.Fatal("unknown distro planned")
|
||||
}
|
||||
|
||||
ubuntu := Detect("ID=ubuntu\n", nil)
|
||||
if _, err := PlanSource(ubuntu, SourceOptions{}); err == nil {
|
||||
t.Fatal("missing architecture planned")
|
||||
}
|
||||
for _, repo := range []string{"file:///tmp/worker.git", "not-a-url", "https://ex ample/x"} {
|
||||
if _, err := PlanSource(ubuntu, SourceOptions{UnameM: "x86_64", Repo: repo}); err == nil {
|
||||
t.Fatalf("invalid repo %q planned", repo)
|
||||
}
|
||||
}
|
||||
if _, err := PlanSource(ubuntu, SourceOptions{UnameM: "x86_64", BuildDir: "relative"}); err == nil {
|
||||
t.Fatal("relative build dir planned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackagePrereqsNeverIncludeCompiler(t *testing.T) {
|
||||
for _, pkg := range []PackageManager{PkgApk, PkgApt, PkgPacman, PkgDnf} {
|
||||
for _, name := range packagePrereqs(pkg) {
|
||||
switch name {
|
||||
case "build-essential", "gcc", "g++", "base-devel", "gcc-c++", "make":
|
||||
t.Fatalf("plan includes compiler package %q", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if got := packagePrereqs(PkgUnknown); len(got) != 0 {
|
||||
t.Fatalf("unknown package manager planned packages %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRepoURLSchemes(t *testing.T) {
|
||||
for _, ok := range []string{"https://rocketgit.ru/rsmon/worker.git", "http://x/y", "git://example.test/r"} {
|
||||
if err := validateRepoURL(ok); err != nil {
|
||||
t.Fatalf("validateRepoURL(%q): %v", ok, err)
|
||||
}
|
||||
}
|
||||
for _, bad := range []string{"ssh://h@x/r", "s3://bucket/key", "x y", ""} {
|
||||
if err := validateRepoURL(bad); err == nil {
|
||||
t.Fatalf("validateRepoURL(%q) succeeded", bad)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user