github.com/sunvim/utils@v0.1.0/fs/fs_test.go (about) 1 package fs 2 3 import ( 4 "io" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 const ( 12 lockTestPath = "test.lock" 13 ) 14 15 var ( 16 lockTestMode = os.FileMode(0666) 17 ) 18 19 func testLockFile(t *testing.T, fs FileSystem) { 20 _ = fs.Remove(lockTestPath) 21 lock, acquiredExisting, err := fs.CreateLockFile(lockTestPath, lockTestMode) 22 if lock == nil || acquiredExisting || err != nil { 23 t.Fatal(lock, err, acquiredExisting) 24 } 25 lock2, acquiredExisting2, err2 := fs.CreateLockFile(lockTestPath, lockTestMode) 26 if lock2 != nil || acquiredExisting2 || err2 != os.ErrExist { 27 t.Fatal(lock2, acquiredExisting2, err2) 28 } 29 30 err = lock.Unlock() 31 assert.Nil(t, err) 32 33 _, err = fs.Stat(lockTestPath) 34 assert.NotNil(t, err) 35 } 36 37 func touchFile(fs FileSystem, path string) error { 38 f, err := fs.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(0666)) 39 if err != nil { 40 return err 41 } 42 return f.Close() 43 } 44 45 func testLockFileAcquireExisting(t *testing.T, fs FileSystem) { 46 err := touchFile(fs, lockTestPath) 47 assert.Nil(t, err) 48 49 lock, acquiredExisting, err := fs.CreateLockFile(lockTestPath, lockTestMode) 50 if lock == nil || !acquiredExisting || err != nil { 51 t.Fatal(lock, err, acquiredExisting) 52 } 53 54 err = lock.Unlock() 55 assert.Nil(t, err) 56 57 _, err = fs.Stat(lockTestPath) 58 assert.NotNil(t, err) 59 } 60 61 func testFS(t *testing.T, fsys FileSystem) { 62 f, err := fsys.OpenFile("test", os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(0666)) 63 assert.Nil(t, err) 64 65 buf := make([]byte, 10) 66 67 t.Run("Empty file", func(t *testing.T) { 68 off, err := f.Seek(0, io.SeekCurrent) 69 assert.Nil(t, err) 70 assert.Equal(t, int64(0), off) 71 72 n, err := f.Read(buf) 73 assert.Equal(t, 0, n) 74 assert.Equal(t, io.EOF, err) 75 76 n, err = f.ReadAt(buf, 0) 77 assert.Equal(t, 0, n) 78 assert.Equal(t, io.EOF, err) 79 80 n, err = f.ReadAt(buf, 10) 81 assert.Equal(t, 0, n) 82 assert.Equal(t, io.EOF, err) 83 84 b, err := f.Slice(1, 10) 85 assert.Equal(t, io.EOF, err) 86 assert.Nil(t, b) 87 }) 88 89 testData := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 90 91 t.Run("Write", func(t *testing.T) { 92 n, err := f.Write(testData[:9]) 93 assert.Nil(t, err) 94 assert.Equal(t, 9, n) 95 96 off, err := f.Seek(0, io.SeekCurrent) 97 assert.Nil(t, err) 98 assert.Equal(t, int64(9), off) 99 }) 100 101 t.Run("Write beyond EOF", func(t *testing.T) { 102 off, err := f.Seek(2, io.SeekStart) 103 assert.Nil(t, err) 104 assert.Equal(t, int64(2), off) 105 106 n, err := f.Write(testData[2:]) 107 assert.Nil(t, err) 108 assert.Equal(t, 8, n) 109 110 off, err = f.Seek(0, io.SeekCurrent) 111 assert.Nil(t, err) 112 assert.Equal(t, int64(10), off) 113 }) 114 115 t.Run("Slice", func(t *testing.T) { 116 b, err := f.Slice(1, 9) 117 assert.Nil(t, err) 118 assert.Equal(t, testData[1:9], b) 119 120 b, err = f.Slice(0, 10) 121 assert.Nil(t, err) 122 assert.Equal(t, testData, b) 123 124 // Offset larger than mapping. 125 b, err = f.Slice(0, 12) 126 assert.Equal(t, io.EOF, err) 127 assert.Nil(t, b) 128 }) 129 130 t.Run("WriteAt", func(t *testing.T) { 131 n, err := f.WriteAt(testData[1:4], 1) 132 assert.Nil(t, err) 133 assert.Equal(t, 3, n) 134 135 // WriteAt doesn't move offset. 136 off, err := f.Seek(0, io.SeekCurrent) 137 assert.Nil(t, err) 138 assert.Equal(t, int64(10), off) 139 }) 140 141 t.Run("Sync", func(t *testing.T) { 142 // Not tested yet, just make sure it doesn't return an error. 143 assert.Nil(t, f.Sync()) 144 }) 145 146 t.Run("ReadAt", func(t *testing.T) { 147 n, err := f.ReadAt(buf, 0) 148 assert.Nil(t, err) 149 assert.Equal(t, len(testData), n) 150 assert.Equal(t, testData, buf) 151 }) 152 153 t.Run("Read EOF", func(t *testing.T) { 154 n, err := f.Read(buf) 155 assert.Equal(t, io.EOF, err) 156 assert.Equal(t, 0, n) 157 }) 158 159 t.Run("Read", func(t *testing.T) { 160 // SeekEnd and Read 161 off, err := f.Seek(0, io.SeekEnd) 162 assert.Nil(t, err) 163 assert.Equal(t, int64(len(testData)), off) 164 165 n, err := f.Read(buf) 166 assert.Equal(t, io.EOF, err) 167 assert.Equal(t, 0, n) 168 169 // SeekStart and Read 170 off, err = f.Seek(0, io.SeekStart) 171 assert.Nil(t, err) 172 assert.Equal(t, int64(0), off) 173 174 n, err = f.Read(buf) 175 assert.Nil(t, err) 176 assert.Equal(t, len(testData), n) 177 assert.Equal(t, testData, buf) 178 179 off, err = f.Seek(0, io.SeekCurrent) 180 assert.Equal(t, int64(n), off) 181 assert.Nil(t, err) 182 183 // SeekStart 2 and Read 184 testOff := int64(2) 185 lbuf := make([]byte, 8) 186 off, err = f.Seek(testOff, io.SeekStart) 187 assert.Nil(t, err) 188 assert.Equal(t, testOff, off) 189 190 n, err = f.Read(lbuf) 191 assert.Nil(t, err) 192 assert.Equal(t, len(testData)-int(testOff), n) 193 assert.Equal(t, testData[testOff:], lbuf) 194 }) 195 196 t.Run("Read larger than file", func(t *testing.T) { 197 off, err := f.Seek(0, io.SeekStart) 198 assert.Nil(t, err) 199 assert.Equal(t, int64(0), off) 200 201 lbuf := make([]byte, 4096) 202 n, err := f.Read(lbuf) 203 assert.Nil(t, err) 204 assert.Equal(t, len(testData), n) 205 assert.Equal(t, testData, lbuf[:n]) 206 207 n, err = f.Read(lbuf) 208 assert.Equal(t, io.EOF, err) 209 assert.Equal(t, 0, n) 210 }) 211 212 t.Run("Close and Open again", func(t *testing.T) { 213 assert.Nil(t, f.Close()) 214 215 f, err = fsys.OpenFile("test", os.O_RDWR, os.FileMode(0666)) 216 assert.Nil(t, err) 217 218 b, err := f.Slice(1, 10) 219 assert.Nil(t, err) 220 assert.Equal(t, testData[1:], b) 221 }) 222 223 t.Run("Truncate extend", func(t *testing.T) { 224 err := f.Truncate(11) 225 assert.Nil(t, err) 226 227 lbuf := make([]byte, 11) 228 n, err := f.ReadAt(lbuf, 0) 229 assert.Nil(t, err) 230 assert.Equal(t, 11, n) 231 assert.Equal(t, testData, lbuf[:10]) 232 233 b, err := f.Slice(0, 11) 234 assert.Nil(t, err) 235 assert.Equal(t, testData, b[:10]) 236 237 fi, err := f.Stat() 238 assert.Nil(t, err) 239 assert.Equal(t, int64(11), fi.Size()) 240 }) 241 242 t.Run("Truncate shrink", func(t *testing.T) { 243 err := f.Truncate(1) 244 assert.Nil(t, err) 245 246 lbuf := make([]byte, 1) 247 n, err := f.ReadAt(lbuf, 0) 248 assert.Nil(t, err) 249 assert.Equal(t, 1, n) 250 assert.Equal(t, testData[:1], lbuf) 251 252 b, err := f.Slice(0, 1) 253 assert.Nil(t, err) 254 assert.Equal(t, testData[:1], b) 255 256 b, err = f.Slice(0, 10) 257 assert.Equal(t, io.EOF, err) 258 assert.Nil(t, b) 259 260 fi, err := f.Stat() 261 assert.Nil(t, err) 262 assert.Equal(t, int64(1), fi.Size()) 263 }) 264 265 t.Run("Truncate shrink to zero", func(t *testing.T) { 266 err := f.Truncate(0) 267 assert.Nil(t, err) 268 269 n, err := f.ReadAt(buf, 0) 270 assert.Equal(t, io.EOF, err) 271 assert.Equal(t, 0, n) 272 273 b, err := f.Slice(0, 1) 274 assert.Equal(t, io.EOF, err) 275 assert.Nil(t, b) 276 277 fi, err := f.Stat() 278 assert.Nil(t, err) 279 assert.Equal(t, int64(0), fi.Size()) 280 }) 281 282 t.Run("Close", func(t *testing.T) { 283 assert.Nil(t, f.Close()) 284 285 err := f.Close() 286 assert.NotNil(t, err) 287 288 _, err = f.Seek(1, io.SeekStart) 289 assert.NotNil(t, err) 290 }) 291 292 t.Run("Rename", func(t *testing.T) { 293 err := fsys.Rename("foobar", "baz") 294 assert.NotNil(t, err) 295 296 assert.Nil(t, fsys.Rename("test", "test2")) 297 fi, err := fsys.Stat("test2") 298 assert.Nil(t, err) 299 assert.Equal(t, int64(0), fi.Size()) 300 assert.Equal(t, "test2", fi.Name()) 301 }) 302 303 t.Run("ReadDir", func(t *testing.T) { 304 fis, err := fsys.ReadDir(".") 305 assert.Nil(t, err) 306 307 var hasTestFile bool 308 for _, fi := range fis { 309 if fi.Name() == "test2" { 310 hasTestFile = true 311 } 312 } 313 assert.Equal(t, true, hasTestFile) 314 }) 315 316 t.Run("Remove", func(t *testing.T) { 317 err := fsys.Remove("test2") 318 assert.Nil(t, err) 319 320 _, err = fsys.Stat("test2") 321 assert.NotNil(t, err) 322 }) 323 }