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 }