github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/fs/mountfs_test.go (about)

     1  // Package fs provides mountpath and FQN abstractions and methods to resolve/map stored content
     2  /*
     3   * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package fs_test
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/NVIDIA/aistore/api/apc"
    11  	"github.com/NVIDIA/aistore/cmn"
    12  	"github.com/NVIDIA/aistore/cmn/cos"
    13  	"github.com/NVIDIA/aistore/cmn/fname"
    14  	"github.com/NVIDIA/aistore/core/mock"
    15  	"github.com/NVIDIA/aistore/fs"
    16  	"github.com/NVIDIA/aistore/tools"
    17  	"github.com/NVIDIA/aistore/tools/tassert"
    18  	"github.com/NVIDIA/aistore/tools/trand"
    19  )
    20  
    21  func TestMountpathAddNonExisting(t *testing.T) {
    22  	initFS()
    23  
    24  	_, err := fs.Add("/nonexistingpath", "")
    25  	tassert.Errorf(t, err != nil, "adding non-existing mountpath succeeded")
    26  
    27  	tools.AssertMountpathCount(t, 0, 0)
    28  }
    29  
    30  func TestMountpathAddExisting(t *testing.T) {
    31  	initFS()
    32  
    33  	tools.AddMpath(t, "/tmp/abc")
    34  	tools.AssertMountpathCount(t, 1, 0)
    35  }
    36  
    37  func TestMountpathAddValid(t *testing.T) {
    38  	initFS()
    39  
    40  	mpaths := []string{"/tmp/clouder", "/tmp/locals/abc", "/tmp/locals/err"}
    41  	for _, mpath := range mpaths {
    42  		tools.AddMpath(t, mpath)
    43  	}
    44  	tools.AssertMountpathCount(t, 3, 0)
    45  
    46  	for _, mpath := range mpaths {
    47  		removedMP, err := fs.Remove(mpath)
    48  		tassert.Errorf(t, err == nil, "removing valid mountpath %q failed, err: %v", mpath, err)
    49  		tassert.Errorf(t, removedMP != nil, "expected remove to return removed mountpath")
    50  	}
    51  	tools.AssertMountpathCount(t, 0, 0)
    52  }
    53  
    54  func TestMountpathAddIncorrect(t *testing.T) {
    55  	initFS()
    56  
    57  	_, err := fs.Add("tmp/not/absolute/path", "")
    58  	tassert.Errorf(t, err != nil, "expected adding incorrect mountpath to fail")
    59  
    60  	tools.AssertMountpathCount(t, 0, 0)
    61  }
    62  
    63  func TestMountpathAddAlreadyAdded(t *testing.T) {
    64  	initFS()
    65  
    66  	mpath := "/tmp/abc"
    67  	tools.AddMpath(t, mpath)
    68  	tools.AssertMountpathCount(t, 1, 0)
    69  
    70  	_, err := fs.Add(mpath, "daeID")
    71  	tassert.Errorf(t, err != nil, "adding already added mountpath succeeded")
    72  
    73  	tools.AssertMountpathCount(t, 1, 0)
    74  }
    75  
    76  func TestMountpathRemoveNonExisting(t *testing.T) {
    77  	initFS()
    78  
    79  	removedMP, err := fs.Remove("/nonexistingpath")
    80  	tassert.Errorf(t, err != nil, "removing non-existing mountpath succeeded")
    81  	tassert.Errorf(t, removedMP == nil, "expected no mountpath removed")
    82  
    83  	tools.AssertMountpathCount(t, 0, 0)
    84  }
    85  
    86  func TestMountpathRemoveExisting(t *testing.T) {
    87  	initFS()
    88  
    89  	mpath := "/tmp/abc"
    90  	tools.AddMpath(t, mpath)
    91  
    92  	removedMP, err := fs.Remove(mpath)
    93  	tassert.CheckError(t, err)
    94  	tassert.Errorf(t, removedMP != nil, "expected remove to return removed mountpath")
    95  
    96  	tools.AssertMountpathCount(t, 0, 0)
    97  }
    98  
    99  func TestMountpathRemoveDisabled(t *testing.T) {
   100  	initFS()
   101  
   102  	mpath := "/tmp/abc"
   103  	tools.AddMpath(t, mpath)
   104  
   105  	_, err := fs.Disable(mpath)
   106  	tassert.CheckFatal(t, err)
   107  	tools.AssertMountpathCount(t, 0, 1)
   108  
   109  	removedMP, err := fs.Remove(mpath)
   110  	tassert.CheckError(t, err)
   111  	tassert.Errorf(t, removedMP != nil, "expected remove to return removed mountpath")
   112  
   113  	tools.AssertMountpathCount(t, 0, 0)
   114  }
   115  
   116  func TestMountpathDisableNonExisting(t *testing.T) {
   117  	initFS()
   118  
   119  	_, err := fs.Disable("/tmp")
   120  	tassert.Errorf(t, err != nil, "disabling non existing mountpath should not be successful")
   121  
   122  	tools.AssertMountpathCount(t, 0, 0)
   123  }
   124  
   125  func TestMountpathDisableExisting(t *testing.T) {
   126  	initFS()
   127  
   128  	mpath := "/tmp/abc"
   129  	tools.AddMpath(t, mpath)
   130  
   131  	disabledMP, err := fs.Disable(mpath)
   132  	tassert.CheckFatal(t, err)
   133  	tassert.Errorf(t, disabledMP != nil, "disabling was not successful")
   134  
   135  	tools.AssertMountpathCount(t, 0, 1)
   136  }
   137  
   138  func TestMountpathDisableAlreadyDisabled(t *testing.T) {
   139  	initFS()
   140  
   141  	mpath := "/tmp/abc"
   142  	tools.AddMpath(t, mpath)
   143  
   144  	disabledMP, err := fs.Disable(mpath)
   145  	tassert.CheckFatal(t, err)
   146  	tassert.Errorf(t, disabledMP != nil, "disabling was not successful")
   147  
   148  	disabledMP, err = fs.Disable(mpath)
   149  	tassert.CheckFatal(t, err)
   150  	tassert.Errorf(t, disabledMP == nil, "already disabled mountpath should not be disabled again")
   151  
   152  	tools.AssertMountpathCount(t, 0, 1)
   153  }
   154  
   155  func TestMountpathEnableNonExisting(t *testing.T) {
   156  	fs.TestNew(nil)
   157  	_, err := fs.Enable("/tmp")
   158  	tassert.Errorf(t, err != nil, "enabling nonexisting mountpath should end with error")
   159  
   160  	tools.AssertMountpathCount(t, 0, 0)
   161  }
   162  
   163  func TestMountpathEnableExistingButNotDisabled(t *testing.T) {
   164  	initFS()
   165  
   166  	mpath := "/tmp/abc"
   167  	tools.AddMpath(t, mpath)
   168  	enabledMP, err := fs.Enable(mpath)
   169  	tassert.CheckFatal(t, err)
   170  	tassert.Errorf(t, enabledMP == nil, "already enabled mountpath should not be enabled again")
   171  
   172  	tools.AssertMountpathCount(t, 1, 0)
   173  }
   174  
   175  func TestMountpathEnableExistingAndDisabled(t *testing.T) {
   176  	initFS()
   177  
   178  	mpath := "/tmp/abc"
   179  	tools.AddMpath(t, mpath)
   180  
   181  	disabledMP, err := fs.Disable(mpath)
   182  	tassert.CheckFatal(t, err)
   183  	tassert.Errorf(t, disabledMP != nil, "disabling was not successful")
   184  
   185  	enabled, err := fs.Enable(mpath)
   186  	tassert.CheckFatal(t, err)
   187  	tassert.Errorf(t, enabled != nil, "enabling was not successful")
   188  
   189  	tools.AssertMountpathCount(t, 1, 0)
   190  }
   191  
   192  func TestMountpathEnableAlreadyEnabled(t *testing.T) {
   193  	initFS()
   194  
   195  	mpath := "/tmp/abc"
   196  	tools.AddMpath(t, mpath)
   197  
   198  	disabledMP, err := fs.Disable(mpath)
   199  	tassert.CheckFatal(t, err)
   200  	tassert.Errorf(t, disabledMP != nil, "disabling was not successful")
   201  
   202  	tools.AssertMountpathCount(t, 0, 1)
   203  
   204  	enabledMP, err := fs.Enable(mpath)
   205  	tassert.CheckFatal(t, err)
   206  	tassert.Errorf(t, enabledMP != nil, "enabling was not successful")
   207  
   208  	enabledMP, err = fs.Enable(mpath)
   209  	tassert.CheckFatal(t, err)
   210  	tassert.Errorf(t, enabledMP == nil, "enabling already enabled mountpath should not be successful")
   211  
   212  	tools.AssertMountpathCount(t, 1, 0)
   213  }
   214  
   215  func TestMountpathsAddMultipleWithSameFSID(t *testing.T) {
   216  	fs.TestNew(mock.NewIOS())
   217  
   218  	mpath := "/tmp/abc"
   219  	tools.AddMpath(t, mpath)
   220  
   221  	_, err := fs.Add("/", "")
   222  	tassert.Errorf(t, err != nil, "expected adding path with same FSID to be unsuccessful")
   223  
   224  	tools.AssertMountpathCount(t, 1, 0)
   225  }
   226  
   227  func TestMountpathAddAndDisableMultiple(t *testing.T) {
   228  	initFS()
   229  
   230  	mp1, mp2 := "/tmp/mp1", "/tmp/mp2"
   231  	tools.AddMpath(t, mp1)
   232  	tools.AddMpath(t, mp2)
   233  
   234  	tools.AssertMountpathCount(t, 2, 0)
   235  
   236  	disabledMP, err := fs.Disable(mp1)
   237  	tassert.CheckFatal(t, err)
   238  	tassert.Errorf(t, disabledMP != nil, "disabling was not successful")
   239  	tools.AssertMountpathCount(t, 1, 1)
   240  }
   241  
   242  func TestMoveToDeleted(t *testing.T) {
   243  	initFS()
   244  
   245  	mpath := t.TempDir()
   246  	tools.AddMpath(t, mpath)
   247  
   248  	mpaths := fs.GetAvail()
   249  	mi := mpaths[mpath]
   250  
   251  	// Initially .$deleted directory should not exist.
   252  	tools.CheckPathNotExists(t, mi.DeletedRoot())
   253  
   254  	// Removing path that don't exist is still good.
   255  	err := mi.MoveToDeleted("/path/to/wonderland")
   256  	tassert.CheckFatal(t, err)
   257  
   258  	for range 5 {
   259  		topDir, _ := tools.PrepareDirTree(t, tools.DirTreeDesc{
   260  			Dirs:  10,
   261  			Files: 10,
   262  			Depth: 2,
   263  			Empty: false,
   264  		})
   265  
   266  		tools.CheckPathExists(t, topDir, true /*dir*/)
   267  
   268  		err = mi.MoveToDeleted(topDir)
   269  		tassert.CheckFatal(t, err)
   270  
   271  		tools.CheckPathNotExists(t, topDir)
   272  		tools.CheckPathExists(t, mi.DeletedRoot(), true /*dir*/)
   273  	}
   274  }
   275  
   276  func TestMoveMarkers(t *testing.T) {
   277  	tests := []struct {
   278  		name string
   279  		f    func(string, ...func()) (*fs.Mountpath, error)
   280  	}{
   281  		{name: "remove", f: fs.Remove},
   282  		{name: "disable", f: fs.Disable},
   283  	}
   284  	for _, test := range tests {
   285  		t.Run(test.name, func(t *testing.T) {
   286  			initFS()
   287  
   288  			mpath := createMountpath(t)
   289  
   290  			fatalErr, writeErr := fs.PersistMarker(fname.RebalanceMarker)
   291  			tassert.CheckFatal(t, fatalErr)
   292  			tassert.CheckFatal(t, writeErr)
   293  
   294  			createMountpath(t)
   295  
   296  			exists := fs.MarkerExists(fname.RebalanceMarker)
   297  			tassert.Fatalf(t, exists, "marker does not exist")
   298  
   299  			_, err := test.f(mpath.Path)
   300  			tassert.CheckFatal(t, err)
   301  
   302  			exists = fs.MarkerExists(fname.RebalanceMarker)
   303  			tassert.Fatalf(t, exists, "marker does not exist")
   304  		})
   305  	}
   306  }
   307  
   308  func initFS() {
   309  	fs.TestNew(mock.NewIOS())
   310  }
   311  
   312  func createMountpath(t *testing.T) *fs.Mountpath {
   313  	mpathDir := t.TempDir()
   314  	tools.AddMpath(t, mpathDir)
   315  	mpaths := fs.GetAvail()
   316  	return mpaths[mpathDir]
   317  }
   318  
   319  func BenchmarkMakePathFQN(b *testing.B) {
   320  	var (
   321  		bck = cmn.Bck{
   322  			Name:     "bck",
   323  			Provider: apc.Azure,
   324  			Ns:       cmn.Ns{Name: "name", UUID: "uuid"},
   325  		}
   326  		mi      = fs.Mountpath{Path: trand.String(200)}
   327  		objName = trand.String(15)
   328  	)
   329  
   330  	b.ReportAllocs()
   331  	b.ResetTimer()
   332  	for range b.N {
   333  		s := mi.MakePathFQN(&bck, fs.ObjectType, objName)
   334  		cos.Assert(s != "")
   335  	}
   336  }