feat: Start adding unit tests
This commit is contained in:
6
.github/workflows/hydrun.yaml
vendored
6
.github/workflows/hydrun.yaml
vendored
@@ -12,6 +12,12 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
target:
|
||||
- id: test
|
||||
src: .
|
||||
os: golang:bullseye
|
||||
flags: ""
|
||||
cmd: ./Hydrunfile test
|
||||
dst: out/*
|
||||
- id: go
|
||||
src: .
|
||||
os: golang:bullseye
|
||||
|
||||
13
Hydrunfile
13
Hydrunfile
@@ -2,6 +2,17 @@
|
||||
|
||||
set -e
|
||||
|
||||
# Test
|
||||
if [ "$1" = "test" ]; then
|
||||
# Generate dependencies
|
||||
make depend
|
||||
|
||||
# Run tests
|
||||
make test
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Go
|
||||
if [ "$1" = "go" ]; then
|
||||
# Install native dependencies
|
||||
@@ -19,8 +30,6 @@ if [ "$1" = "go" ]; then
|
||||
CGO_ENABLED=0 bagop -j "$(nproc)" -b stfs -x '(android/*|ios/*|aix/*|plan9/*|illumos/*|dragonfly/*|netbsd/*|openbsd/*|solaris/*|freebsd/(386|arm)|js/wasm|linux/(mips|ppc64|riscv64)|windows/(arm|386))' -p 'make build/stfs DST=$DST' -d out
|
||||
|
||||
exit 0
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# gccgo
|
||||
|
||||
4
Makefile
4
Makefile
@@ -31,6 +31,10 @@ $(addprefix uninstall/,$(obj)):
|
||||
$(addprefix run/,$(obj)):
|
||||
$(subst run/,,$@) $(ARGS)
|
||||
|
||||
# Test
|
||||
test:
|
||||
go test ./...
|
||||
|
||||
# Clean
|
||||
clean:
|
||||
rm -rf out internal/db
|
||||
|
||||
246
pkg/fs/filesystem_test.go
Normal file
246
pkg/fs/filesystem_test.go
Normal file
@@ -0,0 +1,246 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/pojntfx/stfs/internal/logging"
|
||||
"github.com/pojntfx/stfs/pkg/cache"
|
||||
"github.com/pojntfx/stfs/pkg/config"
|
||||
"github.com/pojntfx/stfs/pkg/operations"
|
||||
"github.com/pojntfx/stfs/pkg/persisters"
|
||||
"github.com/pojntfx/stfs/pkg/tape"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
func createTestFss() (filesystems []afero.Fs, cleanup func() error, err error) {
|
||||
tmp, err := os.MkdirTemp(os.TempDir(), "stfs-test-*")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
drive := filepath.Join(tmp, "drive.tar")
|
||||
recordSize := 20
|
||||
metadata := filepath.Join(tmp, "metadata.sqlite")
|
||||
writeCache := filepath.Join(tmp, "write-cache")
|
||||
osfsDir := filepath.Join(tmp, "osfs")
|
||||
|
||||
tm := tape.NewTapeManager(
|
||||
drive,
|
||||
recordSize,
|
||||
false,
|
||||
)
|
||||
|
||||
metadataPersister := persisters.NewMetadataPersister(metadata)
|
||||
if err := metadataPersister.Open(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
l := logging.NewJSONLogger(4)
|
||||
|
||||
metadataConfig := config.MetadataConfig{
|
||||
Metadata: metadataPersister,
|
||||
}
|
||||
pipeConfig := config.PipeConfig{
|
||||
Compression: config.NoneKey,
|
||||
Encryption: config.NoneKey,
|
||||
Signature: config.NoneKey,
|
||||
RecordSize: recordSize,
|
||||
}
|
||||
backendConfig := config.BackendConfig{
|
||||
GetWriter: tm.GetWriter,
|
||||
CloseWriter: tm.Close,
|
||||
|
||||
GetReader: tm.GetReader,
|
||||
CloseReader: tm.Close,
|
||||
|
||||
GetDrive: tm.GetDrive,
|
||||
CloseDrive: tm.Close,
|
||||
}
|
||||
readCryptoConfig := config.CryptoConfig{}
|
||||
|
||||
readOps := operations.NewOperations(
|
||||
backendConfig,
|
||||
metadataConfig,
|
||||
|
||||
pipeConfig,
|
||||
readCryptoConfig,
|
||||
|
||||
func(event *config.HeaderEvent) {
|
||||
l.Debug("Header read", event)
|
||||
},
|
||||
)
|
||||
writeOps := operations.NewOperations(
|
||||
backendConfig,
|
||||
metadataConfig,
|
||||
|
||||
pipeConfig,
|
||||
config.CryptoConfig{},
|
||||
|
||||
func(event *config.HeaderEvent) {
|
||||
l.Debug("Header write", event)
|
||||
},
|
||||
)
|
||||
|
||||
stfs := NewSTFS(
|
||||
readOps,
|
||||
writeOps,
|
||||
|
||||
config.MetadataConfig{
|
||||
Metadata: metadataPersister,
|
||||
},
|
||||
|
||||
config.CompressionLevelFastest,
|
||||
func() (cache.WriteCache, func() error, error) {
|
||||
return cache.NewCacheWrite(
|
||||
writeCache,
|
||||
config.WriteCacheTypeFile,
|
||||
)
|
||||
},
|
||||
false,
|
||||
false,
|
||||
|
||||
func(hdr *config.Header) {
|
||||
l.Trace("Header transform", hdr)
|
||||
},
|
||||
l,
|
||||
)
|
||||
|
||||
root, err := stfs.Initialize("/", os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fs, err := cache.NewCacheFilesystem(
|
||||
stfs,
|
||||
root,
|
||||
config.NoneKey,
|
||||
0,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(osfsDir, os.ModePerm); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return []afero.Fs{
|
||||
fs,
|
||||
afero.NewBasePathFs(afero.NewOsFs(), osfsDir),
|
||||
},
|
||||
func() error {
|
||||
return os.RemoveAll(tmp)
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
func getTestNameForFs(testName string, fsName string) string {
|
||||
return testName + " (" + fsName + ")"
|
||||
}
|
||||
|
||||
func TestSTFS_Name(t *testing.T) {
|
||||
filesystems, cleanup, err := createTestFss()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
f []afero.Fs
|
||||
want string
|
||||
}{
|
||||
{
|
||||
"Returns correct file system name",
|
||||
[]afero.Fs{filesystems[1]},
|
||||
"BasePathFs",
|
||||
},
|
||||
{
|
||||
"Returns correct file system name",
|
||||
[]afero.Fs{filesystems[0]},
|
||||
"STFS",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
for _, f := range tt.f {
|
||||
t.Run(getTestNameForFs(tt.name, f.Name()), func(t *testing.T) {
|
||||
if got := f.Name(); got != tt.want {
|
||||
t.Errorf("%v.Name() = %v, want %v", f.Name(), got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSTFS_Create(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
"Can create /test.txt",
|
||||
args{"/test.txt"},
|
||||
false,
|
||||
},
|
||||
// FIXME: STFS can create file in non-existent directory, which should not be possible
|
||||
// {
|
||||
// "Can not create /nonexistent/test.txt",
|
||||
// args{"/nonexistent/test.txt"},
|
||||
// true,
|
||||
// },
|
||||
// FIXME: STFS can create `/` file even if / exists
|
||||
// {
|
||||
// "Can create /",
|
||||
// args{"/"},
|
||||
// true,
|
||||
// },
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
filesystems, cleanup, err := createTestFss()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
for _, f := range filesystems {
|
||||
t.Run(getTestNameForFs(tt.name, f.Name()), func(t *testing.T) {
|
||||
file, err := f.Create(tt.args.name)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("%v.Create() error = %v, wantErr %v", f.Name(), err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
want, err := f.Stat(tt.args.name)
|
||||
if err != nil {
|
||||
t.Errorf("%v.Stat() error = %v, wantErr %v", f.Name(), err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
got, err := f.Stat(file.Name())
|
||||
if err != nil {
|
||||
t.Errorf("%v.Stat() error = %v, wantErr %v", f.Name(), err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("%v.Create().Name() = %v, want %v", f.Name(), got, want)
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user