github.com/johnathanhowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/host/storagemanager/dependencies.go (about)

     1  package storagemanager
     2  
     3  import (
     4  	"crypto/rand"
     5  	"errors"
     6  	"io/ioutil"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/NebulousLabs/Sia/persist"
    11  )
    12  
    13  // Fake errors that get returned when a simulated failure of a dependency is
    14  // desired for testing.
    15  var (
    16  	mockErrListen       = errors.New("simulated Listen failure")
    17  	mockErrLoadFile     = errors.New("simulated LoadFile failure")
    18  	mockErrMkdirAll     = errors.New("simulated MkdirAll failure")
    19  	mockErrNewLogger    = errors.New("simulated NewLogger failure")
    20  	mockErrOpenDatabase = errors.New("simulated OpenDatabase failure")
    21  	mockErrReadFile     = errors.New("simulated ReadFile failure")
    22  	mockErrRemoveFile   = errors.New("simulated RemoveFile faulure")
    23  	mockErrSymlink      = errors.New("simulated Symlink failure")
    24  	mockErrWriteFile    = errors.New("simulated WriteFile failure")
    25  )
    26  
    27  // These interfaces define the StorageManager's dependencies. Mocking
    28  // implementation complexity can be reduced by defining each dependency as the
    29  // minimum possible subset of the real dependency.
    30  type (
    31  	// dependencies defines all of the dependencies of the StorageManager.
    32  	dependencies interface {
    33  		// loadFile allows the host to load a persistence structure form disk.
    34  		loadFile(persist.Metadata, interface{}, string) error
    35  
    36  		// mkdirAll gives the host the ability to create chains of folders
    37  		// within the filesystem.
    38  		mkdirAll(string, os.FileMode) error
    39  
    40  		// newLogger creates a logger that the host can use to log messages and
    41  		// write critical statements.
    42  		newLogger(string) (*persist.Logger, error)
    43  
    44  		// openDatabase creates a database that the host can use to interact
    45  		// with large volumes of persistent data.
    46  		openDatabase(persist.Metadata, string) (*persist.BoltDatabase, error)
    47  
    48  		// randRead fills the input bytes with random data.
    49  		randRead([]byte) (int, error)
    50  
    51  		// readFile reads a file in full from the filesystem.
    52  		readFile(string) ([]byte, error)
    53  
    54  		// removeFile removes a file from file filesystem.
    55  		removeFile(string) error
    56  
    57  		// symlink creates a sym link between a source and a destination.
    58  		symlink(s1, s2 string) error
    59  
    60  		// writeFile writes data to the filesystem using the provided filename.
    61  		writeFile(string, []byte, os.FileMode) error
    62  	}
    63  )
    64  
    65  type (
    66  	// productionDependencies is an empty struct that implements all of the
    67  	// dependencies using full featured libraries.
    68  	productionDependencies struct{}
    69  )
    70  
    71  // composeErrors will take two errors and compose them into a single errors
    72  // with a longer message. Any nil errors used as inputs will be stripped out,
    73  // and if there are zero non-nil inputs then 'nil' will be returned.
    74  func composeErrors(errs ...error) error {
    75  	// Strip out any nil errors.
    76  	var errStrings []string
    77  	for _, err := range errs {
    78  		if err != nil {
    79  			errStrings = append(errStrings, err.Error())
    80  		}
    81  	}
    82  
    83  	// Return nil if there are no non-nil errors in the input.
    84  	if len(errStrings) <= 0 {
    85  		return nil
    86  	}
    87  
    88  	// Combine all of the non-nil errors into one larger return value.
    89  	return errors.New(strings.Join(errStrings, "; "))
    90  }
    91  
    92  // loadFile allows the host to load a persistence structure form disk.
    93  func (productionDependencies) loadFile(m persist.Metadata, i interface{}, s string) error {
    94  	return persist.LoadFile(m, i, s)
    95  }
    96  
    97  // mkdirAll gives the host the ability to create chains of folders within the
    98  // filesystem.
    99  func (productionDependencies) mkdirAll(s string, fm os.FileMode) error {
   100  	return os.MkdirAll(s, fm)
   101  }
   102  
   103  // newLogger creates a logger that the host can use to log messages and write
   104  // critical statements.
   105  func (productionDependencies) newLogger(s string) (*persist.Logger, error) {
   106  	return persist.NewFileLogger(s)
   107  }
   108  
   109  // openDatabase creates a database that the host can use to interact with large
   110  // volumes of persistent data.
   111  func (productionDependencies) openDatabase(m persist.Metadata, s string) (*persist.BoltDatabase, error) {
   112  	return persist.OpenDatabase(m, s)
   113  }
   114  
   115  // randRead fills the input bytes with random data.
   116  func (productionDependencies) randRead(b []byte) (int, error) {
   117  	return rand.Read(b)
   118  }
   119  
   120  // readFile reads a file from the filesystem.
   121  func (productionDependencies) readFile(s string) ([]byte, error) {
   122  	return ioutil.ReadFile(s)
   123  }
   124  
   125  // removeFile removes a file from the filesystem.
   126  func (productionDependencies) removeFile(s string) error {
   127  	return os.Remove(s)
   128  }
   129  
   130  // symlink creates a symlink between a source and a destination file.
   131  func (productionDependencies) symlink(s1, s2 string) error {
   132  	return os.Symlink(s1, s2)
   133  }
   134  
   135  // writeFile writes a file to the filesystem.
   136  func (productionDependencies) writeFile(s string, b []byte, fm os.FileMode) error {
   137  	return ioutil.WriteFile(s, b, fm)
   138  }