tractor.dev/toolkit-go@v0.0.0-20241010005851-214d91207d07/engine/fs/memfs/file_test.go (about) 1 // Copyright © 2014 Steve Francia <spf@spf13.com>. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package memfs 15 16 import ( 17 "bytes" 18 "io" 19 "testing" 20 "time" 21 ) 22 23 func TestFileDataNameRace(t *testing.T) { 24 t.Parallel() 25 const someName = "someName" 26 const someOtherName = "someOtherName" 27 d := FileData{ 28 name: someName, 29 } 30 31 if d.Name() != someName { 32 t.Errorf("Failed to read correct Name, was %v", d.Name()) 33 } 34 35 ChangeFileName(&d, someOtherName) 36 if d.Name() != someOtherName { 37 t.Errorf("Failed to set Name, was %v", d.Name()) 38 } 39 40 go func() { 41 ChangeFileName(&d, someName) 42 }() 43 44 if d.Name() != someName && d.Name() != someOtherName { 45 t.Errorf("Failed to read either Name, was %v", d.Name()) 46 } 47 } 48 49 func TestFileDataModTimeRace(t *testing.T) { 50 t.Parallel() 51 someTime := time.Now() 52 someOtherTime := someTime.Add(1 * time.Minute) 53 54 d := FileData{ 55 modtime: someTime, 56 } 57 58 s := FileInfo{ 59 FileData: &d, 60 } 61 62 if s.ModTime() != someTime { 63 t.Errorf("Failed to read correct value, was %v", s.ModTime()) 64 } 65 66 SetModTime(&d, someOtherTime) 67 if s.ModTime() != someOtherTime { 68 t.Errorf("Failed to set ModTime, was %v", s.ModTime()) 69 } 70 71 go func() { 72 SetModTime(&d, someTime) 73 }() 74 75 if s.ModTime() != someTime && s.ModTime() != someOtherTime { 76 t.Errorf("Failed to read either modtime, was %v", s.ModTime()) 77 } 78 } 79 80 func TestFileDataModeRace(t *testing.T) { 81 t.Parallel() 82 const someMode = 0777 83 const someOtherMode = 0660 84 85 d := FileData{ 86 mode: someMode, 87 } 88 89 s := FileInfo{ 90 FileData: &d, 91 } 92 93 if s.Mode() != someMode { 94 t.Errorf("Failed to read correct value, was %v", s.Mode()) 95 } 96 97 SetMode(&d, someOtherMode) 98 if s.Mode() != someOtherMode { 99 t.Errorf("Failed to set Mode, was %v", s.Mode()) 100 } 101 102 go func() { 103 SetMode(&d, someMode) 104 }() 105 106 if s.Mode() != someMode && s.Mode() != someOtherMode { 107 t.Errorf("Failed to read either mode, was %v", s.Mode()) 108 } 109 } 110 111 // See https://github.com/spf13/afero/issues/286. 112 func TestFileWriteAt(t *testing.T) { 113 t.Parallel() 114 115 data := CreateFile("abc.txt") 116 f := NewFileHandle(data) 117 118 testData := []byte{1, 2, 3, 4, 5} 119 offset := len(testData) 120 121 // 5 zeros + testdata 122 _, err := f.WriteAt(testData, int64(offset)) 123 if err != nil { 124 t.Fatal(err) 125 } 126 127 // 2 * testdata 128 _, err = f.WriteAt(testData, 0) 129 if err != nil { 130 t.Fatal(err) 131 } 132 133 // 3 * testdata 134 _, err = f.WriteAt(testData, int64(offset*2)) 135 if err != nil { 136 t.Fatal(err) 137 } 138 139 // 3 * testdata + 5 zeros + testdata 140 _, err = f.WriteAt(testData, int64(offset*4)) 141 if err != nil { 142 t.Fatal(err) 143 } 144 145 // 5 * testdata 146 _, err = f.WriteAt(testData, int64(offset*3)) 147 if err != nil { 148 t.Fatal(err) 149 } 150 151 err = f.Close() 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 expected := bytes.Repeat(testData, 5) 157 if !bytes.Equal(expected, data.data) { 158 t.Fatalf("expected: %v, got: %v", expected, data.data) 159 } 160 } 161 162 func TestFileDataIsDirRace(t *testing.T) { 163 t.Parallel() 164 165 d := FileData{ 166 dir: true, 167 } 168 169 s := FileInfo{ 170 FileData: &d, 171 } 172 173 if s.IsDir() != true { 174 t.Errorf("Failed to read correct value, was %v", s.IsDir()) 175 } 176 177 go func() { 178 s.Lock() 179 d.dir = false 180 s.Unlock() 181 }() 182 183 //just logging the value to trigger a read: 184 t.Logf("Value is %v", s.IsDir()) 185 } 186 187 func TestFileDataSizeRace(t *testing.T) { 188 t.Parallel() 189 190 const someData = "Hello" 191 const someOtherDataSize = "Hello World" 192 193 d := FileData{ 194 data: []byte(someData), 195 dir: false, 196 } 197 198 s := FileInfo{ 199 FileData: &d, 200 } 201 202 if s.Size() != int64(len(someData)) { 203 t.Errorf("Failed to read correct value, was %v", s.Size()) 204 } 205 206 go func() { 207 s.Lock() 208 d.data = []byte(someOtherDataSize) 209 s.Unlock() 210 }() 211 212 //just logging the value to trigger a read: 213 t.Logf("Value is %v", s.Size()) 214 215 //Testing the Dir size case 216 d.dir = true 217 if s.Size() != int64(42) { 218 t.Errorf("Failed to read correct value for dir, was %v", s.Size()) 219 } 220 } 221 222 func TestFileReadAtSeekOffset(t *testing.T) { 223 t.Parallel() 224 225 fd := CreateFile("foo") 226 f := NewFileHandle(fd) 227 228 _, err := f.WriteString("TEST") 229 if err != nil { 230 t.Fatal(err) 231 } 232 offset, err := f.Seek(0, io.SeekStart) 233 if err != nil { 234 t.Fatal(err) 235 } 236 if offset != 0 { 237 t.Fail() 238 } 239 240 offsetBeforeReadAt, err := f.Seek(0, io.SeekCurrent) 241 if err != nil { 242 t.Fatal(err) 243 } 244 if offsetBeforeReadAt != 0 { 245 t.Fatal("expected 0") 246 } 247 248 b := make([]byte, 4) 249 n, err := f.ReadAt(b, 0) 250 if err != nil { 251 t.Fatal(err) 252 } 253 if n != 4 { 254 t.Fail() 255 } 256 if string(b) != "TEST" { 257 t.Fail() 258 } 259 260 offsetAfterReadAt, err := f.Seek(0, io.SeekCurrent) 261 if err != nil { 262 t.Fatal(err) 263 } 264 if offsetAfterReadAt != offsetBeforeReadAt { 265 t.Fatal("ReadAt should not affect offset") 266 } 267 268 err = f.Close() 269 if err != nil { 270 t.Fatal(err) 271 } 272 } 273 274 func TestFileWriteAndSeek(t *testing.T) { 275 fd := CreateFile("foo") 276 f := NewFileHandle(fd) 277 278 assert := func(expected bool, v ...interface{}) { 279 if !expected { 280 t.Helper() 281 t.Fatal(v...) 282 } 283 } 284 285 data4 := []byte{0, 1, 2, 3} 286 data20 := bytes.Repeat(data4, 5) 287 var off int64 288 289 for i := 0; i < 100; i++ { 290 // write 20 bytes 291 n, err := f.Write(data20) 292 assert(err == nil, err) 293 off += int64(n) 294 assert(n == len(data20), n) 295 assert(off == int64((i+1)*len(data20)), off) 296 297 // rewind to start and write 4 bytes there 298 cur, err := f.Seek(-off, io.SeekCurrent) 299 assert(err == nil, err) 300 assert(cur == 0, cur) 301 302 n, err = f.Write(data4) 303 assert(err == nil, err) 304 assert(n == len(data4), n) 305 306 // back at the end 307 cur, err = f.Seek(off-int64(n), io.SeekCurrent) 308 assert(err == nil, err) 309 assert(cur == off, cur, off) 310 } 311 }