diff --git a/assemble_test.go b/assemble_test.go index 88e2cb7..5aeb119 100644 --- a/assemble_test.go +++ b/assemble_test.go @@ -1,11 +1,10 @@ package desync import ( - "bytes" "context" "crypto/md5" "crypto/rand" - "io" + "fmt" "os" "path/filepath" "testing" @@ -23,15 +22,9 @@ 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) @@ -39,7 +32,7 @@ func TestExtract(t *testing.T) { // Chunk the file to get an index index, _, err := IndexFromFile( context.Background(), - in.Name(), + in, 10, ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault, NewProgressBar(""), @@ -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) } @@ -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 @@ -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 { @@ -200,16 +174,10 @@ 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) @@ -217,7 +185,7 @@ func TestSeed(t *testing.T) { // Chunk the file to get an index dstIndex, _, err := IndexFromFile( context.Background(), - dst.Name(), + dst, 10, ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault, NewProgressBar(""), @@ -227,25 +195,18 @@ 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(""), @@ -253,19 +214,19 @@ func TestSeed(t *testing.T) { 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) } @@ -353,19 +314,11 @@ 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 { @@ -373,7 +326,7 @@ func TestSelfSeedInPlace(t *testing.T) { } // 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) } diff --git a/cmd/desync/chop_test.go b/cmd/desync/chop_test.go index c9e4a5f..b8a5583 100644 --- a/cmd/desync/chop_test.go +++ b/cmd/desync/chop_test.go @@ -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()) diff --git a/cmd/desync/config_test.go b/cmd/desync/config_test.go index c485abc..1ea3fd6 100644 --- a/cmd/desync/config_test.go +++ b/cmd/desync/config_test.go @@ -2,6 +2,7 @@ package main import ( "os" + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -9,14 +10,11 @@ import ( 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 @@ -35,14 +33,11 @@ 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 @@ -50,6 +45,6 @@ func TestConfigFileMultipleMatches(t *testing.T) { // 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) } diff --git a/cmd/desync/options_test.go b/cmd/desync/options_test.go index 1361027..4bc6523 100644 --- a/cmd/desync/options_test.go +++ b/cmd/desync/options_test.go @@ -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 @@ -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() @@ -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") @@ -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() @@ -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") @@ -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() @@ -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") diff --git a/make_test.go b/make_test.go index 1b4cfb7..9ece7a1 100644 --- a/make_test.go +++ b/make_test.go @@ -7,9 +7,9 @@ import ( "crypto/sha512" "fmt" "os" + "path/filepath" "testing" - "github.com/folbricht/tempfile" "github.com/stretchr/testify/require" ) @@ -31,16 +31,9 @@ func TestParallelChunking(t *testing.T) { for name, input := range tests { t.Run(name, func(t *testing.T) { // Put the input data into a file for chunking - f, err := tempfile.New("", "") - if err != nil { - t.Fatal(err) - } - defer os.Remove(f.Name()) + f := filepath.Join(t.TempDir(), "input") b := join(input...) - if _, err := f.Write(b); err != nil { - t.Fatal(err) - } - f.Close() + require.NoError(t, os.WriteFile(f, b, 0644)) // Chunk the file single stream first to use the results as reference for // the parallel chunking @@ -66,7 +59,7 @@ func TestParallelChunking(t *testing.T) { t.Run(fmt.Sprintf("%s, n=%d", name, n), func(t *testing.T) { index, _, err := IndexFromFile( context.Background(), - f.Name(), + f, n, ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault, NewProgressBar(""), @@ -105,18 +98,14 @@ func TestIndexFromFileStats(t *testing.T) { for name, input := range tests { t.Run(name, func(t *testing.T) { - f, err := tempfile.New("", "") - require.NoError(t, err) - defer os.Remove(f.Name()) - _, err = f.Write(join(input...)) - require.NoError(t, err) - f.Close() + f := filepath.Join(t.TempDir(), "input") + require.NoError(t, os.WriteFile(f, join(input...), 0644)) for n := 2; n <= 8; n++ { t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) { index, stats, err := IndexFromFile( context.Background(), - f.Name(), + f, n, ChunkSizeMinDefault, ChunkSizeAvgDefault, ChunkSizeMaxDefault, NewProgressBar(""), diff --git a/selfseed_test.go b/selfseed_test.go index 1b44cdc..9207a4f 100644 --- a/selfseed_test.go +++ b/selfseed_test.go @@ -5,6 +5,7 @@ import ( "crypto/md5" "crypto/rand" "os" + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -95,19 +96,16 @@ func TestSelfSeed(t *testing.T) { sum := md5.Sum(b) // Build a temp target file to extract into - dst, err := os.CreateTemp("", "dst") - require.NoError(t, err) - defer os.Remove(dst.Name()) - defer dst.Close() + dst := filepath.Join(t.TempDir(), "dst") // 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}, ) require.NoError(t, err) // Compare the checksums to that of the input data - b, err = os.ReadFile(dst.Name()) + b, err = os.ReadFile(dst) require.NoError(t, err) require.Equal(t, sum, md5.Sum(b), "checksum of extracted file doesn't match expected") diff --git a/sparse-file_test.go b/sparse-file_test.go index 7315438..917b01f 100644 --- a/sparse-file_test.go +++ b/sparse-file_test.go @@ -6,6 +6,7 @@ import ( "errors" "math/rand" "os" + "path/filepath" "sync" "testing" @@ -73,9 +74,7 @@ func TestLoaderChunkRange(t *testing.T) { func TestSparseFileRead(t *testing.T) { // Sparse output file - sparseFile, err := os.CreateTemp("", "") - require.NoError(t, err) - defer os.Remove(sparseFile.Name()) + sparseFile := filepath.Join(t.TempDir(), "sparse") // Open the store s, err := NewLocalStore("testdata/blob1.store", StoreOptions{}) @@ -94,7 +93,7 @@ func TestSparseFileRead(t *testing.T) { require.NoError(t, err) // Initialize the sparse file and open a handle - sparse, err := NewSparseFile(sparseFile.Name(), index, s, SparseFileOptions{}) + sparse, err := NewSparseFile(sparseFile, index, s, SparseFileOptions{}) require.NoError(t, err) h, err := sparse.Open() require.NoError(t, err) @@ -132,9 +131,7 @@ func TestSparseFileRead(t *testing.T) { // failed load must surface an error, and a subsequent read must retry and // return the real chunk data rather than the zeroed (never-written) region. func TestSparseFileRetryAfterFailedLoad(t *testing.T) { - sparseFile, err := os.CreateTemp("", "") - require.NoError(t, err) - defer os.Remove(sparseFile.Name()) + sparseFile := filepath.Join(t.TempDir(), "sparse") s, err := NewLocalStore("testdata/blob1.store", StoreOptions{}) require.NoError(t, err) @@ -166,7 +163,7 @@ func TestSparseFileRetryAfterFailedLoad(t *testing.T) { // Store that fails the first GetChunk for the target chunk, then works. flaky := &flakyStore{Store: s, failID: target.ID, failsLeft: 1} - sparse, err := NewSparseFile(sparseFile.Name(), index, flaky, SparseFileOptions{}) + sparse, err := NewSparseFile(sparseFile, index, flaky, SparseFileOptions{}) require.NoError(t, err) h, err := sparse.Open() require.NoError(t, err)