156 lines
4.5 KiB
Go
156 lines
4.5 KiB
Go
package releasearchive
|
||
|
||
import (
|
||
"archive/tar"
|
||
"archive/zip"
|
||
"compress/gzip"
|
||
"io"
|
||
"os"
|
||
"path/filepath"
|
||
"runtime"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
func TestCreateTarGzPreservesReleaseModes(t *testing.T) {
|
||
source := createFixture(t)
|
||
destination := filepath.Join(t.TempDir(), "Scert-test.tar.gz")
|
||
if err := Create(Options{
|
||
Source: source, Destination: destination, Format: FormatTarGz,
|
||
Executables: []string{"install-linux.sh", "scert", "scert-admin", "scert-nginx", "scert-storage"},
|
||
}); err != nil {
|
||
t.Fatalf("创建 Linux 发布归档失败:%v", err)
|
||
}
|
||
|
||
file, err := os.Open(destination)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer file.Close()
|
||
gzipReader, err := gzip.NewReader(file)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer gzipReader.Close()
|
||
tarReader := tar.NewReader(gzipReader)
|
||
modes := map[string]int64{}
|
||
for {
|
||
header, err := tarReader.Next()
|
||
if err == io.EOF {
|
||
break
|
||
}
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
modes[strings.TrimSuffix(header.Name, "/")] = header.Mode
|
||
}
|
||
assertMode(t, modes, "install-linux.sh", 0o755)
|
||
assertMode(t, modes, "scert", 0o755)
|
||
assertMode(t, modes, "scert-admin", 0o755)
|
||
assertMode(t, modes, "scert-nginx", 0o755)
|
||
assertMode(t, modes, "scert-storage", 0o755)
|
||
assertMode(t, modes, "web/index.html", 0o644)
|
||
assertMode(t, modes, "web", 0o755)
|
||
}
|
||
|
||
func TestCreateZipContainsReleaseFiles(t *testing.T) {
|
||
source := createFixture(t, "install-windows.ps1", "scert.exe", "scert-admin.exe")
|
||
destination := filepath.Join(t.TempDir(), "Scert-test.zip")
|
||
if err := Create(Options{Source: source, Destination: destination, Format: FormatZip}); err != nil {
|
||
t.Fatalf("创建 Windows 发布归档失败:%v", err)
|
||
}
|
||
reader, err := zip.OpenReader(destination)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer reader.Close()
|
||
expected := map[string]bool{
|
||
"install-windows.ps1": true,
|
||
"scert.exe": true,
|
||
"scert-admin.exe": true,
|
||
"web/index.html": true,
|
||
}
|
||
for _, item := range reader.File {
|
||
if item.FileInfo().IsDir() {
|
||
continue
|
||
}
|
||
if !expected[item.Name] {
|
||
t.Fatalf("Windows 发布归档出现非预期文件:%s", item.Name)
|
||
}
|
||
delete(expected, item.Name)
|
||
}
|
||
if len(expected) != 0 {
|
||
t.Fatalf("Windows 发布归档缺少必要文件:%v", expected)
|
||
}
|
||
}
|
||
|
||
func TestCreateRejectsExistingArchive(t *testing.T) {
|
||
source := createFixture(t)
|
||
destination := filepath.Join(t.TempDir(), "existing.tar.gz")
|
||
if err := os.WriteFile(destination, []byte("keep"), 0o600); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
err := Create(Options{Source: source, Destination: destination, Format: FormatTarGz})
|
||
if err == nil || !strings.Contains(err.Error(), "拒绝覆盖") {
|
||
t.Fatalf("已有发布归档未被拒绝:%v", err)
|
||
}
|
||
data, readErr := os.ReadFile(destination)
|
||
if readErr != nil || string(data) != "keep" {
|
||
t.Fatalf("已有发布归档被修改:data=%q err=%v", data, readErr)
|
||
}
|
||
}
|
||
|
||
func TestCreateRejectsMissingExecutable(t *testing.T) {
|
||
source := createFixture(t)
|
||
err := Create(Options{
|
||
Source: source, Destination: filepath.Join(t.TempDir(), "missing.tar.gz"),
|
||
Format: FormatTarGz, Executables: []string{"missing"},
|
||
})
|
||
if err == nil || !strings.Contains(err.Error(), "缺少可执行文件") {
|
||
t.Fatalf("缺少可执行文件未被拒绝:%v", err)
|
||
}
|
||
}
|
||
|
||
func TestCreateRejectsSymlink(t *testing.T) {
|
||
if runtime.GOOS == "windows" {
|
||
t.Skip("Windows 测试环境通常不允许普通用户创建符号链接")
|
||
}
|
||
source := createFixture(t)
|
||
if err := os.Symlink(filepath.Join(source, "scert"), filepath.Join(source, "linked")); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
err := Create(Options{
|
||
Source: source, Destination: filepath.Join(t.TempDir(), "linked.tar.gz"), Format: FormatTarGz,
|
||
})
|
||
if err == nil || !strings.Contains(err.Error(), "符号链接") {
|
||
t.Fatalf("发布目录符号链接未被拒绝:%v", err)
|
||
}
|
||
}
|
||
|
||
func createFixture(t *testing.T, files ...string) string {
|
||
t.Helper()
|
||
source := t.TempDir()
|
||
if err := os.MkdirAll(filepath.Join(source, "web"), 0o755); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if len(files) == 0 {
|
||
files = []string{"install-linux.sh", "scert", "scert-admin", "scert-nginx", "scert-storage"}
|
||
}
|
||
for _, name := range files {
|
||
if err := os.WriteFile(filepath.Join(source, name), []byte(name), 0o644); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
if err := os.WriteFile(filepath.Join(source, "web", "index.html"), []byte("index"), 0o600); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
return source
|
||
}
|
||
|
||
func assertMode(t *testing.T, modes map[string]int64, name string, expected int64) {
|
||
t.Helper()
|
||
if actual, ok := modes[name]; !ok || actual != expected {
|
||
t.Fatalf("归档权限不正确 %s:actual=%o expected=%o", name, actual, expected)
|
||
}
|
||
}
|