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  }