Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 30 additions & 77 deletions assemble_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package desync

import (
"bytes"
"context"
"crypto/md5"
"crypto/rand"
"io"
"fmt"
"os"
"path/filepath"
"testing"
Expand All @@ -23,23 +22,17 @@ func TestExtract(t *testing.T) {
b = append(b, b...)
}
b = append(b, make([]byte, 2*ChunkSizeMaxDefault)...) // want to have at least one null-chunk in the input
in, err := os.CreateTemp("", "in")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(in.Name())
if _, err := io.Copy(in, bytes.NewReader(b)); err != nil {
t.Fatal(err)
}
in.Close()
tmp := t.TempDir()
in := filepath.Join(tmp, "in")
require.NoError(t, os.WriteFile(in, b, 0644))

// Record the checksum of the input file, used to compare to the output later
inSum := md5.Sum(b)

// Chunk the file to get an index
index, _, err := IndexFromFile(
context.Background(),
in.Name(),
in,
10,
ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault,
NewProgressBar(""),
Expand All @@ -55,7 +48,7 @@ func TestExtract(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := ChopFile(context.Background(), in.Name(), index.Chunks, s, 10, NewProgressBar("")); err != nil {
if err := ChopFile(context.Background(), in, index.Chunks, s, 10, NewProgressBar("")); err != nil {
t.Fatal(err)
}

Expand All @@ -67,36 +60,18 @@ func TestExtract(t *testing.T) {
}

// Prepare output files for each test - first a non-existing one
out1, err := os.CreateTemp("", "out1")
if err != nil {
t.Fatal(err)
}
os.Remove(out1.Name())
out1 := filepath.Join(tmp, "out1")

// This one is a complete file matching what we expect at the end
out2, err := os.CreateTemp("", "out2")
if err != nil {
t.Fatal(err)
}
if _, err := io.Copy(out2, bytes.NewReader(b)); err != nil {
t.Fatal(err)
}
out2.Close()
defer os.Remove(out2.Name())
out2 := filepath.Join(tmp, "out2")
require.NoError(t, os.WriteFile(out2, b, 0644))

// Incomplete or damaged file that has most but not all data
out3, err := os.CreateTemp("", "out3")
if err != nil {
t.Fatal(err)
}
b[0] ^= 0xff // flip some bits
b[len(b)-1] ^= 0xff
b = append(b, 0) // make it longer
if _, err := io.Copy(out3, bytes.NewReader(b)); err != nil {
t.Fatal(err)
}
out3.Close()
defer os.Remove(out3.Name())
out3 := filepath.Join(tmp, "out3")
require.NoError(t, os.WriteFile(out3, b, 0644))

// At this point we have the data needed for the test setup
// in - Temp file that represents the original input file
Expand All @@ -113,14 +88,13 @@ func TestExtract(t *testing.T) {
store Store
seed []Seed
}{
"extract to new file": {outfile: out1.Name(), store: s},
"extract to complete file": {outfile: out2.Name(), store: bs},
"extract to incomplete file": {outfile: out3.Name(), store: s},
"extract to new file": {outfile: out1, store: s},
"extract to complete file": {outfile: out2, store: bs},
"extract to incomplete file": {outfile: out3, store: s},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
defer os.Remove(test.outfile)
if _, err := AssembleFile(context.Background(), test.outfile, index, test.store, nil,
AssembleOptions{10, InvalidSeedActionBailOut},
); err != nil {
Expand Down Expand Up @@ -200,24 +174,18 @@ func TestSeed(t *testing.T) {
for name, test := range tests {
t.Run(name, func(t *testing.T) {
// Build the destination file so we can chunk it
dst, err := os.CreateTemp("", "dst")
if err != nil {
t.Fatal(err)
}
tmp := t.TempDir()
dst := filepath.Join(tmp, "dst")
dstBytes := join(test.target...)
if _, err := io.Copy(dst, bytes.NewReader(dstBytes)); err != nil {
t.Fatal(err)
}
dst.Close()
defer os.Remove(dst.Name())
require.NoError(t, os.WriteFile(dst, dstBytes, 0644))

// Record the checksum of the target file, used to compare to the output later
dstSum := md5.Sum(dstBytes)

// Chunk the file to get an index
dstIndex, _, err := IndexFromFile(
context.Background(),
dst.Name(),
dst,
10,
ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault,
NewProgressBar(""),
Expand All @@ -227,45 +195,38 @@ func TestSeed(t *testing.T) {
}

// Chop up the input file into the store
if err := ChopFile(context.Background(), dst.Name(), dstIndex.Chunks, s, 10, NewProgressBar("")); err != nil {
if err := ChopFile(context.Background(), dst, dstIndex.Chunks, s, 10, NewProgressBar("")); err != nil {
t.Fatal(err)
}

// Build the seed files and indexes then populate the array of seeds
var seeds []Seed
for _, f := range test.seeds {
seedFile, err := os.CreateTemp("", "seed")
if err != nil {
t.Fatal(err)
}
if _, err := io.Copy(seedFile, bytes.NewReader(join(f...))); err != nil {
t.Fatal(err)
}
seedFile.Close()
defer os.Remove(seedFile.Name())
for i, f := range test.seeds {
seedFile := filepath.Join(tmp, fmt.Sprintf("seed%d", i))
require.NoError(t, os.WriteFile(seedFile, join(f...), 0644))
seedIndex, _, err := IndexFromFile(
context.Background(),
seedFile.Name(),
seedFile,
10,
ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault,
NewProgressBar(""),
)
if err != nil {
t.Fatal(err)
}
seed, err := NewIndexSeed(dst.Name(), seedFile.Name(), seedIndex)
seed, err := NewIndexSeed(dst, seedFile, seedIndex)
if err != nil {
t.Fatal(err)
}
seeds = append(seeds, seed)
}

if _, err := AssembleFile(context.Background(), dst.Name(), dstIndex, s, seeds,
if _, err := AssembleFile(context.Background(), dst, dstIndex, s, seeds,
AssembleOptions{10, InvalidSeedActionBailOut},
); err != nil {
t.Fatal(err)
}
b, err := os.ReadFile(dst.Name())
b, err := os.ReadFile(dst)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -353,27 +314,19 @@ func TestSelfSeedInPlace(t *testing.T) {
sum := md5.Sum(b)

// Build a temp target file pre-populated with the correct content
dst, err := os.CreateTemp("", "dst")
if err != nil {
t.Fatal(err)
}
defer os.Remove(dst.Name())
_, err = dst.Write(b)
if err != nil {
t.Fatal(err)
}
dst.Close()
dst := filepath.Join(t.TempDir(), "dst")
require.NoError(t, os.WriteFile(dst, b, 0644))

// Extract the file
stats, err := AssembleFile(context.Background(), dst.Name(), idx, s, nil,
stats, err := AssembleFile(context.Background(), dst, idx, s, nil,
AssembleOptions{1, InvalidSeedActionBailOut},
)
if err != nil {
t.Fatal(err)
}

// Compare the checksums to that of the input data
b, err = os.ReadFile(dst.Name())
b, err = os.ReadFile(dst)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/desync/chop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestChopErrors(t *testing.T) {
{"without store",
[]string{"testdata/blob1.caibx", "testdata/blob1"}},
{"invalid store",
[]string{"-s", filepath.Join(os.TempDir(), "desync"), "testdata/blob1.caibx", "testdata/blob1"}},
[]string{"-s", filepath.Join(t.TempDir(), "desync"), "testdata/blob1.caibx", "testdata/blob1"}},
} {
t.Run(test.name, func(t *testing.T) {
cmd := newChopCommand(context.Background())
Expand Down
21 changes: 8 additions & 13 deletions cmd/desync/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@ package main

import (
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
)

func TestConfigFile(t *testing.T) {
cfgFileContent := []byte(`{"store-options": {"/path/to/store/":{"uncompressed": true}}}`)
f, err := os.CreateTemp("", "")
require.NoError(t, err)
f.Close()
defer os.Remove(f.Name())
require.NoError(t, os.WriteFile(f.Name(), cfgFileContent, 0644))
f := filepath.Join(t.TempDir(), "config")
require.NoError(t, os.WriteFile(f, cfgFileContent, 0644))

// Set the global config file name
cfgFile = f.Name()
cfgFile = f

// Call init, this should use the custom config file and global "cfg" should contain the
// values
Expand All @@ -35,21 +33,18 @@ func TestConfigFile(t *testing.T) {

func TestConfigFileMultipleMatches(t *testing.T) {
cfgFileContent := []byte(`{"store-options": {"/path/to/store/":{"uncompressed": true}, "/path/to/store":{"uncompressed": false}}}`)
f, err := os.CreateTemp("", "")
require.NoError(t, err)
f.Close()
defer os.Remove(f.Name())
require.NoError(t, os.WriteFile(f.Name(), cfgFileContent, 0644))
f := filepath.Join(t.TempDir(), "config")
require.NoError(t, os.WriteFile(f, cfgFileContent, 0644))

// Set the global config file name
cfgFile = f.Name()
cfgFile = f

// Call init, this should use the custom config file and global "cfg" should contain the
// values
initConfig()

// We expect this to fail because both "/path/to/store/" and "/path/to/store" matches the
// provided location
_, err = cfg.GetStoreOptionsFor("/path/to/store")
_, err := cfg.GetStoreOptionsFor("/path/to/store")
require.Error(t, err)
}
39 changes: 16 additions & 23 deletions cmd/desync/options_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package main

import (
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
"os"
"path/filepath"
"testing"
"time"

"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)

const defaultErrorRetry = 3
Expand Down Expand Up @@ -65,14 +67,11 @@ func TestErrorRetryOptions(t *testing.T) {
},
} {
t.Run(test.name, func(t *testing.T) {
f, err := os.CreateTemp("", "desync-options")
require.NoError(t, err)
defer os.Remove(f.Name())
_, err = f.Write(test.cfgFileContent)
require.NoError(t, err)
f := filepath.Join(t.TempDir(), "desync-options")
require.NoError(t, os.WriteFile(f, test.cfgFileContent, 0644))

// Set the global config file name
cfgFile = f.Name()
cfgFile = f

initConfig()

Expand All @@ -82,7 +81,7 @@ func TestErrorRetryOptions(t *testing.T) {
cmd.SetArgs(test.args)

// Execute the mock command, to load the options provided in the launch arguments
_, err = cmd.ExecuteC()
_, err := cmd.ExecuteC()
require.NoError(t, err)

configOptions, err := cfg.GetStoreOptionsFor("/store/20230901")
Expand Down Expand Up @@ -161,14 +160,11 @@ func TestStringOptions(t *testing.T) {
},
} {
t.Run(test.name, func(t *testing.T) {
f, err := os.CreateTemp("", "desync-options")
require.NoError(t, err)
defer os.Remove(f.Name())
_, err = f.Write(test.cfgFileContent)
require.NoError(t, err)
f := filepath.Join(t.TempDir(), "desync-options")
require.NoError(t, os.WriteFile(f, test.cfgFileContent, 0644))

// Set the global config file name
cfgFile = f.Name()
cfgFile = f

initConfig()

Expand All @@ -178,7 +174,7 @@ func TestStringOptions(t *testing.T) {
cmd.SetArgs(test.args)

// Execute the mock command, to load the options provided in the launch arguments
_, err = cmd.ExecuteC()
_, err := cmd.ExecuteC()
require.NoError(t, err)

configOptions, err := cfg.GetStoreOptionsFor("/store/20230901")
Expand Down Expand Up @@ -232,14 +228,11 @@ func TestTrustInsecureOption(t *testing.T) {
},
} {
t.Run(test.name, func(t *testing.T) {
f, err := os.CreateTemp("", "desync-options")
require.NoError(t, err)
defer os.Remove(f.Name())
_, err = f.Write(test.cfgFileContent)
require.NoError(t, err)
f := filepath.Join(t.TempDir(), "desync-options")
require.NoError(t, os.WriteFile(f, test.cfgFileContent, 0644))

// Set the global config file name
cfgFile = f.Name()
cfgFile = f

initConfig()

Expand All @@ -249,7 +242,7 @@ func TestTrustInsecureOption(t *testing.T) {
cmd.SetArgs(test.args)

// Execute the mock command, to load the options provided in the launch arguments
_, err = cmd.ExecuteC()
_, err := cmd.ExecuteC()
require.NoError(t, err)

configOptions, err := cfg.GetStoreOptionsFor("/store/20230901")
Expand Down
Loading
Loading