mirror of
https://github.com/kopia/kopia.git
synced 2025-12-23 22:57:50 -05:00
test(repository): server testability refactoring (#2612)
- removed repo.OpenAPIServer() which was only needed for testability - introduced servertesting package to replace it
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/acl"
|
||||
)
|
||||
@@ -23,9 +24,7 @@ func TestAccessLevelJSONSerialization(t *testing.T) {
|
||||
s1.E = acl.AccessLevelFull
|
||||
|
||||
v, err := json.MarshalIndent(s1, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
got := string(v)
|
||||
want := `{
|
||||
|
||||
4
internal/cache/storage_protection_test.go
vendored
4
internal/cache/storage_protection_test.go
vendored
@@ -20,9 +20,7 @@ func TestHMACStorageProtection(t *testing.T) {
|
||||
|
||||
func TestEncryptionStorageProtection(t *testing.T) {
|
||||
e, err := cache.AuthenticatedEncryptionProtection([]byte{1})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
testStorageProtection(t, e, true)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/faketime"
|
||||
"github.com/kopia/kopia/internal/gather"
|
||||
"github.com/kopia/kopia/internal/mockfs"
|
||||
@@ -28,9 +30,7 @@ func TestTimeFuncWiring(t *testing.T) {
|
||||
r0 := rep.(repo.DirectRepository)
|
||||
|
||||
_, env.RepositoryWriter, err = r0.NewDirectWriter(ctx, repo.WriteSessionOptions{Purpose: "test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
// verify wiring for the repo layer
|
||||
if got, want := env.RepositoryWriter.Time(), ft.NowFunc()(); !got.Equal(want) {
|
||||
|
||||
@@ -9,17 +9,18 @@
|
||||
"github.com/kopia/kopia/internal/apiclient"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
)
|
||||
|
||||
func TestCLIAPI(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -8,18 +8,19 @@
|
||||
"github.com/kopia/kopia/internal/apiclient"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
)
|
||||
|
||||
func TestPathsAPI(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"github.com/kopia/kopia/internal/apiclient"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
"github.com/kopia/kopia/repo/compression"
|
||||
"github.com/kopia/kopia/snapshot"
|
||||
@@ -19,13 +20,13 @@
|
||||
|
||||
func TestPolicies(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"github.com/kopia/kopia/internal/mockfs"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
"github.com/kopia/kopia/internal/uitask"
|
||||
"github.com/kopia/kopia/repo"
|
||||
@@ -46,13 +47,13 @@ func TestRestoreSnapshots(t *testing.T) {
|
||||
return nil
|
||||
}))
|
||||
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"github.com/kopia/kopia/internal/mockfs"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/repo"
|
||||
"github.com/kopia/kopia/repo/manifest"
|
||||
"github.com/kopia/kopia/snapshot"
|
||||
@@ -72,13 +73,13 @@ func TestListAndDeleteSnapshots(t *testing.T) {
|
||||
return nil
|
||||
}))
|
||||
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
@@ -201,13 +202,13 @@ func TestEditSnapshots(t *testing.T) {
|
||||
return nil
|
||||
}))
|
||||
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"github.com/kopia/kopia/internal/clock"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
"github.com/kopia/kopia/internal/uitask"
|
||||
"github.com/kopia/kopia/snapshot"
|
||||
@@ -20,13 +21,13 @@
|
||||
|
||||
func TestSnapshotCounters(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
@@ -98,15 +99,15 @@ func TestSnapshotCounters(t *testing.T) {
|
||||
|
||||
func TestSourceRefreshesAfterPolicy(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
_ = ctx
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -8,17 +8,18 @@
|
||||
"github.com/kopia/kopia/internal/apiclient"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
)
|
||||
|
||||
func TestUIPreferences(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
srvInfo := startServer(t, env, false)
|
||||
srvInfo := servertesting.StartServer(t, env, false)
|
||||
|
||||
cli, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: srvInfo.BaseURL,
|
||||
TrustedServerCertificateFingerprint: srvInfo.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -2,26 +2,17 @@
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/apiclient"
|
||||
"github.com/kopia/kopia/internal/auth"
|
||||
"github.com/kopia/kopia/internal/passwordpersist"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/server"
|
||||
"github.com/kopia/kopia/internal/testlogging"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
"github.com/kopia/kopia/repo"
|
||||
"github.com/kopia/kopia/repo/content"
|
||||
@@ -31,70 +22,11 @@
|
||||
)
|
||||
|
||||
const (
|
||||
testUsername = "foo"
|
||||
testHostname = "bar"
|
||||
testPassword = "123"
|
||||
testPathname = "/tmp/path"
|
||||
|
||||
testUIUsername = "ui-user"
|
||||
testUIPassword = "123456"
|
||||
|
||||
maxCacheSizeBytes = 1e6
|
||||
)
|
||||
|
||||
//nolint:thelper
|
||||
func startServer(t *testing.T, env *repotesting.Environment, tls bool) *repo.APIServerInfo {
|
||||
ctx := testlogging.Context(t)
|
||||
|
||||
s, err := server.New(ctx, &server.Options{
|
||||
ConfigFile: env.ConfigFile(),
|
||||
PasswordPersist: passwordpersist.File(),
|
||||
Authorizer: auth.LegacyAuthorizer(),
|
||||
Authenticator: auth.CombineAuthenticators(
|
||||
auth.AuthenticateSingleUser(testUsername+"@"+testHostname, testPassword),
|
||||
auth.AuthenticateSingleUser(testUIUsername, testUIPassword),
|
||||
),
|
||||
RefreshInterval: 1 * time.Minute,
|
||||
UIUser: testUIUsername,
|
||||
UIPreferencesFile: filepath.Join(testutil.TempDirectory(t), "ui-pref.json"),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
s.SetRepository(ctx, env.Repository)
|
||||
|
||||
// ensure we disconnect the repository before shutting down the server.
|
||||
t.Cleanup(func() { s.SetRepository(ctx, nil) })
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
asi := &repo.APIServerInfo{}
|
||||
|
||||
m := mux.NewRouter()
|
||||
s.SetupHTMLUIAPIHandlers(m)
|
||||
s.SetupRepositoryAPIHandlers(m)
|
||||
s.SetupControlAPIHandlers(m)
|
||||
s.ServeStaticFiles(m, server.AssetFile())
|
||||
|
||||
hs := httptest.NewUnstartedServer(s.GRPCRouterHandler(m))
|
||||
if tls {
|
||||
hs.EnableHTTP2 = true
|
||||
hs.StartTLS()
|
||||
serverHash := sha256.Sum256(hs.Certificate().Raw)
|
||||
asi.BaseURL = hs.URL
|
||||
asi.TrustedServerCertificateFingerprint = hex.EncodeToString(serverHash[:])
|
||||
} else {
|
||||
hs.Start()
|
||||
asi.BaseURL = hs.URL
|
||||
}
|
||||
|
||||
t.Cleanup(hs.Close)
|
||||
|
||||
return asi
|
||||
}
|
||||
|
||||
func TestServer_REST(t *testing.T) {
|
||||
testServer(t, true)
|
||||
}
|
||||
@@ -106,27 +38,25 @@ func TestServer_GRPC(t *testing.T) {
|
||||
//nolint:thelper
|
||||
func testServer(t *testing.T, disableGRPC bool) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
apiServerInfo := startServer(t, env, true)
|
||||
apiServerInfo := servertesting.StartServer(t, env, true)
|
||||
|
||||
apiServerInfo.DisableGRPC = disableGRPC
|
||||
|
||||
ctx2, cancel := context.WithCancel(ctx)
|
||||
|
||||
rep, err := repo.OpenAPIServer(ctx2, apiServerInfo, repo.ClientOptions{
|
||||
Username: testUsername,
|
||||
Hostname: testHostname,
|
||||
}, &content.CachingOptions{
|
||||
rep, err := servertesting.ConnectAndOpenAPIServer(t, ctx2, apiServerInfo, repo.ClientOptions{
|
||||
Username: servertesting.TestUsername,
|
||||
Hostname: servertesting.TestHostname,
|
||||
}, content.CachingOptions{
|
||||
CacheDirectory: testutil.TempDirectory(t),
|
||||
MaxCacheSizeBytes: maxCacheSizeBytes,
|
||||
}, testPassword)
|
||||
}, servertesting.TestPassword, &repo.Options{})
|
||||
|
||||
// cancel immediately to ensure we did not spawn goroutines that depend on ctx inside
|
||||
// repo.OpenAPIServer()
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer rep.Close(ctx)
|
||||
|
||||
@@ -135,12 +65,12 @@ func testServer(t *testing.T, disableGRPC bool) {
|
||||
|
||||
func TestGRPCServer_AuthenticationError(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
apiServerInfo := startServer(t, env, true)
|
||||
apiServerInfo := servertesting.StartServer(t, env, true)
|
||||
|
||||
if _, err := repo.OpenAPIServer(ctx, apiServerInfo, repo.ClientOptions{
|
||||
if _, err := servertesting.ConnectAndOpenAPIServer(t, ctx, apiServerInfo, repo.ClientOptions{
|
||||
Username: "bad-username",
|
||||
Hostname: "bad-hostname",
|
||||
}, nil, "bad-password"); err == nil {
|
||||
}, content.CachingOptions{}, "bad-password", &repo.Options{}); err == nil {
|
||||
t.Fatal("unexpected success when connecting with invalid username")
|
||||
}
|
||||
}
|
||||
@@ -148,21 +78,21 @@ func TestGRPCServer_AuthenticationError(t *testing.T) {
|
||||
//nolint:gocyclo
|
||||
func TestServerUIAccessDeniedToRemoteUser(t *testing.T) {
|
||||
ctx, env := repotesting.NewEnvironment(t, repotesting.FormatNotImportant)
|
||||
si := startServer(t, env, true)
|
||||
si := servertesting.StartServer(t, env, true)
|
||||
|
||||
remoteUserClient, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: si.BaseURL,
|
||||
TrustedServerCertificateFingerprint: si.TrustedServerCertificateFingerprint,
|
||||
Username: testUsername + "@" + testHostname,
|
||||
Password: testPassword,
|
||||
Username: servertesting.TestUsername + "@" + servertesting.TestHostname,
|
||||
Password: servertesting.TestPassword,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
uiUserWithoutCSRFToken, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: si.BaseURL,
|
||||
TrustedServerCertificateFingerprint: si.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
@@ -170,8 +100,8 @@ func TestServerUIAccessDeniedToRemoteUser(t *testing.T) {
|
||||
uiUserClient, err := apiclient.NewKopiaAPIClient(apiclient.Options{
|
||||
BaseURL: si.BaseURL,
|
||||
TrustedServerCertificateFingerprint: si.TrustedServerCertificateFingerprint,
|
||||
Username: testUIUsername,
|
||||
Password: testUIPassword,
|
||||
Username: servertesting.TestUIUsername,
|
||||
Password: servertesting.TestUIPassword,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
@@ -250,8 +180,8 @@ func remoteRepositoryTest(ctx context.Context, t *testing.T, rep repo.Repository
|
||||
manifestID, manifestID2 manifest.ID
|
||||
written = make([]byte, 100000)
|
||||
srcInfo = snapshot.SourceInfo{
|
||||
Host: testHostname,
|
||||
UserName: testUsername,
|
||||
Host: servertesting.TestHostname,
|
||||
UserName: servertesting.TestUsername,
|
||||
Path: testPathname,
|
||||
}
|
||||
)
|
||||
@@ -415,13 +345,11 @@ func mustListSnapshotCount(ctx context.Context, t *testing.T, rep repo.Repositor
|
||||
t.Helper()
|
||||
|
||||
snaps, err := snapshot.ListSnapshots(ctx, rep, snapshot.SourceInfo{
|
||||
UserName: testUsername,
|
||||
Host: testHostname,
|
||||
UserName: servertesting.TestUsername,
|
||||
Host: servertesting.TestHostname,
|
||||
Path: testPathname,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if got, want := len(snaps), wantCount; got != want {
|
||||
t.Fatalf("unexpected number of snapshots: %v, want %v", got, want)
|
||||
|
||||
107
internal/servertesting/servertesting.go
Normal file
107
internal/servertesting/servertesting.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// Package servertesting provides helpers for launching and testing Kopia server.
|
||||
package servertesting
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"net/http/httptest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/auth"
|
||||
"github.com/kopia/kopia/internal/passwordpersist"
|
||||
"github.com/kopia/kopia/internal/repotesting"
|
||||
"github.com/kopia/kopia/internal/server"
|
||||
"github.com/kopia/kopia/internal/testlogging"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
"github.com/kopia/kopia/repo"
|
||||
"github.com/kopia/kopia/repo/content"
|
||||
)
|
||||
|
||||
const (
|
||||
TestUsername = "foo"
|
||||
TestHostname = "bar"
|
||||
TestPassword = "123"
|
||||
|
||||
TestUIUsername = "ui-user"
|
||||
TestUIPassword = "123456"
|
||||
)
|
||||
|
||||
// StartServer starts a test server and returns APIServerInfo.
|
||||
func StartServer(t *testing.T, env *repotesting.Environment, tls bool) *repo.APIServerInfo {
|
||||
t.Helper()
|
||||
|
||||
ctx := testlogging.Context(t)
|
||||
|
||||
s, err := server.New(ctx, &server.Options{
|
||||
ConfigFile: env.ConfigFile(),
|
||||
PasswordPersist: passwordpersist.File(),
|
||||
Authorizer: auth.LegacyAuthorizer(),
|
||||
Authenticator: auth.CombineAuthenticators(
|
||||
auth.AuthenticateSingleUser(TestUsername+"@"+TestHostname, TestPassword),
|
||||
auth.AuthenticateSingleUser(TestUIUsername, TestUIPassword),
|
||||
),
|
||||
RefreshInterval: 1 * time.Minute,
|
||||
UIUser: TestUIUsername,
|
||||
UIPreferencesFile: filepath.Join(testutil.TempDirectory(t), "ui-pref.json"),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
s.SetRepository(ctx, env.Repository)
|
||||
|
||||
// ensure we disconnect the repository before shutting down the server.
|
||||
t.Cleanup(func() { s.SetRepository(ctx, nil) })
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
asi := &repo.APIServerInfo{}
|
||||
|
||||
m := mux.NewRouter()
|
||||
s.SetupHTMLUIAPIHandlers(m)
|
||||
s.SetupRepositoryAPIHandlers(m)
|
||||
s.SetupControlAPIHandlers(m)
|
||||
s.ServeStaticFiles(m, server.AssetFile())
|
||||
|
||||
hs := httptest.NewUnstartedServer(s.GRPCRouterHandler(m))
|
||||
if tls {
|
||||
hs.EnableHTTP2 = true
|
||||
hs.StartTLS()
|
||||
serverHash := sha256.Sum256(hs.Certificate().Raw)
|
||||
asi.BaseURL = hs.URL
|
||||
asi.TrustedServerCertificateFingerprint = hex.EncodeToString(serverHash[:])
|
||||
} else {
|
||||
hs.Start()
|
||||
asi.BaseURL = hs.URL
|
||||
}
|
||||
|
||||
t.Cleanup(hs.Close)
|
||||
|
||||
return asi
|
||||
}
|
||||
|
||||
// ConnectAndOpenAPIServer creates temporary config file and to and opens API server for testing.
|
||||
func ConnectAndOpenAPIServer(t *testing.T, ctx context.Context, asi *repo.APIServerInfo, rco repo.ClientOptions, caching content.CachingOptions, password string, opt *repo.Options) (repo.Repository, error) {
|
||||
t.Helper()
|
||||
|
||||
configFile := filepath.Join(t.TempDir(), "tmp.config")
|
||||
|
||||
if err := repo.ConnectAPIServer(ctx, configFile, asi, password, &repo.ConnectOptions{
|
||||
ClientOptions: rco,
|
||||
CachingOptions: caching,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
repo.Disconnect(ctx, configFile)
|
||||
})
|
||||
|
||||
//
|
||||
return repo.Open(ctx, configFile, password, opt)
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/stat"
|
||||
)
|
||||
|
||||
@@ -20,9 +22,7 @@ func TestSparseCopy(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
blk, err := stat.GetBlockSize(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
type chunk struct {
|
||||
slice []byte
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetBlockSize(t *testing.T) {
|
||||
s, err := GetBlockSize(os.DevNull)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if s <= 0 {
|
||||
t.Fatalf("invalid disk block size: %d, must be greater than 0", s)
|
||||
@@ -29,9 +29,7 @@ func TestGetFileAllocSize(t *testing.T) {
|
||||
data := bytes.Repeat([]byte{1}, size)
|
||||
|
||||
err := os.WriteFile(f, data, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
s, err := GetFileAllocSize(f)
|
||||
if err != nil {
|
||||
|
||||
@@ -139,9 +139,7 @@ func TestFileStorageConcurrency(t *testing.T) {
|
||||
st, err := New(ctx, &Options{
|
||||
Path: path,
|
||||
}, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
blobtesting.VerifyConcurrentAccess(t, st, blobtesting.ConcurrentAccessOptions{
|
||||
NumBlobs: 16,
|
||||
|
||||
@@ -38,14 +38,10 @@ func mustGetLocalTmpDir(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
tmpDir, err := os.MkdirTemp(".", ".creds")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
tmpDir, err = filepath.Abs(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
os.RemoveAll(tmpDir)
|
||||
@@ -80,9 +76,7 @@ func mustRunCommand(t *testing.T, cmd string, args ...string) []byte {
|
||||
t.Helper()
|
||||
|
||||
v, err := runAndGetOutput(t, cmd, args...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
return v
|
||||
}
|
||||
@@ -344,9 +338,7 @@ func mustReadFileToString(t *testing.T, fname string) string {
|
||||
t.Helper()
|
||||
|
||||
data, err := os.ReadFile(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
return string(data)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/clock"
|
||||
"github.com/kopia/kopia/repo/blob"
|
||||
)
|
||||
@@ -11,19 +13,13 @@ func TestGenerateSessionID(t *testing.T) {
|
||||
n := clock.Now()
|
||||
|
||||
s1, err := generateSessionID(n)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
s2, err := generateSessionID(n)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
s3, err := generateSessionID(n)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
m := map[SessionID]bool{
|
||||
s1: true,
|
||||
|
||||
@@ -55,9 +55,7 @@ func (s *formatSpecificTestSuite) TestDeleteUnreferencedBlobs(t *testing.T) {
|
||||
env.RepositoryWriter.Flush(ctx)
|
||||
|
||||
blobsBefore, err := blob.ListAllBlobs(ctx, env.RepositoryWriter.BlobStorage(), "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if got, want := len(blobsBefore), 4; got != want {
|
||||
t.Fatalf("unexpected number of blobs after writing: %v", blobsBefore)
|
||||
@@ -153,9 +151,7 @@ func (s *formatSpecificTestSuite) TestDeleteUnreferencedBlobs(t *testing.T) {
|
||||
// make sure we're back to the starting point.
|
||||
|
||||
blobsAfter, err := blob.ListAllBlobs(ctx, env.RepositoryWriter.BlobStorage(), "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(blobsBefore, blobsAfter); diff != "" {
|
||||
t.Fatalf("unexpected diff: %v", diff)
|
||||
@@ -190,9 +186,7 @@ func mustPutDummySessionBlob(t *testing.T, st blob.Storage, sessionIDSuffix blob
|
||||
t.Helper()
|
||||
|
||||
j, err := json.Marshal(si)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
h := hmac.New(sha256.New, testHMACSecret)
|
||||
h.Write(j)
|
||||
|
||||
@@ -359,9 +359,7 @@ func verifyFull(ctx context.Context, t *testing.T, om *Manager, oid ID, want []b
|
||||
func verifyNoError(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func verifyIndirectBlock(ctx context.Context, t *testing.T, om *Manager, oid ID) {
|
||||
@@ -598,14 +596,10 @@ func mustWriteObject(t *testing.T, om *Manager, data []byte, compressor compress
|
||||
defer w.Close()
|
||||
|
||||
_, err := w.Write(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
oid, err := w.Result()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
return oid
|
||||
}
|
||||
|
||||
@@ -200,9 +200,7 @@ func mustAbs(t *testing.T, p string) string {
|
||||
t.Helper()
|
||||
|
||||
p2, err := filepath.Abs(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
return p2
|
||||
}
|
||||
|
||||
@@ -337,9 +337,7 @@ func (th *testHarness) openAnother(t *testing.T) repo.RepositoryWriter {
|
||||
})
|
||||
|
||||
_, w, err := r.NewWriter(ctx, repo.WriteSessionOptions{Purpose: "test"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
return w
|
||||
}
|
||||
|
||||
@@ -7,13 +7,17 @@
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/kopia/kopia/internal/apiclient"
|
||||
"github.com/kopia/kopia/internal/serverapi"
|
||||
"github.com/kopia/kopia/internal/servertesting"
|
||||
"github.com/kopia/kopia/internal/testlogging"
|
||||
"github.com/kopia/kopia/internal/testutil"
|
||||
"github.com/kopia/kopia/internal/timetrack"
|
||||
"github.com/kopia/kopia/repo"
|
||||
"github.com/kopia/kopia/repo/blob"
|
||||
"github.com/kopia/kopia/repo/content"
|
||||
"github.com/kopia/kopia/tests/clitestutil"
|
||||
"github.com/kopia/kopia/tests/testdirtree"
|
||||
"github.com/kopia/kopia/tests/testenv"
|
||||
@@ -124,29 +128,25 @@ func testAPIServerRepository(t *testing.T, serverStartArgs []string, useGRPC, al
|
||||
|
||||
// open repository client.
|
||||
ctx2, cancel := context.WithCancel(ctx)
|
||||
rep, err := repo.OpenAPIServer(ctx2, &repo.APIServerInfo{
|
||||
rep, err := servertesting.ConnectAndOpenAPIServer(t, ctx2, &repo.APIServerInfo{
|
||||
BaseURL: sp.BaseURL,
|
||||
TrustedServerCertificateFingerprint: sp.SHA256Fingerprint,
|
||||
DisableGRPC: !useGRPC,
|
||||
}, repo.ClientOptions{
|
||||
Username: "foo",
|
||||
Hostname: "bar",
|
||||
}, nil, "baz")
|
||||
}, content.CachingOptions{}, "baz", &repo.Options{})
|
||||
|
||||
// cancel immediately to ensure we did not spawn goroutines that depend on ctx inside
|
||||
// repo.OpenAPIServer()
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
// open new write session in repository client
|
||||
|
||||
_, writeSess, err := rep.NewWriter(ctx, repo.WriteSessionOptions{Purpose: "some writer"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
logErrorAndIgnore(t, serverapi.Shutdown(ctx, controlClient))
|
||||
|
||||
@@ -257,14 +257,14 @@ func testAPIServerRepository(t *testing.T, serverStartArgs []string, useGRPC, al
|
||||
// open repository client to a dead server, this should fail quickly instead of retrying forever.
|
||||
timer := timetrack.StartTimer()
|
||||
|
||||
repo.OpenAPIServer(ctx, &repo.APIServerInfo{
|
||||
servertesting.ConnectAndOpenAPIServer(t, ctx, &repo.APIServerInfo{
|
||||
BaseURL: sp.BaseURL,
|
||||
TrustedServerCertificateFingerprint: sp.SHA256Fingerprint,
|
||||
DisableGRPC: !useGRPC,
|
||||
}, repo.ClientOptions{
|
||||
Username: "foo",
|
||||
Hostname: "bar",
|
||||
}, nil, "baz")
|
||||
}, content.CachingOptions{}, "baz", &repo.Options{})
|
||||
|
||||
//nolint:forbidigo
|
||||
if dur := timer.Elapsed(); dur > 15*time.Second {
|
||||
|
||||
@@ -182,9 +182,7 @@ func TestSnapshotRestore(t *testing.T) {
|
||||
|
||||
// create a file with well-known name.
|
||||
f, err := os.Create(filepath.Join(source, "single-file"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Fprintf(f, "some-data")
|
||||
f.Close()
|
||||
@@ -427,9 +425,7 @@ func TestRestoreSnapshotOfSingleFile(t *testing.T) {
|
||||
sourceFile := filepath.Join(sourceDir, "single-file")
|
||||
|
||||
f, err := os.Create(sourceFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Fprintf(f, "some-data")
|
||||
f.Close()
|
||||
@@ -765,9 +761,7 @@ func verifyFileMode(t *testing.T, filename string, want os.FileMode) {
|
||||
}
|
||||
|
||||
s, err := os.Lstat(filename)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
// make sure we restored permissions correctly
|
||||
if s.Mode() != want {
|
||||
@@ -779,9 +773,7 @@ func verifyValidZipFile(t *testing.T, fname string) {
|
||||
t.Helper()
|
||||
|
||||
zr, err := zip.OpenReader(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer zr.Close()
|
||||
}
|
||||
@@ -790,9 +782,8 @@ func verifyValidTarFile(t *testing.T, fname string) {
|
||||
t.Helper()
|
||||
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer f.Close()
|
||||
|
||||
verifyValidTarReader(t, tar.NewReader(f))
|
||||
@@ -815,15 +806,12 @@ func verifyValidTarGzipFile(t *testing.T, fname string) {
|
||||
t.Helper()
|
||||
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
defer f.Close()
|
||||
|
||||
gz, err := gzip.NewReader(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
verifyValidTarReader(t, tar.NewReader(gz))
|
||||
}
|
||||
@@ -842,9 +830,7 @@ func TestSnapshotRestoreByPath(t *testing.T) {
|
||||
|
||||
// create a file with well-known name.
|
||||
f, err := os.Create(filepath.Join(source, "single-file"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Fprintf(f, "some-data")
|
||||
f.Close()
|
||||
|
||||
@@ -368,17 +368,13 @@ func verifyFileExists(t *testing.T, fname string) {
|
||||
t.Helper()
|
||||
|
||||
_, err := os.Stat(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func verifyNoError(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func mustReadEnvFile(t *testing.T, fname string) map[string]string {
|
||||
|
||||
Reference in New Issue
Block a user