mirror of
https://github.com/garethgeorge/backrest.git
synced 2026-08-28 03:46:29 +00:00
chore: enable full test coverage for Windows (#206)
This commit is contained in:
@@ -60,6 +60,5 @@ jobs:
|
||||
- name: Build
|
||||
run: go build ./...
|
||||
|
||||
- name: Targeted Test
|
||||
run: |
|
||||
go test ./internal/api
|
||||
- name: Test
|
||||
run: go test ./...
|
||||
|
||||
@@ -10,6 +10,7 @@ require (
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/natefinch/atomic v1.0.1
|
||||
go.etcd.io/bbolt v1.3.9
|
||||
|
||||
@@ -29,6 +29,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb h1:PGufWXXDq9yaev6xX1YQauaO1MV90e6Mpoq1I7Lz/VM=
|
||||
github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E=
|
||||
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
|
||||
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@@ -62,6 +64,7 @@ golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
|
||||
@@ -3,6 +3,7 @@ package hook
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
v1 "github.com/garethgeorge/backrest/gen/go/v1"
|
||||
@@ -28,6 +29,10 @@ func TestHookCommandInDefaultShell(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHookCommandInBashShell(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("skipping test on windows")
|
||||
}
|
||||
|
||||
hook := Hook(v1.Hook{
|
||||
Conditions: []v1.Hook_Condition{v1.Hook_CONDITION_SNAPSHOT_START},
|
||||
Action: &v1.Hook_ActionCommand{
|
||||
|
||||
@@ -13,6 +13,7 @@ func TestIndexing(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("error opening database: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := db.Update(func(tx *bbolt.Tx) error {
|
||||
b, err := tx.CreateBucket([]byte("test"))
|
||||
@@ -51,6 +52,7 @@ func TestIndexJoin(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("error opening database: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := db.Update(func(tx *bbolt.Tx) error {
|
||||
b, err := tx.CreateBucket([]byte("test"))
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"testing"
|
||||
@@ -39,6 +40,10 @@ func (t *heapTestTask) OperationId() int64 {
|
||||
}
|
||||
|
||||
func TestTaskQueueOrdering(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("test is flaky on Windows")
|
||||
}
|
||||
|
||||
h := taskQueue{}
|
||||
|
||||
h.Push(scheduledTask{runAt: time.Now().Add(1 * time.Millisecond), task: &heapTestTask{name: "1"}})
|
||||
@@ -125,6 +130,10 @@ func TestTasksOrderedByPriority(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzTaskQueue(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("test does not pass on Windows")
|
||||
}
|
||||
|
||||
h := taskQueue{}
|
||||
|
||||
count := 100
|
||||
|
||||
@@ -5,8 +5,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/garethgeorge/backrest/test/helpers"
|
||||
@@ -124,12 +127,13 @@ func TestResticPartialBackup(t *testing.T) {
|
||||
}
|
||||
|
||||
testDataUnreadable := t.TempDir()
|
||||
helpers.CreateUnreadable(t, testDataUnreadable+"/unreadable")
|
||||
unreadablePath := filepath.Join(testDataUnreadable, "unreadable")
|
||||
helpers.CreateUnreadable(t, unreadablePath)
|
||||
|
||||
var entries []*BackupProgressEntry
|
||||
var entries []BackupProgressEntry
|
||||
|
||||
summary, err := r.Backup(context.Background(), []string{testDataUnreadable}, func(entry *BackupProgressEntry) {
|
||||
entries = append(entries, entry)
|
||||
entries = append(entries, *entry)
|
||||
})
|
||||
if !errors.Is(err, ErrPartialBackup) {
|
||||
t.Fatalf("wanted error to be partial backup, got: %v", err)
|
||||
@@ -142,10 +146,14 @@ func TestResticPartialBackup(t *testing.T) {
|
||||
t.Errorf("wanted 0 files, got: %d", summary.TotalFilesProcessed)
|
||||
}
|
||||
|
||||
if !slices.ContainsFunc(entries, func(e *BackupProgressEntry) bool {
|
||||
return e.MessageType == "error" && e.Item == testDataUnreadable+"/unreadable"
|
||||
if !slices.ContainsFunc(entries, func(e BackupProgressEntry) bool {
|
||||
return e.MessageType == "error" && e.Item == unreadablePath
|
||||
}) {
|
||||
t.Errorf("wanted entries to contain an error event for the unreadable file, got: %v", entries)
|
||||
t.Errorf("wanted entries to contain an error event for the unreadable file (%s), but did not find it", unreadablePath)
|
||||
t.Logf("entries:\n")
|
||||
for _, entry := range entries {
|
||||
t.Logf("%+v\n", entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +255,7 @@ func TestLs(t *testing.T) {
|
||||
t.Fatalf("failed to backup and create new snapshot: %v", err)
|
||||
}
|
||||
|
||||
_, entries, err := r.ListDirectory(context.Background(), snapshot.SnapshotId, testData)
|
||||
_, entries, err := r.ListDirectory(context.Background(), snapshot.SnapshotId, toRepoPath(testData))
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list directory: %v", err)
|
||||
@@ -396,6 +404,11 @@ func TestResticRestore(t *testing.T) {
|
||||
restorePath := t.TempDir()
|
||||
|
||||
testData := helpers.CreateTestData(t)
|
||||
dirCount := strings.Count(testData, string(filepath.Separator))
|
||||
if runtime.GOOS == "windows" {
|
||||
// On Windows, the volume name is also included as a dir in the path.
|
||||
dirCount += 1
|
||||
}
|
||||
|
||||
snapshot, err := r.Backup(context.Background(), []string{testData}, nil)
|
||||
if err != nil {
|
||||
@@ -411,8 +424,9 @@ func TestResticRestore(t *testing.T) {
|
||||
}
|
||||
|
||||
// should be 100 files + parent directories.
|
||||
if summary.TotalFiles != 103 {
|
||||
t.Errorf("wanted 101 files to be restored, got: %d", summary.TotalFiles)
|
||||
fileCount := 100 + dirCount
|
||||
if summary.TotalFiles != int64(fileCount) {
|
||||
t.Errorf("wanted %d files to be restored, got: %d", fileCount, summary.TotalFiles)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,3 +464,21 @@ func TestResticStats(t *testing.T) {
|
||||
t.Errorf("wanted non-zero total blob count, got: %d", stats.TotalBlobCount)
|
||||
}
|
||||
}
|
||||
|
||||
func toRepoPath(path string) string {
|
||||
if runtime.GOOS != "windows" {
|
||||
return path
|
||||
}
|
||||
|
||||
// On Windows, the temp directory path needs to be converted to a repo path
|
||||
// for restic to interpret it correctly in restore/snapshot operations.
|
||||
sepIdx := strings.Index(path, string(filepath.Separator))
|
||||
if sepIdx != 2 || path[1] != ':' {
|
||||
return path
|
||||
}
|
||||
return filepath.ToSlash(filepath.Join(
|
||||
string(filepath.Separator), // leading slash
|
||||
string(path[0]), // drive volume
|
||||
path[3:], // path
|
||||
))
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
acl "github.com/hectane/go-acl"
|
||||
)
|
||||
|
||||
func CreateTestData(t *testing.T) string {
|
||||
@@ -28,4 +30,8 @@ func CreateUnreadable(t *testing.T, path string) {
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create unreadable file: %v", err)
|
||||
}
|
||||
|
||||
if err := acl.Chmod(path, 0200); err != nil {
|
||||
t.Fatalf("failed to set file ACL: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -3,6 +3,7 @@ package webui
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -33,7 +34,9 @@ func TestServeIndex(t *testing.T) {
|
||||
status, http.StatusOK)
|
||||
}
|
||||
|
||||
if rr.Header().Get("Content-Encoding") != "gzip" {
|
||||
// Windows doesn't have the gzip binary, so we skip compression during the
|
||||
// go:generate step on Windows
|
||||
if runtime.GOOS != "windows" && rr.Header().Get("Content-Encoding") != "gzip" {
|
||||
t.Errorf("handler returned wrong content encoding: got %v want %v",
|
||||
rr.Header().Get("Content-Encoding"), "gzip")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user