gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/filesystem/siadir/persist_test.go (about)

     1  package siadir
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"reflect"
     7  	"testing"
     8  	"time"
     9  
    10  	"gitlab.com/NebulousLabs/errors"
    11  	"gitlab.com/NebulousLabs/fastrand"
    12  	"go.sia.tech/siad/modules"
    13  	"go.sia.tech/siad/persist"
    14  )
    15  
    16  // TestPersist probes the persist subsystem
    17  func TestPersist(t *testing.T) {
    18  	t.Run("NewMetadata", testNewMetadata)
    19  
    20  	if testing.Short() {
    21  		t.SkipNow()
    22  	}
    23  	t.Parallel()
    24  
    25  	t.Run("CallLoadSiaDirMetadata", testCallLoadSiaDirMetadata)
    26  	t.Run("CreateDirMetadataAll", testCreateDirMetadataAll)
    27  }
    28  
    29  // testCallLoadSiaDirMetadata probes the callLoadSiaDirMetadata function
    30  func testCallLoadSiaDirMetadata(t *testing.T) {
    31  	testDir, err := newSiaDirTestDir(t.Name())
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	// Calling load on an empty path should return IsNotExist
    37  	_, err = callLoadSiaDirMetadata("doesntexist", modules.ProdDependencies)
    38  	if !errors.IsOSNotExist(err) {
    39  		t.Error("unexpected error", err)
    40  	}
    41  
    42  	// An empty file, should return corrupt
    43  	emptyFile := filepath.Join(testDir, "emptyFile")
    44  	f, err := os.Create(emptyFile)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	if err := f.Close(); err != nil {
    49  		t.Fatal(err)
    50  	}
    51  	_, err = callLoadSiaDirMetadata(emptyFile, modules.ProdDependencies)
    52  	if !errors.Contains(err, ErrCorruptFile) {
    53  		t.Error("unexpected error", err)
    54  	}
    55  
    56  	// A file with corrupt data should return invalid checksum
    57  	corruptFile := filepath.Join(testDir, "corruptFile")
    58  	f, err = os.Create(corruptFile)
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  	_, err = f.Write(fastrand.Bytes(100))
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	if err := f.Close(); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	_, err = callLoadSiaDirMetadata(corruptFile, modules.ProdDependencies)
    70  	if !errors.Contains(err, ErrInvalidChecksum) {
    71  		t.Error("unexpected error", err)
    72  	}
    73  
    74  	// Test happy case
    75  	happyFile := filepath.Join(testDir, modules.SiaDirExtension)
    76  	f, err = os.Create(happyFile)
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  	if err := f.Close(); err != nil {
    81  		t.Fatal(err)
    82  	}
    83  	mdNew, err := newMetadata()
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	err = saveDir(testDir, mdNew, modules.ProdDependencies)
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	_, err = callLoadSiaDirMetadata(happyFile, modules.ProdDependencies)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  }
    96  
    97  // testCreateDirMetadataAll probes the case of a potential infinite loop in
    98  // createDirMetadataAll
    99  func testCreateDirMetadataAll(t *testing.T) {
   100  	testDir, err := newSiaDirTestDir(t.Name())
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  
   105  	// Create done chan to protect against blocking test
   106  	done := make(chan struct{})
   107  	go func() {
   108  		select {
   109  		case <-done:
   110  		case <-time.After(time.Minute):
   111  			t.Error("Test didn't return in time")
   112  		}
   113  	}()
   114  
   115  	// Ignoring errors, only checking that the functions return as a regression
   116  	// test for a infinite loop bug.
   117  	createDirMetadataAll(testDir, "", persist.DefaultDiskPermissionsTest, modules.ProdDependencies)
   118  	createDirMetadataAll(testDir, ".", persist.DefaultDiskPermissionsTest, modules.ProdDependencies)
   119  	createDirMetadataAll(testDir, "/", persist.DefaultDiskPermissionsTest, modules.ProdDependencies)
   120  	close(done)
   121  
   122  	// Test cleanup. This is needed because the above test cases create a .siadir
   123  	// in the current directory.
   124  	err = os.Remove(modules.SiaDirExtension)
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  }
   129  
   130  // testNewMetadata probes the newMetadata function
   131  func testNewMetadata(t *testing.T) {
   132  	md := Metadata{
   133  		AggregateHealth:        DefaultDirHealth,
   134  		AggregateMinRedundancy: DefaultDirRedundancy,
   135  		AggregateRemoteHealth:  DefaultDirHealth,
   136  		AggregateStuckHealth:   DefaultDirHealth,
   137  
   138  		Health:        DefaultDirHealth,
   139  		MinRedundancy: DefaultDirRedundancy,
   140  		Mode:          modules.DefaultDirPerm,
   141  		RemoteHealth:  DefaultDirHealth,
   142  		StuckHealth:   DefaultDirHealth,
   143  		Version:       metadataVersion,
   144  	}
   145  	mdNew, err := newMetadata()
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  
   150  	// Sync the time fields
   151  	md.AggregateModTime = mdNew.AggregateModTime
   152  	md.ModTime = mdNew.ModTime
   153  
   154  	// Metadatas should match
   155  	if !reflect.DeepEqual(md, mdNew) {
   156  		t.Log("expected:", md)
   157  		t.Log("actual:", mdNew)
   158  		t.Fatal("metadata mismtach")
   159  	}
   160  }