go-hep.org/x/hep@v0.38.1/xrootd/filesystem_mock_test.go (about)

     1  // Copyright ©2018 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package xrootd // import "go-hep.org/x/hep/xrootd"
     6  
     7  import (
     8  	"context"
     9  	"net"
    10  	"reflect"
    11  	"testing"
    12  
    13  	"go-hep.org/x/hep/xrootd/xrdfs"
    14  	"go-hep.org/x/hep/xrootd/xrdproto"
    15  	"go-hep.org/x/hep/xrootd/xrdproto/chmod"
    16  	"go-hep.org/x/hep/xrootd/xrdproto/dirlist"
    17  	"go-hep.org/x/hep/xrootd/xrdproto/mkdir"
    18  	"go-hep.org/x/hep/xrootd/xrdproto/mv"
    19  	"go-hep.org/x/hep/xrootd/xrdproto/open"
    20  	"go-hep.org/x/hep/xrootd/xrdproto/rm"
    21  	"go-hep.org/x/hep/xrootd/xrdproto/rmdir"
    22  	"go-hep.org/x/hep/xrootd/xrdproto/stat"
    23  	"go-hep.org/x/hep/xrootd/xrdproto/statx"
    24  	"go-hep.org/x/hep/xrootd/xrdproto/truncate"
    25  )
    26  
    27  func TestFileSystem_Dirlist_Mock(t *testing.T) {
    28  	t.Parallel()
    29  
    30  	path := "/tmp/test"
    31  	want := []xrdfs.EntryStat{
    32  		{
    33  			EntryName:   "testfile",
    34  			EntrySize:   20,
    35  			Mtime:       10,
    36  			HasStatInfo: true,
    37  		},
    38  		{
    39  			EntryName:   "testfile2",
    40  			EntrySize:   21,
    41  			Mtime:       12,
    42  			HasStatInfo: true,
    43  			Flags:       xrdfs.StatIsDir,
    44  		},
    45  	}
    46  	wantRequest := dirlist.Request{
    47  		Options: dirlist.WithStatInfo,
    48  		Path:    path,
    49  	}
    50  
    51  	serverFunc := func(cancel func(), conn net.Conn) {
    52  		data, err := xrdproto.ReadRequest(conn)
    53  		if err != nil {
    54  			cancel()
    55  			t.Fatalf("could not read request: %v", err)
    56  		}
    57  
    58  		var gotRequest dirlist.Request
    59  		gotHeader, err := unmarshalRequest(data, &gotRequest)
    60  		if err != nil {
    61  			cancel()
    62  			t.Fatalf("could not unmarshal request: %v", err)
    63  		}
    64  
    65  		if !reflect.DeepEqual(gotRequest, wantRequest) {
    66  			cancel()
    67  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
    68  		}
    69  
    70  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, dirlist.Response{Entries: want, WithStatInfo: true})
    71  		if err != nil {
    72  			cancel()
    73  			t.Fatalf("could not write response: %v", err)
    74  		}
    75  	}
    76  
    77  	clientFunc := func(cancel func(), client *Client) {
    78  		fs := client.FS()
    79  		got, err := fs.Dirlist(context.Background(), path)
    80  		if err != nil {
    81  			t.Fatalf("invalid dirlist call: %v", err)
    82  		}
    83  		if !reflect.DeepEqual(got, want) {
    84  			t.Fatalf("dirlist info does not match:\ngot = %v\nwant = %v", got, want)
    85  		}
    86  	}
    87  
    88  	testClientWithMockServer(serverFunc, clientFunc)
    89  }
    90  
    91  func TestFileSystem_Dirlist_Mock_WithoutStatInfo(t *testing.T) {
    92  	t.Parallel()
    93  
    94  	path := "/tmp/test"
    95  
    96  	var want = []xrdfs.EntryStat{
    97  		{
    98  			EntryName:   "testfile",
    99  			HasStatInfo: false,
   100  		},
   101  		{
   102  			EntryName:   "testfile2",
   103  			HasStatInfo: false,
   104  		},
   105  	}
   106  
   107  	var wantRequest = dirlist.Request{
   108  		Options: dirlist.WithStatInfo,
   109  		Path:    path,
   110  	}
   111  
   112  	serverFunc := func(cancel func(), conn net.Conn) {
   113  		data, err := xrdproto.ReadRequest(conn)
   114  		if err != nil {
   115  			cancel()
   116  			t.Fatalf("could not read request: %v", err)
   117  		}
   118  
   119  		var gotRequest dirlist.Request
   120  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   121  		if err != nil {
   122  			cancel()
   123  			t.Fatalf("could not unmarshal request: %v", err)
   124  		}
   125  
   126  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   127  			cancel()
   128  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   129  		}
   130  
   131  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, dirlist.Response{Entries: want, WithStatInfo: false})
   132  		if err != nil {
   133  			cancel()
   134  			t.Fatalf("could not write response: %v", err)
   135  		}
   136  	}
   137  
   138  	clientFunc := func(cancel func(), client *Client) {
   139  		fs := fileSystem{client}
   140  		got, err := fs.Dirlist(context.Background(), path)
   141  		if err != nil {
   142  			t.Fatalf("invalid dirlist call: %v", err)
   143  		}
   144  		if !reflect.DeepEqual(got, want) {
   145  			t.Fatalf("dirlist info does not match:\ngot = %v\nwant = %v", got, want)
   146  		}
   147  	}
   148  
   149  	testClientWithMockServer(serverFunc, clientFunc)
   150  }
   151  
   152  func testFileSystem_Open_Mock(t *testing.T, wantFileHandle xrdfs.FileHandle, wantFileCompression *xrdfs.FileCompression, wantFileInfo *xrdfs.EntryStat) {
   153  	path := "/tmp/test"
   154  
   155  	var wantRequest = open.Request{
   156  		Path:    path,
   157  		Mode:    xrdfs.OpenModeOtherRead,
   158  		Options: xrdfs.OpenOptionsOpenRead,
   159  	}
   160  
   161  	serverFunc := func(cancel func(), conn net.Conn) {
   162  		data, err := xrdproto.ReadRequest(conn)
   163  		if err != nil {
   164  			cancel()
   165  			t.Fatalf("could not read request: %v", err)
   166  		}
   167  
   168  		var gotRequest open.Request
   169  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   170  		if err != nil {
   171  			cancel()
   172  			t.Fatalf("could not unmarshal request: %v", err)
   173  		}
   174  
   175  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   176  			cancel()
   177  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   178  		}
   179  
   180  		response := open.Response{
   181  			FileHandle:  wantFileHandle,
   182  			Compression: wantFileCompression,
   183  			Stat:        wantFileInfo,
   184  		}
   185  
   186  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, response)
   187  		if err != nil {
   188  			cancel()
   189  			t.Fatalf("could not write response: %v", err)
   190  		}
   191  	}
   192  
   193  	clientFunc := func(cancel func(), client *Client) {
   194  		fs := client.FS()
   195  		gotFile, err := fs.Open(context.Background(), path, xrdfs.OpenModeOtherRead, xrdfs.OpenOptionsOpenRead)
   196  		if err != nil {
   197  			t.Fatalf("invalid open call: %v", err)
   198  		}
   199  		// FIXME: consider calling defer gotFile.Close(context.Background()).
   200  
   201  		if !reflect.DeepEqual(gotFile.Handle(), wantFileHandle) {
   202  			t.Errorf("FileSystem.Open()\ngotFile.Handle() = %v\nwantFileHandle = %v", gotFile.Handle(), wantFileHandle)
   203  		}
   204  
   205  		if !reflect.DeepEqual(gotFile.Compression(), wantFileCompression) {
   206  			t.Errorf("FileSystem.Open()\ngotFile.Compression() = %v\nwantFileCompression = %v", gotFile.Compression(), wantFileCompression)
   207  		}
   208  		if !reflect.DeepEqual(gotFile.Info(), wantFileInfo) {
   209  			t.Errorf("FileSystem.Open()\ngotFile.Info() = %v\nwantFileInfo = %v", gotFile.Info(), wantFileInfo)
   210  		}
   211  	}
   212  
   213  	testClientWithMockServer(serverFunc, clientFunc)
   214  }
   215  
   216  func TestFileSystem_Open_Mock(t *testing.T) {
   217  	testCases := []struct {
   218  		name        string
   219  		handle      xrdfs.FileHandle
   220  		compression *xrdfs.FileCompression
   221  		stat        *xrdfs.EntryStat
   222  	}{
   223  		{"WithoutCompressionAndStat", xrdfs.FileHandle{0, 0, 0, 0}, nil, nil},
   224  		{"WithEmptyCompression", xrdfs.FileHandle{0, 0, 0, 0}, &xrdfs.FileCompression{}, nil},
   225  		{"WithCompression", xrdfs.FileHandle{0, 0, 0, 0}, &xrdfs.FileCompression{PageSize: 10, Type: [4]byte{'t', 'e', 's', 't'}}, nil},
   226  		{"WithStat", xrdfs.FileHandle{0, 0, 0, 0}, &xrdfs.FileCompression{}, &xrdfs.EntryStat{HasStatInfo: true, EntrySize: 10}},
   227  	}
   228  
   229  	for i := range testCases {
   230  		tc := testCases[i]
   231  		t.Run(tc.name, func(t *testing.T) {
   232  			t.Parallel()
   233  
   234  			testFileSystem_Open_Mock(t, tc.handle, tc.compression, tc.stat)
   235  		})
   236  	}
   237  }
   238  
   239  func TestFileSystem_RemoveFile_Mock(t *testing.T) {
   240  	t.Parallel()
   241  
   242  	var (
   243  		path        = "/tmp/test"
   244  		wantRequest = rm.Request{Path: path}
   245  	)
   246  
   247  	serverFunc := func(cancel func(), conn net.Conn) {
   248  		data, err := xrdproto.ReadRequest(conn)
   249  		if err != nil {
   250  			cancel()
   251  			t.Fatalf("could not read request: %v", err)
   252  		}
   253  
   254  		var gotRequest rm.Request
   255  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   256  		if err != nil {
   257  			cancel()
   258  			t.Fatalf("could not unmarshal request: %v", err)
   259  		}
   260  
   261  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   262  			cancel()
   263  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   264  		}
   265  
   266  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   267  		if err != nil {
   268  			cancel()
   269  			t.Fatalf("could not write response: %v", err)
   270  		}
   271  	}
   272  
   273  	clientFunc := func(cancel func(), client *Client) {
   274  		fs := fileSystem{client}
   275  		err := fs.RemoveFile(context.Background(), path)
   276  		if err != nil {
   277  			t.Fatalf("invalid rm call: %v", err)
   278  		}
   279  	}
   280  
   281  	testClientWithMockServer(serverFunc, clientFunc)
   282  }
   283  
   284  func TestFileSystem_Truncate_Mock(t *testing.T) {
   285  	t.Parallel()
   286  
   287  	var (
   288  		path              = "/tmp/test"
   289  		wantSize    int64 = 10
   290  		wantRequest       = truncate.Request{Path: path, Size: wantSize}
   291  	)
   292  
   293  	serverFunc := func(cancel func(), conn net.Conn) {
   294  		data, err := xrdproto.ReadRequest(conn)
   295  		if err != nil {
   296  			cancel()
   297  			t.Fatalf("could not read request: %v", err)
   298  		}
   299  
   300  		var gotRequest truncate.Request
   301  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   302  		if err != nil {
   303  			cancel()
   304  			t.Fatalf("could not unmarshal request: %v", err)
   305  		}
   306  
   307  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   308  			cancel()
   309  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   310  		}
   311  
   312  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   313  		if err != nil {
   314  			cancel()
   315  			t.Fatalf("could not write response: %v", err)
   316  		}
   317  	}
   318  
   319  	clientFunc := func(cancel func(), client *Client) {
   320  		fs := fileSystem{client}
   321  		err := fs.Truncate(context.Background(), path, wantSize)
   322  		if err != nil {
   323  			t.Fatalf("invalid truncate call: %v", err)
   324  		}
   325  	}
   326  
   327  	testClientWithMockServer(serverFunc, clientFunc)
   328  }
   329  
   330  func TestFileSystem_Stat_Mock(t *testing.T) {
   331  	t.Parallel()
   332  
   333  	path := "/tmp/test"
   334  
   335  	var want = xrdfs.EntryStat{
   336  		EntrySize:   20,
   337  		Mtime:       10,
   338  		HasStatInfo: true,
   339  	}
   340  
   341  	var wantRequest = stat.Request{Path: path}
   342  
   343  	serverFunc := func(cancel func(), conn net.Conn) {
   344  		data, err := xrdproto.ReadRequest(conn)
   345  		if err != nil {
   346  			cancel()
   347  			t.Fatalf("could not read request: %v", err)
   348  		}
   349  
   350  		var gotRequest stat.Request
   351  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   352  		if err != nil {
   353  			cancel()
   354  			t.Fatalf("could not unmarshal request: %v", err)
   355  		}
   356  
   357  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   358  			cancel()
   359  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   360  		}
   361  
   362  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, stat.DefaultResponse{EntryStat: want})
   363  		if err != nil {
   364  			cancel()
   365  			t.Fatalf("could not write response: %v", err)
   366  		}
   367  	}
   368  
   369  	clientFunc := func(cancel func(), client *Client) {
   370  		fs := client.FS()
   371  		got, err := fs.Stat(context.Background(), path)
   372  		if err != nil {
   373  			t.Fatalf("invalid stat call: %v", err)
   374  		}
   375  		if !reflect.DeepEqual(got, want) {
   376  			t.Fatalf("stat info does not match:\ngot = %v\nwant = %v", got, want)
   377  		}
   378  	}
   379  
   380  	testClientWithMockServer(serverFunc, clientFunc)
   381  }
   382  
   383  func TestFileSystem_VirtualStat_Mock(t *testing.T) {
   384  	t.Parallel()
   385  
   386  	path := "/tmp/test"
   387  
   388  	var want = xrdfs.VirtualFSStat{
   389  		NumberRW:           1,
   390  		FreeRW:             100,
   391  		UtilizationRW:      10,
   392  		NumberStaging:      2,
   393  		FreeStaging:        200,
   394  		UtilizationStaging: 20,
   395  	}
   396  
   397  	var wantRequest = stat.Request{Path: path, Options: stat.OptionsVFS}
   398  
   399  	serverFunc := func(cancel func(), conn net.Conn) {
   400  		data, err := xrdproto.ReadRequest(conn)
   401  		if err != nil {
   402  			cancel()
   403  			t.Fatalf("could not read request: %v", err)
   404  		}
   405  
   406  		var gotRequest stat.Request
   407  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   408  		if err != nil {
   409  			cancel()
   410  			t.Fatalf("could not unmarshal request: %v", err)
   411  		}
   412  
   413  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   414  			cancel()
   415  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   416  		}
   417  
   418  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, stat.VirtualFSResponse{VirtualFSStat: want})
   419  		if err != nil {
   420  			cancel()
   421  			t.Fatalf("could not write response: %v", err)
   422  		}
   423  	}
   424  
   425  	clientFunc := func(cancel func(), client *Client) {
   426  		fs := client.FS()
   427  		got, err := fs.VirtualStat(context.Background(), path)
   428  		if err != nil {
   429  			t.Fatalf("invalid stat call: %v", err)
   430  		}
   431  		if !reflect.DeepEqual(got, want) {
   432  			t.Fatalf("virtual stat info does not match:\ngot = %v\nwant = %v", got, want)
   433  		}
   434  	}
   435  
   436  	testClientWithMockServer(serverFunc, clientFunc)
   437  }
   438  
   439  func TestFileSystem_Mkdir_Mock(t *testing.T) {
   440  	t.Parallel()
   441  
   442  	path := "/tmp/test"
   443  	wantRequest := mkdir.Request{Path: path, Mode: xrdfs.OpenModeOwnerRead | xrdfs.OpenModeOwnerWrite}
   444  
   445  	serverFunc := func(cancel func(), conn net.Conn) {
   446  		data, err := xrdproto.ReadRequest(conn)
   447  		if err != nil {
   448  			cancel()
   449  			t.Fatalf("could not read request: %v", err)
   450  		}
   451  
   452  		var gotRequest mkdir.Request
   453  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   454  		if err != nil {
   455  			cancel()
   456  			t.Fatalf("could not unmarshal request: %v", err)
   457  		}
   458  
   459  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   460  			cancel()
   461  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   462  		}
   463  
   464  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   465  		if err != nil {
   466  			cancel()
   467  			t.Fatalf("could not write response: %v", err)
   468  		}
   469  	}
   470  
   471  	clientFunc := func(cancel func(), client *Client) {
   472  		fs := client.FS()
   473  		err := fs.Mkdir(context.Background(), path, xrdfs.OpenModeOwnerRead|xrdfs.OpenModeOwnerWrite)
   474  		if err != nil {
   475  			t.Fatalf("invalid mkdir call: %v", err)
   476  		}
   477  	}
   478  
   479  	testClientWithMockServer(serverFunc, clientFunc)
   480  }
   481  
   482  func TestFileSystem_MkdirAll_Mock(t *testing.T) {
   483  	t.Parallel()
   484  
   485  	path := "/tmp/test"
   486  	wantRequest := mkdir.Request{
   487  		Path:    path,
   488  		Mode:    xrdfs.OpenModeOwnerRead | xrdfs.OpenModeOwnerWrite,
   489  		Options: mkdir.OptionsMakePath,
   490  	}
   491  
   492  	serverFunc := func(cancel func(), conn net.Conn) {
   493  		data, err := xrdproto.ReadRequest(conn)
   494  		if err != nil {
   495  			cancel()
   496  			t.Fatalf("could not read request: %v", err)
   497  		}
   498  
   499  		var gotRequest mkdir.Request
   500  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   501  		if err != nil {
   502  			cancel()
   503  			t.Fatalf("could not unmarshal request: %v", err)
   504  		}
   505  
   506  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   507  			cancel()
   508  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   509  		}
   510  
   511  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   512  		if err != nil {
   513  			cancel()
   514  			t.Fatalf("could not write response: %v", err)
   515  		}
   516  	}
   517  
   518  	clientFunc := func(cancel func(), client *Client) {
   519  		fs := client.FS()
   520  		err := fs.MkdirAll(context.Background(), path, xrdfs.OpenModeOwnerRead|xrdfs.OpenModeOwnerWrite)
   521  		if err != nil {
   522  			t.Fatalf("invalid mkdir call: %v", err)
   523  		}
   524  	}
   525  
   526  	testClientWithMockServer(serverFunc, clientFunc)
   527  }
   528  
   529  func TestFileSystem_RemoveDir_Mock(t *testing.T) {
   530  	t.Parallel()
   531  
   532  	var (
   533  		path        = "/tmp/test"
   534  		wantRequest = rmdir.Request{Path: path}
   535  	)
   536  
   537  	serverFunc := func(cancel func(), conn net.Conn) {
   538  		data, err := xrdproto.ReadRequest(conn)
   539  		if err != nil {
   540  			cancel()
   541  			t.Fatalf("could not read request: %v", err)
   542  		}
   543  
   544  		var gotRequest rmdir.Request
   545  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   546  		if err != nil {
   547  			cancel()
   548  			t.Fatalf("could not unmarshal request: %v", err)
   549  		}
   550  
   551  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   552  			cancel()
   553  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   554  		}
   555  
   556  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   557  		if err != nil {
   558  			cancel()
   559  			t.Fatalf("could not write response: %v", err)
   560  		}
   561  	}
   562  
   563  	clientFunc := func(cancel func(), client *Client) {
   564  		fs := fileSystem{client}
   565  		err := fs.RemoveDir(context.Background(), path)
   566  		if err != nil {
   567  			t.Fatalf("invalid rmdir call: %v", err)
   568  		}
   569  	}
   570  
   571  	testClientWithMockServer(serverFunc, clientFunc)
   572  }
   573  
   574  func TestFileSystem_Rename_Mock(t *testing.T) {
   575  	t.Parallel()
   576  
   577  	var (
   578  		oldpath     = "/tmp/test1"
   579  		newpath     = "/tmp/test2"
   580  		wantRequest = mv.Request{OldPath: oldpath, NewPath: newpath}
   581  	)
   582  
   583  	serverFunc := func(cancel func(), conn net.Conn) {
   584  		data, err := xrdproto.ReadRequest(conn)
   585  		if err != nil {
   586  			cancel()
   587  			t.Fatalf("could not read request: %v", err)
   588  		}
   589  
   590  		var gotRequest mv.Request
   591  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   592  		if err != nil {
   593  			cancel()
   594  			t.Fatalf("could not unmarshal request: %v", err)
   595  		}
   596  
   597  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   598  			cancel()
   599  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   600  		}
   601  
   602  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   603  		if err != nil {
   604  			cancel()
   605  			t.Fatalf("could not write response: %v", err)
   606  		}
   607  	}
   608  
   609  	clientFunc := func(cancel func(), client *Client) {
   610  		fs := fileSystem{client}
   611  		err := fs.Rename(context.Background(), oldpath, newpath)
   612  		if err != nil {
   613  			t.Fatalf("invalid mv call: %v", err)
   614  		}
   615  	}
   616  
   617  	testClientWithMockServer(serverFunc, clientFunc)
   618  }
   619  
   620  func TestFileSystem_Chmod_Mock(t *testing.T) {
   621  	t.Parallel()
   622  
   623  	var (
   624  		path        = "/tmp/test2"
   625  		perm        = xrdfs.OpenModeOwnerRead | xrdfs.OpenModeOwnerWrite
   626  		wantRequest = chmod.Request{Path: path, Mode: perm}
   627  	)
   628  
   629  	serverFunc := func(cancel func(), conn net.Conn) {
   630  		data, err := xrdproto.ReadRequest(conn)
   631  		if err != nil {
   632  			cancel()
   633  			t.Fatalf("could not read request: %v", err)
   634  		}
   635  
   636  		var gotRequest chmod.Request
   637  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   638  		if err != nil {
   639  			cancel()
   640  			t.Fatalf("could not unmarshal request: %v", err)
   641  		}
   642  
   643  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   644  			cancel()
   645  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   646  		}
   647  
   648  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, nil)
   649  		if err != nil {
   650  			cancel()
   651  			t.Fatalf("could not write response: %v", err)
   652  		}
   653  	}
   654  
   655  	clientFunc := func(cancel func(), client *Client) {
   656  		fs := fileSystem{client}
   657  		err := fs.Chmod(context.Background(), path, perm)
   658  		if err != nil {
   659  			t.Fatalf("invalid chmod call: %v", err)
   660  		}
   661  	}
   662  
   663  	testClientWithMockServer(serverFunc, clientFunc)
   664  }
   665  
   666  func TestFileSystem_Statx_Mock(t *testing.T) {
   667  	paths := []string{"/tmp/test", "/tmp/test2"}
   668  	want := []xrdfs.StatFlags{xrdfs.StatIsDir, xrdfs.StatIsOffline}
   669  	wantRequest := statx.Request{Paths: "/tmp/test\n/tmp/test2"}
   670  
   671  	serverFunc := func(cancel func(), conn net.Conn) {
   672  		data, err := xrdproto.ReadRequest(conn)
   673  		if err != nil {
   674  			cancel()
   675  			t.Fatalf("could not read request: %v", err)
   676  		}
   677  
   678  		var gotRequest statx.Request
   679  		gotHeader, err := unmarshalRequest(data, &gotRequest)
   680  		if err != nil {
   681  			cancel()
   682  			t.Fatalf("could not unmarshal request: %v", err)
   683  		}
   684  
   685  		if !reflect.DeepEqual(gotRequest, wantRequest) {
   686  			cancel()
   687  			t.Fatalf("request info does not match:\ngot = %v\nwant = %v", gotRequest, wantRequest)
   688  		}
   689  
   690  		err = xrdproto.WriteResponse(conn, gotHeader.StreamID, xrdproto.Ok, statx.Response{StatFlags: want})
   691  		if err != nil {
   692  			cancel()
   693  			t.Fatalf("could not write response: %v", err)
   694  		}
   695  	}
   696  
   697  	clientFunc := func(cancel func(), client *Client) {
   698  		fs := client.FS()
   699  		got, err := fs.Statx(context.Background(), paths)
   700  		if err != nil {
   701  			t.Fatalf("invalid statx call: %v", err)
   702  		}
   703  		if !reflect.DeepEqual(got, want) {
   704  			t.Fatalf("statx info does not match:\ngot = %v\nwant = %v", got, want)
   705  		}
   706  	}
   707  
   708  	testClientWithMockServer(serverFunc, clientFunc)
   709  }