github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libfuse/mount_test.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  //
     5  //go:build !windows
     6  // +build !windows
     7  
     8  package libfuse
     9  
    10  import (
    11  	"bytes"
    12  	"encoding/json"
    13  	"fmt"
    14  	"io"
    15  	"os"
    16  	"os/exec"
    17  	"path"
    18  	"reflect"
    19  	"runtime"
    20  	"strconv"
    21  	"strings"
    22  	"syscall"
    23  	"testing"
    24  	"time"
    25  
    26  	"bazil.org/fuse"
    27  	"bazil.org/fuse/fs"
    28  	"bazil.org/fuse/fs/fstestutil"
    29  	"github.com/keybase/client/go/kbfs/ioutil"
    30  	"github.com/keybase/client/go/kbfs/libcontext"
    31  	"github.com/keybase/client/go/kbfs/libfs"
    32  	"github.com/keybase/client/go/kbfs/libkbfs"
    33  	"github.com/keybase/client/go/kbfs/test/clocktest"
    34  	"github.com/keybase/client/go/kbfs/tlf"
    35  	kbname "github.com/keybase/client/go/kbun"
    36  	"github.com/keybase/client/go/logger"
    37  	"github.com/keybase/client/go/protocol/keybase1"
    38  	"github.com/pkg/errors"
    39  	"github.com/stretchr/testify/require"
    40  	"golang.org/x/net/context"
    41  	"golang.org/x/sys/unix"
    42  )
    43  
    44  func makeFS(ctx context.Context, t testing.TB, config *libkbfs.ConfigLocal) (
    45  	*fstestutil.Mount, *FS, func()) {
    46  	log := logger.NewTestLogger(t)
    47  	debugLog := log.CloneWithAddedDepth(1)
    48  	fuse.Debug = MakeFuseDebugFn(debugLog, false /* superVerbose */)
    49  
    50  	// TODO duplicates main() in kbfsfuse/main.go too much
    51  	filesys := &FS{
    52  		config:        config,
    53  		log:           log,
    54  		vlog:          config.MakeVLogger(log),
    55  		errLog:        log,
    56  		errVlog:       config.MakeVLogger(log),
    57  		notifications: libfs.NewFSNotifications(log),
    58  		root:          NewRoot(),
    59  	}
    60  	filesys.root.private = &FolderList{
    61  		fs:      filesys,
    62  		tlfType: tlf.Private,
    63  		folders: make(map[string]*TLF),
    64  	}
    65  	filesys.root.public = &FolderList{
    66  		fs:      filesys,
    67  		tlfType: tlf.Public,
    68  		folders: make(map[string]*TLF),
    69  	}
    70  	filesys.root.team = &FolderList{
    71  		fs:      filesys,
    72  		tlfType: tlf.SingleTeam,
    73  		folders: make(map[string]*TLF),
    74  	}
    75  	filesys.execAfterDelay = func(d time.Duration, f func()) {
    76  		time.AfterFunc(d, f)
    77  	}
    78  	fn := func(mnt *fstestutil.Mount) fs.FS {
    79  		filesys.fuse = mnt.Server
    80  		filesys.conn = mnt.Conn
    81  		return filesys
    82  	}
    83  	options := GetPlatformSpecificMountOptionsForTest()
    84  	mnt, err := fstestutil.MountedFuncT(t, fn, &fs.Config{
    85  		WithContext: func(ctx context.Context, req fuse.Request) context.Context {
    86  			return filesys.WithContext(ctx)
    87  		},
    88  	}, options...)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	// the cancelFn returned will cancel notification processing; the
    93  	// FUSE serve loop is terminated by unmounting the filesystem
    94  	ctx = context.WithValue(ctx, libfs.CtxAppIDKey, filesys)
    95  	ctx, cancelFn := context.WithCancel(ctx)
    96  	filesys.LaunchNotificationProcessor(ctx)
    97  	return mnt, filesys, func() {
    98  		cancelFn()
    99  	}
   100  }
   101  
   102  type fileInfoCheck func(fi os.FileInfo) error
   103  
   104  func mustBeFileWithSize(fi os.FileInfo, size int64) error {
   105  	if fi.Size() != size {
   106  		return fmt.Errorf("Bad file size: %d", fi.Size())
   107  	}
   108  	return nil
   109  }
   110  
   111  func mustBeDir(fi os.FileInfo) error {
   112  	if !fi.IsDir() {
   113  		return fmt.Errorf("not a directory: %v", fi)
   114  	}
   115  	return nil
   116  }
   117  
   118  func checkDirNoTestError(
   119  	t testing.TB, dir string, want map[string]fileInfoCheck) error {
   120  	// make a copy of want, to be safe
   121  	{
   122  		tmp := make(map[string]fileInfoCheck, len(want))
   123  		for k, v := range want {
   124  			tmp[k] = v
   125  		}
   126  		want = tmp
   127  	}
   128  
   129  	fis, err := ioutil.ReadDir(dir)
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	for _, fi := range fis {
   134  		if check, ok := want[fi.Name()]; ok {
   135  			delete(want, fi.Name())
   136  			if check != nil {
   137  				if err := check(fi); err != nil {
   138  					return fmt.Errorf("check failed: %v: %v", fi.Name(), err)
   139  				}
   140  			}
   141  			continue
   142  		}
   143  		return fmt.Errorf("unexpected direntry: %q size=%v mode=%v",
   144  			fi.Name(), fi.Size(), fi.Mode())
   145  	}
   146  	for filename := range want {
   147  		return fmt.Errorf("never saw file: %v", filename)
   148  	}
   149  	return nil
   150  }
   151  
   152  func checkDir(t testing.TB, dir string, want map[string]fileInfoCheck) {
   153  	err := checkDirNoTestError(t, dir, want)
   154  	if err != nil {
   155  		t.Error(err)
   156  	}
   157  }
   158  
   159  // timeEqualFuzzy returns whether a is b+-skew.
   160  func timeEqualFuzzy(a, b time.Time, skew time.Duration) bool {
   161  	b1 := b.Add(-skew)
   162  	b2 := b.Add(skew)
   163  	return !a.Before(b1) && !a.After(b2)
   164  }
   165  
   166  func testCleanupDelayer(ctx context.Context, t *testing.T) {
   167  	err := libcontext.CleanupCancellationDelayer(ctx)
   168  	require.NoError(t, err)
   169  }
   170  
   171  func TestStatRoot(t *testing.T) {
   172  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   173  	defer testCleanupDelayer(ctx, t)
   174  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   175  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   176  	mnt, _, cancelFn := makeFS(ctx, t, config)
   177  	defer mnt.Close()
   178  	defer cancelFn()
   179  
   180  	fi, err := ioutil.Lstat(mnt.Dir)
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  	if g, e := fi.Mode().String(), `dr-x------`; g != e {
   185  		t.Errorf("wrong mode for folder: %q != %q", g, e)
   186  	}
   187  }
   188  
   189  func TestStatPrivate(t *testing.T) {
   190  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   191  	defer testCleanupDelayer(ctx, t)
   192  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   193  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   194  	mnt, _, cancelFn := makeFS(ctx, t, config)
   195  	defer mnt.Close()
   196  	defer cancelFn()
   197  
   198  	fi, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName))
   199  	if err != nil {
   200  		t.Fatal(err)
   201  	}
   202  	if g, e := fi.Mode().String(), `dr-x------`; g != e {
   203  		t.Errorf("wrong mode for folder: %q != %q", g, e)
   204  	}
   205  }
   206  
   207  func TestStatPublic(t *testing.T) {
   208  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   209  	defer testCleanupDelayer(ctx, t)
   210  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   211  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   212  	mnt, _, cancelFn := makeFS(ctx, t, config)
   213  	defer mnt.Close()
   214  	defer cancelFn()
   215  
   216  	fi, err := ioutil.Lstat(path.Join(mnt.Dir, PublicName))
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if g, e := fi.Mode().String(), `dr-x------`; g != e {
   221  		t.Errorf("wrong mode for folder: %q != %q", g, e)
   222  	}
   223  }
   224  
   225  func TestStatMyFolder(t *testing.T) {
   226  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   227  	defer testCleanupDelayer(ctx, t)
   228  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   229  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   230  	mnt, _, cancelFn := makeFS(ctx, t, config)
   231  	defer mnt.Close()
   232  	defer cancelFn()
   233  
   234  	// Access the tlf once to have the *Dir populated in tlf.go
   235  	if err := ioutil.Mkdir(
   236  		path.Join(mnt.Dir, PrivateName, "jdoe", "d"), os.ModeDir); err != nil {
   237  		t.Fatal(err)
   238  	}
   239  
   240  	fi, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName, "jdoe"))
   241  	if err != nil {
   242  		t.Fatal(err)
   243  	}
   244  	if g, e := fi.Mode().String(), `drwx------`; g != e {
   245  		t.Errorf("wrong mode for folder: %q != %q", g, e)
   246  	}
   247  }
   248  
   249  func TestStatNonexistentFolder(t *testing.T) {
   250  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   251  	defer testCleanupDelayer(ctx, t)
   252  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   253  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   254  	mnt, _, cancelFn := makeFS(ctx, t, config)
   255  	defer mnt.Close()
   256  	defer cancelFn()
   257  
   258  	if _, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName, "does-not-exist")); !ioutil.IsNotExist(err) {
   259  		t.Fatalf("expected ENOENT: %v", err)
   260  	}
   261  }
   262  
   263  func TestStatAlias(t *testing.T) {
   264  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   265  	defer testCleanupDelayer(ctx, t)
   266  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   267  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   268  	mnt, _, cancelFn := makeFS(ctx, t, config)
   269  	defer mnt.Close()
   270  	defer cancelFn()
   271  
   272  	p := path.Join(mnt.Dir, PrivateName, "jdoe,jdoe")
   273  	fi, err := ioutil.Lstat(p)
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  	if g, e := fi.Mode().String(), `Lrwxrwxrwx`; g != e {
   278  		t.Errorf("wrong mode for alias : %q != %q", g, e)
   279  	}
   280  	target, err := os.Readlink(p)
   281  	if err != nil {
   282  		t.Fatal(err)
   283  	}
   284  	if g, e := target, "jdoe"; g != e {
   285  		t.Errorf("wrong alias symlink target: %q != %q", g, e)
   286  	}
   287  }
   288  
   289  // Test that we can determine a normalized alias without any identify
   290  // calls (regression test for KBFS-531).
   291  func TestStatAliasCausesNoIdentifies(t *testing.T) {
   292  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   293  	defer testCleanupDelayer(ctx, t)
   294  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   295  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   296  
   297  	mnt, _, cancelFn := makeFS(ctx, t, config)
   298  	defer mnt.Close()
   299  	defer cancelFn()
   300  
   301  	p := path.Join(mnt.Dir, PublicName, "HEAD")
   302  	// Even though "head" is not a real user in our config, this stat
   303  	// should succeed because no identify calls should be triggered.
   304  	fi, err := ioutil.Lstat(p)
   305  	if err != nil {
   306  		t.Fatal(err)
   307  	}
   308  	if g, e := fi.Mode().String(), `Lrwxrwxrwx`; g != e {
   309  		t.Errorf("wrong mode for alias : %q != %q", g, e)
   310  	}
   311  	target, err := os.Readlink(p)
   312  	if err != nil {
   313  		t.Fatal(err)
   314  	}
   315  	if g, e := target, "head"; g != e {
   316  		t.Errorf("wrong alias symlink target: %q != %q", g, e)
   317  	}
   318  }
   319  
   320  func TestStatInvalidAliasFails(t *testing.T) {
   321  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   322  	defer testCleanupDelayer(ctx, t)
   323  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   324  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   325  
   326  	mnt, _, cancelFn := makeFS(ctx, t, config)
   327  	defer mnt.Close()
   328  	defer cancelFn()
   329  
   330  	p := path.Join(mnt.Dir, PublicName, "HEAD.JPG")
   331  	// This should fail as HEAD.JPG has the wrong format.
   332  	_, err := ioutil.Lstat(p)
   333  	if err == nil {
   334  		t.Fatal("Lstat of HEAD.JPG didn't return an error!")
   335  	}
   336  }
   337  
   338  func TestRemoveAlias(t *testing.T) {
   339  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   340  	defer testCleanupDelayer(ctx, t)
   341  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   342  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   343  	mnt, _, cancelFn := makeFS(ctx, t, config)
   344  	defer mnt.Close()
   345  	defer cancelFn()
   346  
   347  	p := path.Join(mnt.Dir, PrivateName, "jdoe,jdoe")
   348  	err := ioutil.Remove(p)
   349  	if err != nil {
   350  		t.Fatalf("Removing alias failed: %v", err)
   351  	}
   352  }
   353  
   354  func TestStatMyPublic(t *testing.T) {
   355  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   356  	defer testCleanupDelayer(ctx, t)
   357  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   358  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   359  	mnt, _, cancelFn := makeFS(ctx, t, config)
   360  	defer mnt.Close()
   361  	defer cancelFn()
   362  
   363  	// Access the tlf once to have the *Dir populated in tlf.go
   364  	if err := ioutil.Mkdir(
   365  		path.Join(mnt.Dir, PublicName, "jdoe", "d"), os.ModeDir); err != nil {
   366  		t.Fatal(err)
   367  	}
   368  
   369  	fi, err := ioutil.Lstat(path.Join(mnt.Dir, PublicName, "jdoe"))
   370  	if err != nil {
   371  		t.Fatal(err)
   372  	}
   373  	if g, e := fi.Mode().String(), `drwx------`; g != e {
   374  		t.Errorf("wrong mode for folder: %q != %q", g, e)
   375  	}
   376  }
   377  
   378  func TestReaddirRoot(t *testing.T) {
   379  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   380  	defer testCleanupDelayer(ctx, t)
   381  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   382  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   383  	mnt, _, cancelFn := makeFS(ctx, t, config)
   384  	defer mnt.Close()
   385  	defer cancelFn()
   386  
   387  	checkDir(t, mnt.Dir, map[string]fileInfoCheck{
   388  		PrivateName: mustBeDir,
   389  		PublicName:  mustBeDir,
   390  		TeamName:    mustBeDir,
   391  	})
   392  }
   393  
   394  func TestReaddirPrivate(t *testing.T) {
   395  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   396  	defer testCleanupDelayer(ctx, t)
   397  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "janedoe")
   398  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   399  	mnt, _, cancelFn := makeFS(ctx, t, config)
   400  	defer mnt.Close()
   401  	defer cancelFn()
   402  
   403  	{
   404  		ctx := libcontext.BackgroundContextWithCancellationDelayer()
   405  		defer testCleanupDelayer(ctx, t)
   406  		// Force FakeMDServer to have some TlfIDs it can present to us
   407  		// as favorites. Don't go through VFS to avoid caching causing
   408  		// false positives.
   409  		libkbfs.GetRootNodeOrBust(ctx, t, config, "janedoe,jdoe", tlf.Private)
   410  		libkbfs.GetRootNodeOrBust(ctx, t, config, "janedoe,jdoe", tlf.Public)
   411  	}
   412  
   413  	checkDir(t, path.Join(mnt.Dir, PrivateName), map[string]fileInfoCheck{
   414  		"jdoe,janedoe": mustBeDir,
   415  		"jdoe":         mustBeDir, // default home directory
   416  	})
   417  }
   418  
   419  func TestReaddirPrivateDeleteAndReaddFavorite(t *testing.T) {
   420  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   421  	defer testCleanupDelayer(ctx, t)
   422  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "janedoe")
   423  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   424  	mnt, fs, cancelFn := makeFS(ctx, t, config)
   425  	fs.execAfterDelay = func(d time.Duration, f func()) {
   426  		// this causes the entry added to fl.recentlyRemoved (in
   427  		// addToRecentlyRemove) to be removed instantly. this way we can avoid
   428  		// adding delays in tests.
   429  		f()
   430  	}
   431  	defer mnt.Close()
   432  	defer cancelFn()
   433  
   434  	{
   435  		ctx := libcontext.BackgroundContextWithCancellationDelayer()
   436  		defer testCleanupDelayer(ctx, t)
   437  		// Force FakeMDServer to have some TlfIDs it can present to us
   438  		// as favorites. Don't go through VFS to avoid caching causing
   439  		// false positives.
   440  		libkbfs.GetRootNodeOrBust(ctx, t, config, "janedoe,jdoe", tlf.Private)
   441  		libkbfs.GetRootNodeOrBust(ctx, t, config, "janedoe,jdoe", tlf.Public)
   442  	}
   443  
   444  	err := ioutil.Remove(path.Join(mnt.Dir, PrivateName, "jdoe,janedoe"))
   445  	if err != nil {
   446  		t.Fatalf("Removing favorite failed: %v", err)
   447  	}
   448  
   449  	checkDir(t, path.Join(mnt.Dir, PrivateName), map[string]fileInfoCheck{
   450  		"jdoe": mustBeDir, // default home directory
   451  	})
   452  
   453  	// Re-add the favorite by doing a readdir
   454  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe,janedoe"),
   455  		map[string]fileInfoCheck{})
   456  
   457  	checkDir(t, path.Join(mnt.Dir, PrivateName), map[string]fileInfoCheck{
   458  		"jdoe,janedoe": mustBeDir,
   459  		"jdoe":         mustBeDir, // default home directory
   460  	})
   461  }
   462  
   463  func TestReaddirPublic(t *testing.T) {
   464  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   465  	defer testCleanupDelayer(ctx, t)
   466  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "janedoe")
   467  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   468  	mnt, _, cancelFn := makeFS(ctx, t, config)
   469  	defer mnt.Close()
   470  	defer cancelFn()
   471  
   472  	{
   473  		ctx := libcontext.BackgroundContextWithCancellationDelayer()
   474  		defer testCleanupDelayer(ctx, t)
   475  		// Force FakeMDServer to have some TlfIDs it can present to us
   476  		// as favorites. Don't go through VFS to avoid caching causing
   477  		// false positives.
   478  		libkbfs.GetRootNodeOrBust(ctx, t, config, "janedoe,jdoe", tlf.Private)
   479  		libkbfs.GetRootNodeOrBust(ctx, t, config, "janedoe,jdoe", tlf.Public)
   480  	}
   481  
   482  	checkDir(t, path.Join(mnt.Dir, PublicName), map[string]fileInfoCheck{
   483  		"jdoe,janedoe": mustBeDir,
   484  		"jdoe":         mustBeDir, // default personal public directory
   485  	})
   486  }
   487  
   488  type kbserviceBrokenIdentify struct {
   489  	libkbfs.KeybaseService
   490  }
   491  
   492  func (k kbserviceBrokenIdentify) Identify(
   493  	ctx context.Context, assertion, reason string,
   494  	_ keybase1.OfflineAvailability) (
   495  	kbname.NormalizedUsername, keybase1.UserOrTeamID, error) {
   496  	return kbname.NormalizedUsername(""), keybase1.UserOrTeamID(""),
   497  		errors.New("Fake identify error")
   498  }
   499  
   500  // Regression test for KBFS-772 on OSX.  (There's a bug where ls only
   501  // respects errors from Open, not from ReadDirAll.)
   502  func TestReaddirPublicFailedIdentifyViaOSCall(t *testing.T) {
   503  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   504  	defer testCleanupDelayer(ctx, t)
   505  	config1 := libkbfs.MakeTestConfigOrBust(t, "u1", "u2")
   506  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
   507  	mnt1, _, cancelFn1 := makeFS(ctx, t, config1)
   508  	defer mnt1.Close()
   509  	defer cancelFn1()
   510  
   511  	config2 := libkbfs.ConfigAsUser(config1, "u2")
   512  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
   513  	mnt2, _, cancelFn2 := makeFS(ctx, t, config2)
   514  	defer mnt2.Close()
   515  	defer cancelFn2()
   516  
   517  	// Create a shared folder via u2.
   518  	p := path.Join(mnt2.Dir, PrivateName, "u1,u2", "mydir")
   519  	if err := ioutil.Mkdir(p, 0755); err != nil {
   520  		t.Fatal(err)
   521  	}
   522  
   523  	// Make u1 get failures for every identify call.
   524  	config1.SetKeybaseService(kbserviceBrokenIdentify{
   525  		KeybaseService: config1.KeybaseService(),
   526  	})
   527  
   528  	// A private non-existing home folder, with write permissions, fails.
   529  	err := exec.Command("ls", path.Join(mnt1.Dir, PublicName, "u1")).Run()
   530  	if _, ok := err.(*exec.ExitError); !ok {
   531  		t.Fatalf("No error as expected on broken user identify: %v", err)
   532  	}
   533  
   534  	// A private existing shared folder, with write permissions, fails.
   535  	err = exec.Command("ls", path.Join(mnt1.Dir, PrivateName, "u1,u2")).Run()
   536  	if _, ok := err.(*exec.ExitError); !ok {
   537  		t.Fatalf("No error as expected on broken user identify: %v", err)
   538  	}
   539  
   540  	// A public, non-existing folder, without write permissions, fails.
   541  	err = exec.Command("ls", path.Join(mnt1.Dir, PublicName, "u2")).Run()
   542  	if _, ok := err.(*exec.ExitError); !ok {
   543  		t.Fatalf("No error as expected on broken user identify: %v", err)
   544  	}
   545  }
   546  
   547  func TestReaddirMyFolderEmpty(t *testing.T) {
   548  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   549  	defer testCleanupDelayer(ctx, t)
   550  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   551  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   552  	mnt, _, cancelFn := makeFS(ctx, t, config)
   553  	defer mnt.Close()
   554  	defer cancelFn()
   555  
   556  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{})
   557  }
   558  
   559  func syncAll(t *testing.T, tlf string, ty tlf.Type, fs *FS) {
   560  	// golang doesn't let us sync on a directory handle, so if we need
   561  	// to sync all without a file, go through libkbfs directly.
   562  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   563  	defer testCleanupDelayer(ctx, t)
   564  	root := libkbfs.GetRootNodeOrBust(ctx, t, fs.config, tlf, ty)
   565  	err := fs.config.KBFSOps().SyncAll(ctx, root.GetFolderBranch())
   566  	if err != nil {
   567  		t.Fatalf("Couldn't sync all: %v", err)
   568  	}
   569  }
   570  
   571  func syncAndClose(t *testing.T, f *os.File) {
   572  	if f == nil {
   573  		return
   574  	}
   575  	err := f.Sync()
   576  	if err != nil {
   577  		t.Fatal(err)
   578  	}
   579  	f.Close()
   580  }
   581  
   582  func syncFilename(t *testing.T, name string) {
   583  	f, err := os.OpenFile(name, os.O_WRONLY, 0644)
   584  	if err != nil {
   585  		t.Fatal(err)
   586  	}
   587  	syncAndClose(t, f)
   588  }
   589  
   590  func TestReaddirMyFolderWithFiles(t *testing.T) {
   591  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   592  	defer testCleanupDelayer(ctx, t)
   593  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   594  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   595  	mnt, _, cancelFn := makeFS(ctx, t, config)
   596  	defer mnt.Close()
   597  	defer cancelFn()
   598  
   599  	files := map[string]fileInfoCheck{
   600  		"one": nil,
   601  		"two": nil,
   602  	}
   603  	for filename, check := range files {
   604  		if check != nil {
   605  			// only set up the files
   606  			continue
   607  		}
   608  		p := path.Join(mnt.Dir, PrivateName, "jdoe", filename)
   609  		if err := ioutil.WriteFile(
   610  			p, []byte("data for "+filename), 0644); err != nil {
   611  			t.Fatal(err)
   612  		}
   613  		syncFilename(t, p)
   614  	}
   615  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), files)
   616  }
   617  
   618  func testOneCreateThenRead(t *testing.T, p string) {
   619  	f, err := os.Create(p)
   620  	if err != nil {
   621  		t.Fatal(err)
   622  	}
   623  	// Call in a closure since `f` is overridden below.
   624  	defer func() { syncAndClose(t, f) }()
   625  	const input = "hello, world\n"
   626  	if _, err := io.WriteString(f, input); err != nil {
   627  		t.Fatalf("write error: %v", err)
   628  	}
   629  	syncAndClose(t, f)
   630  	f = nil
   631  
   632  	buf, err := ioutil.ReadFile(p)
   633  	if err != nil {
   634  		t.Fatalf("read error: %v", err)
   635  	}
   636  	if g, e := string(buf), input; g != e {
   637  		t.Errorf("bad file contents: %q != %q", g, e)
   638  	}
   639  }
   640  
   641  func TestCreateThenRead(t *testing.T) {
   642  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   643  	defer testCleanupDelayer(ctx, t)
   644  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   645  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   646  	mnt, _, cancelFn := makeFS(ctx, t, config)
   647  	defer mnt.Close()
   648  	defer cancelFn()
   649  
   650  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
   651  	testOneCreateThenRead(t, p)
   652  }
   653  
   654  // Tests that writing and reading multiple files works, implicitly
   655  // exercising any block pointer reference counting code (since the
   656  // initial created files will have identical empty blocks to start
   657  // with).
   658  func TestMultipleCreateThenRead(t *testing.T) {
   659  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   660  	defer testCleanupDelayer(ctx, t)
   661  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   662  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   663  	mnt, _, cancelFn := makeFS(ctx, t, config)
   664  	defer mnt.Close()
   665  	defer cancelFn()
   666  
   667  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile1")
   668  	testOneCreateThenRead(t, p1)
   669  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile2")
   670  	testOneCreateThenRead(t, p2)
   671  }
   672  
   673  func TestReadUnflushed(t *testing.T) {
   674  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   675  	defer testCleanupDelayer(ctx, t)
   676  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   677  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   678  	mnt, _, cancelFn := makeFS(ctx, t, config)
   679  	defer mnt.Close()
   680  	defer cancelFn()
   681  
   682  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
   683  	f, err := os.Create(p)
   684  	if err != nil {
   685  		t.Fatal(err)
   686  	}
   687  	defer syncAndClose(t, f)
   688  	const input = "hello, world\n"
   689  	if _, err := io.WriteString(f, input); err != nil {
   690  		t.Fatalf("write error: %v", err)
   691  	}
   692  	// explicitly no close here
   693  
   694  	buf, err := ioutil.ReadFile(p)
   695  	if err != nil {
   696  		t.Fatalf("read error: %v", err)
   697  	}
   698  	if g, e := string(buf), input; g != e {
   699  		t.Errorf("bad file contents: %q != %q", g, e)
   700  	}
   701  }
   702  
   703  func TestMountAgain(t *testing.T) {
   704  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   705  	defer testCleanupDelayer(ctx, t)
   706  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   707  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   708  
   709  	const input = "hello, world\n"
   710  	const filename = "myfile"
   711  	func() {
   712  		mnt, _, cancelFn := makeFS(ctx, t, config)
   713  		defer mnt.Close()
   714  		defer cancelFn()
   715  
   716  		p := path.Join(mnt.Dir, PrivateName, "jdoe", filename)
   717  		if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
   718  			t.Fatal(err)
   719  		}
   720  		syncFilename(t, p)
   721  	}()
   722  
   723  	func() {
   724  		mnt, _, cancelFn := makeFS(ctx, t, config)
   725  		defer mnt.Close()
   726  		defer cancelFn()
   727  		p := path.Join(mnt.Dir, PrivateName, "jdoe", filename)
   728  		buf, err := ioutil.ReadFile(p)
   729  		if err != nil {
   730  			t.Fatalf("read error: %v", err)
   731  		}
   732  		if g, e := string(buf), input; g != e {
   733  			t.Errorf("bad file contents: %q != %q", g, e)
   734  		}
   735  	}()
   736  }
   737  
   738  func TestCreateExecutable(t *testing.T) {
   739  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   740  	defer testCleanupDelayer(ctx, t)
   741  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   742  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   743  	mnt, _, cancelFn := makeFS(ctx, t, config)
   744  	defer mnt.Close()
   745  	defer cancelFn()
   746  
   747  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
   748  	if err := ioutil.WriteFile(p, []byte("fake binary"), 0755); err != nil {
   749  		t.Fatal(err)
   750  	}
   751  	syncFilename(t, p)
   752  	fi, err := ioutil.Lstat(p)
   753  	if err != nil {
   754  		t.Fatal(err)
   755  	}
   756  	if g, e := fi.Mode().String(), `-rwx------`; g != e {
   757  		t.Errorf("wrong mode for executable: %q != %q", g, e)
   758  	}
   759  }
   760  
   761  func TestMkdir(t *testing.T) {
   762  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   763  	defer testCleanupDelayer(ctx, t)
   764  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   765  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   766  	mnt, _, cancelFn := makeFS(ctx, t, config)
   767  	defer mnt.Close()
   768  	defer cancelFn()
   769  
   770  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
   771  	if err := ioutil.Mkdir(p, 0755); err != nil {
   772  		t.Fatal(err)
   773  	}
   774  	fi, err := ioutil.Lstat(p)
   775  	if err != nil {
   776  		t.Fatal(err)
   777  	}
   778  	if g, e := fi.Mode().String(), `drwx------`; g != e {
   779  		t.Errorf("wrong mode for subdir: %q != %q", g, e)
   780  	}
   781  }
   782  
   783  func TestMkdirAndCreateDeep(t *testing.T) {
   784  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   785  	defer testCleanupDelayer(ctx, t)
   786  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   787  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   788  	const input = "hello, world\n"
   789  
   790  	func() {
   791  		mnt, _, cancelFn := makeFS(ctx, t, config)
   792  		defer mnt.Close()
   793  		defer cancelFn()
   794  
   795  		one := path.Join(mnt.Dir, PrivateName, "jdoe", "one")
   796  		if err := ioutil.Mkdir(one, 0755); err != nil {
   797  			t.Fatal(err)
   798  		}
   799  		two := path.Join(one, "two")
   800  		if err := ioutil.Mkdir(two, 0755); err != nil {
   801  			t.Fatal(err)
   802  		}
   803  		three := path.Join(two, "three")
   804  		if err := ioutil.WriteFile(three, []byte(input), 0644); err != nil {
   805  			t.Fatal(err)
   806  		}
   807  		syncFilename(t, three)
   808  	}()
   809  
   810  	// unmount to flush cache
   811  	func() {
   812  		mnt, _, cancelFn := makeFS(ctx, t, config)
   813  		defer mnt.Close()
   814  		defer cancelFn()
   815  
   816  		p := path.Join(mnt.Dir, PrivateName, "jdoe", "one", "two", "three")
   817  		buf, err := ioutil.ReadFile(p)
   818  		if err != nil {
   819  			t.Fatalf("read error: %v", err)
   820  		}
   821  		if g, e := string(buf), input; g != e {
   822  			t.Errorf("bad file contents: %q != %q", g, e)
   823  		}
   824  	}()
   825  }
   826  
   827  func TestSymlink(t *testing.T) {
   828  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   829  	defer testCleanupDelayer(ctx, t)
   830  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   831  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   832  
   833  	func() {
   834  		mnt, _, cancelFn := makeFS(ctx, t, config)
   835  		defer mnt.Close()
   836  		defer cancelFn()
   837  
   838  		p := path.Join(mnt.Dir, PrivateName, "jdoe", "mylink")
   839  		if err := os.Symlink("myfile", p); err != nil {
   840  			t.Fatal(err)
   841  		}
   842  	}()
   843  
   844  	// unmount to flush cache
   845  	func() {
   846  		mnt, _, cancelFn := makeFS(ctx, t, config)
   847  		defer mnt.Close()
   848  		defer cancelFn()
   849  
   850  		p := path.Join(mnt.Dir, PrivateName, "jdoe", "mylink")
   851  		target, err := os.Readlink(p)
   852  		if err != nil {
   853  			t.Fatal(err)
   854  		}
   855  		if g, e := target, "myfile"; g != e {
   856  			t.Errorf("bad symlink target: %q != %q", g, e)
   857  		}
   858  	}()
   859  }
   860  
   861  func TestRename(t *testing.T) {
   862  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   863  	defer testCleanupDelayer(ctx, t)
   864  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   865  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   866  	mnt, _, cancelFn := makeFS(ctx, t, config)
   867  	defer mnt.Close()
   868  	defer cancelFn()
   869  
   870  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "old")
   871  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "new")
   872  	const input = "hello, world\n"
   873  	if err := ioutil.WriteFile(p1, []byte(input), 0644); err != nil {
   874  		t.Fatal(err)
   875  	}
   876  	syncFilename(t, p1)
   877  
   878  	if err := ioutil.Rename(p1, p2); err != nil {
   879  		t.Fatal(err)
   880  	}
   881  
   882  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{
   883  		"new": func(fi os.FileInfo) error {
   884  			return mustBeFileWithSize(fi, int64(len(input)))
   885  		},
   886  	})
   887  
   888  	buf, err := ioutil.ReadFile(p2)
   889  	if err != nil {
   890  		t.Errorf("read error: %v", err)
   891  	}
   892  	if g, e := string(buf), input; g != e {
   893  		t.Errorf("bad file contents: %q != %q", g, e)
   894  	}
   895  
   896  	if _, err := ioutil.ReadFile(p1); !ioutil.IsNotExist(err) {
   897  		t.Errorf("old name still exists: %v", err)
   898  	}
   899  }
   900  
   901  func TestRenameOverwrite(t *testing.T) {
   902  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   903  	defer testCleanupDelayer(ctx, t)
   904  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   905  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   906  	mnt, _, cancelFn := makeFS(ctx, t, config)
   907  	defer mnt.Close()
   908  	defer cancelFn()
   909  
   910  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "old")
   911  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "new")
   912  	const input = "hello, world\n"
   913  	if err := ioutil.WriteFile(p1, []byte(input), 0644); err != nil {
   914  		t.Fatal(err)
   915  	}
   916  	syncFilename(t, p1)
   917  	if err := ioutil.WriteFile(p2, []byte("loser\n"), 0644); err != nil {
   918  		t.Fatal(err)
   919  	}
   920  	syncFilename(t, p2)
   921  
   922  	if err := ioutil.Rename(p1, p2); err != nil {
   923  		t.Fatal(err)
   924  	}
   925  
   926  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{
   927  		"new": nil,
   928  	})
   929  
   930  	buf, err := ioutil.ReadFile(p2)
   931  	if err != nil {
   932  		t.Errorf("read error: %v", err)
   933  	}
   934  	if g, e := string(buf), input; g != e {
   935  		t.Errorf("bad file contents: %q != %q", g, e)
   936  	}
   937  
   938  	if _, err := ioutil.ReadFile(p1); !ioutil.IsNotExist(err) {
   939  		t.Errorf("old name still exists: %v", err)
   940  	}
   941  }
   942  
   943  func TestRenameCrossDir(t *testing.T) {
   944  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   945  	defer testCleanupDelayer(ctx, t)
   946  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
   947  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   948  	mnt, _, cancelFn := makeFS(ctx, t, config)
   949  	defer mnt.Close()
   950  	defer cancelFn()
   951  
   952  	if err := ioutil.Mkdir(path.Join(mnt.Dir, PrivateName, "jdoe", "one"), 0755); err != nil {
   953  		t.Fatal(err)
   954  	}
   955  	if err := ioutil.Mkdir(path.Join(mnt.Dir, PrivateName, "jdoe", "two"), 0755); err != nil {
   956  		t.Fatal(err)
   957  	}
   958  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "one", "old")
   959  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "two", "new")
   960  	const input = "hello, world\n"
   961  	if err := ioutil.WriteFile(p1, []byte(input), 0644); err != nil {
   962  		t.Fatal(err)
   963  	}
   964  	syncFilename(t, p1)
   965  
   966  	if err := ioutil.Rename(p1, p2); err != nil {
   967  		t.Fatal(err)
   968  	}
   969  
   970  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe", "one"), map[string]fileInfoCheck{})
   971  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe", "two"), map[string]fileInfoCheck{
   972  		"new": nil,
   973  	})
   974  
   975  	buf, err := ioutil.ReadFile(p2)
   976  	if err != nil {
   977  		t.Errorf("read error: %v", err)
   978  	}
   979  	if g, e := string(buf), input; g != e {
   980  		t.Errorf("bad file contents: %q != %q", g, e)
   981  	}
   982  
   983  	if _, err := ioutil.ReadFile(p1); !ioutil.IsNotExist(err) {
   984  		t.Errorf("old name still exists: %v", err)
   985  	}
   986  }
   987  
   988  func TestRenameCrossFolder(t *testing.T) {
   989  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
   990  	defer testCleanupDelayer(ctx, t)
   991  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
   992  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
   993  	mnt, _, cancelFn := makeFS(ctx, t, config)
   994  	defer mnt.Close()
   995  	defer cancelFn()
   996  
   997  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "old")
   998  	p2 := path.Join(mnt.Dir, PrivateName, "wsmith,jdoe", "new")
   999  	const input = "hello, world\n"
  1000  	if err := ioutil.WriteFile(p1, []byte(input), 0644); err != nil {
  1001  		t.Fatal(err)
  1002  	}
  1003  	syncFilename(t, p1)
  1004  
  1005  	err := ioutil.Rename(p1, p2)
  1006  	if err == nil {
  1007  		t.Fatalf("expected an error from rename: %v", err)
  1008  	}
  1009  	lerr, ok := errors.Cause(err).(*os.LinkError)
  1010  	if !ok {
  1011  		t.Fatalf("expected a LinkError from rename: %v", err)
  1012  	}
  1013  	if g, e := lerr.Op, "rename"; g != e {
  1014  		t.Errorf("wrong LinkError.Op: %q != %q", g, e)
  1015  	}
  1016  	if g, e := lerr.Old, p1; g != e {
  1017  		t.Errorf("wrong LinkError.Old: %q != %q", g, e)
  1018  	}
  1019  	if g, e := lerr.New, p2; g != e {
  1020  		t.Errorf("wrong LinkError.New: %q != %q", g, e)
  1021  	}
  1022  	if g, e := lerr.Err, syscall.EXDEV; g != e {
  1023  		t.Errorf("expected EXDEV: %T %v", lerr.Err, lerr.Err)
  1024  	}
  1025  
  1026  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{
  1027  		"old": nil,
  1028  	})
  1029  	checkDir(t, path.Join(mnt.Dir, PrivateName, "wsmith,jdoe"), map[string]fileInfoCheck{})
  1030  
  1031  	buf, err := ioutil.ReadFile(p1)
  1032  	if err != nil {
  1033  		t.Errorf("read error: %v", err)
  1034  	}
  1035  	if g, e := string(buf), input; g != e {
  1036  		t.Errorf("bad file contents: %q != %q", g, e)
  1037  	}
  1038  
  1039  	if _, err := ioutil.ReadFile(p2); !ioutil.IsNotExist(err) {
  1040  		t.Errorf("new name exists even on error: %v", err)
  1041  	}
  1042  }
  1043  
  1044  func TestWriteThenRename(t *testing.T) {
  1045  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1046  	defer testCleanupDelayer(ctx, t)
  1047  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1048  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1049  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1050  	defer mnt.Close()
  1051  	defer cancelFn()
  1052  
  1053  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "old")
  1054  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "new")
  1055  
  1056  	f, err := os.Create(p1)
  1057  	if err != nil {
  1058  		t.Fatalf("cannot create file: %v", err)
  1059  	}
  1060  	defer syncAndClose(t, f)
  1061  
  1062  	// write to the file
  1063  	const input = "hello, world\n"
  1064  	if _, err := f.Write([]byte(input)); err != nil {
  1065  		t.Fatalf("cannot write: %v", err)
  1066  	}
  1067  
  1068  	// now rename the file while it's still open
  1069  	if err := ioutil.Rename(p1, p2); err != nil {
  1070  		t.Fatal(err)
  1071  	}
  1072  
  1073  	// check that the new path has the right length still
  1074  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{
  1075  		"new": func(fi os.FileInfo) error {
  1076  			return mustBeFileWithSize(fi, int64(len(input)))
  1077  		},
  1078  	})
  1079  
  1080  	// write again to the same file
  1081  	const input2 = "goodbye, world\n"
  1082  	if _, err := f.Write([]byte(input2)); err != nil {
  1083  		t.Fatalf("cannot write after rename: %v", err)
  1084  	}
  1085  
  1086  	buf, err := ioutil.ReadFile(p2)
  1087  	if err != nil {
  1088  		t.Errorf("read error: %v", err)
  1089  	}
  1090  	if g, e := string(buf), input+input2; g != e {
  1091  		t.Errorf("bad file contents: %q != %q", g, e)
  1092  	}
  1093  
  1094  	if _, err := ioutil.ReadFile(p1); !ioutil.IsNotExist(err) {
  1095  		t.Errorf("old name still exists: %v", err)
  1096  	}
  1097  }
  1098  
  1099  func TestWriteThenRenameCrossDir(t *testing.T) {
  1100  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1101  	defer testCleanupDelayer(ctx, t)
  1102  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1103  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1104  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1105  	defer mnt.Close()
  1106  	defer cancelFn()
  1107  
  1108  	if err := ioutil.Mkdir(path.Join(mnt.Dir, PrivateName, "jdoe", "one"), 0755); err != nil {
  1109  		t.Fatal(err)
  1110  	}
  1111  	if err := ioutil.Mkdir(path.Join(mnt.Dir, PrivateName, "jdoe", "two"), 0755); err != nil {
  1112  		t.Fatal(err)
  1113  	}
  1114  	p1 := path.Join(mnt.Dir, PrivateName, "jdoe", "one", "old")
  1115  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "two", "new")
  1116  
  1117  	f, err := os.Create(p1)
  1118  	if err != nil {
  1119  		t.Fatalf("cannot create file: %v", err)
  1120  	}
  1121  	defer syncAndClose(t, f)
  1122  
  1123  	// write to the file
  1124  	const input = "hello, world\n"
  1125  	if _, err := f.Write([]byte(input)); err != nil {
  1126  		t.Fatalf("cannot write: %v", err)
  1127  	}
  1128  
  1129  	// now rename the file while it's still open
  1130  	if err := ioutil.Rename(p1, p2); err != nil {
  1131  		t.Fatal(err)
  1132  	}
  1133  
  1134  	// check that the new path has the right length still
  1135  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe", "two"), map[string]fileInfoCheck{
  1136  		"new": func(fi os.FileInfo) error {
  1137  			return mustBeFileWithSize(fi, int64(len(input)))
  1138  		},
  1139  	})
  1140  
  1141  	// write again to the same file
  1142  	const input2 = "goodbye, world\n"
  1143  	if _, err := f.Write([]byte(input2)); err != nil {
  1144  		t.Fatalf("cannot write after rename: %v", err)
  1145  	}
  1146  
  1147  	buf, err := ioutil.ReadFile(p2)
  1148  	if err != nil {
  1149  		t.Errorf("read error: %v", err)
  1150  	}
  1151  	if g, e := string(buf), input+input2; g != e {
  1152  		t.Errorf("bad file contents: %q != %q", g, e)
  1153  	}
  1154  
  1155  	if _, err := ioutil.ReadFile(p1); !ioutil.IsNotExist(err) {
  1156  		t.Errorf("old name still exists: %v", err)
  1157  	}
  1158  }
  1159  
  1160  func TestRemoveFile(t *testing.T) {
  1161  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1162  	defer testCleanupDelayer(ctx, t)
  1163  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1164  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1165  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1166  	defer mnt.Close()
  1167  	defer cancelFn()
  1168  
  1169  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1170  	const input = "hello, world\n"
  1171  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1172  		t.Fatal(err)
  1173  	}
  1174  	syncFilename(t, p)
  1175  
  1176  	if err := ioutil.Remove(p); err != nil {
  1177  		t.Fatal(err)
  1178  	}
  1179  
  1180  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{})
  1181  
  1182  	if _, err := ioutil.ReadFile(p); !ioutil.IsNotExist(err) {
  1183  		t.Errorf("file still exists: %v", err)
  1184  	}
  1185  }
  1186  
  1187  func TestRemoveTLF(t *testing.T) {
  1188  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1189  	defer testCleanupDelayer(ctx, t)
  1190  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "pikachu")
  1191  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1192  	defer mnt.Close()
  1193  	defer cancelFn()
  1194  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1195  
  1196  	p := path.Join(mnt.Dir, PrivateName, "jdoe,pikachu")
  1197  	f1, err := os.Create(path.Join(p, "f"))
  1198  	if err != nil {
  1199  		t.Fatal(err)
  1200  	}
  1201  	syncAndClose(t, f1)
  1202  
  1203  	privatePath := path.Join(mnt.Dir, PrivateName)
  1204  	checks := map[string]fileInfoCheck{
  1205  		"jdoe": nil,
  1206  	}
  1207  
  1208  	var lastErr error
  1209  	for i := 0; i < 10; i++ {
  1210  		if err := syscall.Rmdir(p); err != nil {
  1211  			t.Fatal(err)
  1212  		}
  1213  
  1214  		if runtime.GOOS != "darwin" {
  1215  			checkDir(t, privatePath, checks)
  1216  			return
  1217  		}
  1218  
  1219  		// On OSX, the OS might decide to look up "f" at exactly the wrong
  1220  		// time, and reinstate the "jdoe,pikachu".  Unfortunately there's
  1221  		// no good way to prevent this, so for now we just allow it to
  1222  		// happen and retry until we get what we want.  See KBFS-1370.
  1223  		lastErr = checkDirNoTestError(t, privatePath, checks)
  1224  		if lastErr == nil {
  1225  			return
  1226  		}
  1227  
  1228  		// Make sure the test should still be running.
  1229  		select {
  1230  		case <-ctx.Done():
  1231  			t.Fatal(ctx.Err())
  1232  		default:
  1233  			t.Logf("Retrying TLF removal after error %+v", lastErr)
  1234  		}
  1235  	}
  1236  	if lastErr != nil {
  1237  		t.Error(lastErr)
  1238  	}
  1239  }
  1240  
  1241  func TestRemoveDir(t *testing.T) {
  1242  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1243  	defer testCleanupDelayer(ctx, t)
  1244  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1245  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1246  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1247  	defer mnt.Close()
  1248  	defer cancelFn()
  1249  
  1250  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  1251  	if err := ioutil.Mkdir(p, 0755); err != nil {
  1252  		t.Fatal(err)
  1253  	}
  1254  
  1255  	if err := syscall.Rmdir(p); err != nil {
  1256  		t.Fatal(err)
  1257  	}
  1258  
  1259  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{})
  1260  
  1261  	if _, err := ioutil.Stat(p); !ioutil.IsNotExist(err) {
  1262  		t.Errorf("file still exists: %v", err)
  1263  	}
  1264  }
  1265  
  1266  func TestRemoveDirNotEmpty(t *testing.T) {
  1267  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1268  	defer testCleanupDelayer(ctx, t)
  1269  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1270  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1271  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1272  	defer mnt.Close()
  1273  	defer cancelFn()
  1274  
  1275  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  1276  	if err := ioutil.Mkdir(p, 0755); err != nil {
  1277  		t.Fatal(err)
  1278  	}
  1279  	pFile := path.Join(p, "myfile")
  1280  	if err := ioutil.WriteFile(pFile, []byte("i'm important"), 0644); err != nil {
  1281  		t.Fatal(err)
  1282  	}
  1283  	syncFilename(t, pFile)
  1284  
  1285  	err := syscall.Rmdir(p)
  1286  	if g, e := err, syscall.ENOTEMPTY; g != e {
  1287  		t.Fatalf("wrong error from rmdir: %v (%T) != %v (%T)", g, g, e, e)
  1288  	}
  1289  
  1290  	if _, err := ioutil.ReadFile(pFile); err != nil {
  1291  		t.Errorf("file was lost: %v", err)
  1292  	}
  1293  }
  1294  
  1295  func TestRemoveFileWhileOpenSetEx(t *testing.T) {
  1296  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1297  	defer testCleanupDelayer(ctx, t)
  1298  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1299  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1300  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1301  	defer mnt.Close()
  1302  	defer cancelFn()
  1303  
  1304  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1305  	f, err := os.Create(p)
  1306  	if err != nil {
  1307  		t.Fatalf("cannot create file: %v", err)
  1308  	}
  1309  	// Call in a closure since `f` is overridden below.
  1310  	defer func() { syncAndClose(t, f) }()
  1311  
  1312  	if err := ioutil.Remove(p); err != nil {
  1313  		t.Fatalf("cannot delete file: %v", err)
  1314  	}
  1315  
  1316  	// this must not resurrect a deleted file
  1317  	if err := f.Chmod(0755); err != nil {
  1318  		t.Fatalf("cannot setex: %v", err)
  1319  	}
  1320  
  1321  	// Make sure the mode sticks around even though the file was unlinked.
  1322  	fi, err := f.Stat()
  1323  	if err != nil {
  1324  		t.Fatal(err)
  1325  	}
  1326  	if g, e := fi.Mode().String(), `-rwx------`; g != e {
  1327  		t.Errorf("wrong mode: %q != %q", g, e)
  1328  	}
  1329  	syncAndClose(t, f)
  1330  	f = nil
  1331  
  1332  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"),
  1333  		map[string]fileInfoCheck{})
  1334  
  1335  	if _, err := ioutil.ReadFile(p); !ioutil.IsNotExist(err) {
  1336  		t.Errorf("file still exists: %v", err)
  1337  	}
  1338  }
  1339  
  1340  func TestRemoveFileWhileOpenWritingInTLFRoot(t *testing.T) {
  1341  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1342  	defer testCleanupDelayer(ctx, t)
  1343  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1344  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1345  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1346  	defer mnt.Close()
  1347  	defer cancelFn()
  1348  
  1349  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1350  	f, err := os.Create(p)
  1351  	if err != nil {
  1352  		t.Fatalf("cannot create file: %v", err)
  1353  	}
  1354  	// Call in a closure since `f` is overridden below.
  1355  	defer func() { syncAndClose(t, f) }()
  1356  
  1357  	if err := ioutil.Remove(p); err != nil {
  1358  		t.Fatalf("cannot delete file: %v", err)
  1359  	}
  1360  
  1361  	// this must not resurrect a deleted file
  1362  	const input = "hello, world\n"
  1363  	if _, err := f.Write([]byte(input)); err != nil {
  1364  		t.Fatalf("cannot write: %v", err)
  1365  	}
  1366  	syncAndClose(t, f)
  1367  	f = nil
  1368  
  1369  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{})
  1370  
  1371  	if _, err := ioutil.ReadFile(p); !ioutil.IsNotExist(err) {
  1372  		t.Errorf("file still exists: %v", err)
  1373  	}
  1374  }
  1375  
  1376  func TestRemoveFileWhileOpenWritingInSubDir(t *testing.T) {
  1377  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1378  	defer testCleanupDelayer(ctx, t)
  1379  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1380  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1381  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1382  	defer mnt.Close()
  1383  	defer cancelFn()
  1384  
  1385  	dirPath := path.Join(mnt.Dir, PrivateName, "jdoe", "dir")
  1386  	if err := os.Mkdir(dirPath, 0700); err != nil {
  1387  		t.Fatal(err)
  1388  	}
  1389  
  1390  	p := path.Join(dirPath, "myfile")
  1391  	f, err := os.Create(p)
  1392  	if err != nil {
  1393  		t.Fatalf("cannot create file: %v", err)
  1394  	}
  1395  	// Call in a closure since `f` is overridden below.
  1396  	defer func() { syncAndClose(t, f) }()
  1397  
  1398  	if err := ioutil.Remove(p); err != nil {
  1399  		t.Fatalf("cannot delete file: %v", err)
  1400  	}
  1401  
  1402  	// this must not resurrect a deleted file
  1403  	const input = "hello, world\n"
  1404  	if _, err := f.Write([]byte(input)); err != nil {
  1405  		t.Fatalf("cannot write: %v", err)
  1406  	}
  1407  	syncAndClose(t, f)
  1408  	f = nil
  1409  
  1410  	checkDir(t, dirPath, map[string]fileInfoCheck{})
  1411  
  1412  	if _, err := ioutil.ReadFile(p); !ioutil.IsNotExist(err) {
  1413  		t.Errorf("file still exists: %v", err)
  1414  	}
  1415  }
  1416  
  1417  func TestRenameOverFileWhileOpenWritingInDifferentDir(t *testing.T) {
  1418  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1419  	defer testCleanupDelayer(ctx, t)
  1420  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1421  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1422  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1423  	defer mnt.Close()
  1424  	defer cancelFn()
  1425  
  1426  	dirPath := path.Join(mnt.Dir, PrivateName, "jdoe", "dir")
  1427  	if err := os.Mkdir(dirPath, 0700); err != nil {
  1428  		t.Fatal(err)
  1429  	}
  1430  
  1431  	p1 := path.Join(dirPath, "myfile")
  1432  	f1, err := os.Create(p1)
  1433  	if err != nil {
  1434  		t.Fatalf("cannot create file: %v", err)
  1435  	}
  1436  	// Call in a closure since `f1` is overridden below.
  1437  	defer func() { syncAndClose(t, f1) }()
  1438  
  1439  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "mynewfile")
  1440  	f2, err := os.Create(p2)
  1441  	if err != nil {
  1442  		t.Fatalf("cannot create file: %v", err)
  1443  	}
  1444  	syncAndClose(t, f2)
  1445  
  1446  	if err := os.Rename(p2, p1); err != nil {
  1447  		t.Fatalf("cannot move file: %v", err)
  1448  	}
  1449  
  1450  	// this must not resurrect content in f2
  1451  	const input = "hello, world\n"
  1452  	if _, err := f1.Write([]byte(input)); err != nil {
  1453  		t.Fatalf("cannot write: %v", err)
  1454  	}
  1455  	syncAndClose(t, f1)
  1456  	f1 = nil
  1457  
  1458  	checkDir(t, dirPath, map[string]fileInfoCheck{"myfile": nil})
  1459  
  1460  	content, err := ioutil.ReadFile(p1)
  1461  	if err != nil {
  1462  		t.Fatal(err)
  1463  	}
  1464  	if len(content) > 0 {
  1465  		t.Errorf("write to overwritee resulted in content in overwriter")
  1466  	}
  1467  }
  1468  
  1469  func TestRenameOverFileWhileOpenWritingInSameSubDir(t *testing.T) {
  1470  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1471  	defer testCleanupDelayer(ctx, t)
  1472  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1473  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1474  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1475  	defer mnt.Close()
  1476  	defer cancelFn()
  1477  
  1478  	dirPath := path.Join(mnt.Dir, PrivateName, "jdoe", "dir")
  1479  	if err := os.Mkdir(dirPath, 0700); err != nil {
  1480  		t.Fatal(err)
  1481  	}
  1482  
  1483  	p1 := path.Join(dirPath, "myfile")
  1484  	f1, err := os.Create(p1)
  1485  	if err != nil {
  1486  		t.Fatalf("cannot create file: %v", err)
  1487  	}
  1488  	// Call in a closure since `f1` is overridden below.
  1489  	defer func() { syncAndClose(t, f1) }()
  1490  
  1491  	p2 := path.Join(dirPath, "mynewfile")
  1492  	f2, err := os.Create(p2)
  1493  	if err != nil {
  1494  		t.Fatalf("cannot create file: %v", err)
  1495  	}
  1496  	syncAndClose(t, f2)
  1497  
  1498  	if err := os.Rename(p2, p1); err != nil {
  1499  		t.Fatalf("cannot move file: %v", err)
  1500  	}
  1501  
  1502  	// this must not resurrect content in f2
  1503  	const input = "hello, world\n"
  1504  	if _, err := f1.Write([]byte(input)); err != nil {
  1505  		t.Fatalf("cannot write: %v", err)
  1506  	}
  1507  	syncAndClose(t, f1)
  1508  	f1 = nil
  1509  
  1510  	checkDir(t, dirPath, map[string]fileInfoCheck{"myfile": nil})
  1511  
  1512  	content, err := ioutil.ReadFile(p1)
  1513  	if err != nil {
  1514  		t.Fatal(err)
  1515  	}
  1516  	if len(content) > 0 {
  1517  		t.Errorf("write to overwritee resulted in content in overwriter")
  1518  	}
  1519  }
  1520  
  1521  func TestRemoveFileWhileOpenReading(t *testing.T) {
  1522  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1523  	defer testCleanupDelayer(ctx, t)
  1524  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1525  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1526  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1527  	defer mnt.Close()
  1528  	defer cancelFn()
  1529  
  1530  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1531  	const input = "hello, world\n"
  1532  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1533  		t.Fatal(err)
  1534  	}
  1535  	syncFilename(t, p)
  1536  
  1537  	f, err := os.Open(p)
  1538  	if err != nil {
  1539  		t.Fatalf("cannot open file: %v", err)
  1540  	}
  1541  	// Call in a closure since `f` is overridden below.
  1542  	defer func() { syncAndClose(t, f) }()
  1543  
  1544  	if err := ioutil.Remove(p); err != nil {
  1545  		t.Fatalf("cannot delete file: %v", err)
  1546  	}
  1547  
  1548  	buf, err := ioutil.ReadAll(f)
  1549  	if err != nil {
  1550  		t.Fatalf("cannot read unlinked file: %v", err)
  1551  	}
  1552  	if g, e := string(buf), input; g != e {
  1553  		t.Errorf("read wrong content: %q != %q", g, e)
  1554  	}
  1555  
  1556  	syncAndClose(t, f)
  1557  	f = nil
  1558  
  1559  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe"), map[string]fileInfoCheck{})
  1560  
  1561  	if _, err := ioutil.ReadFile(p); !ioutil.IsNotExist(err) {
  1562  		t.Errorf("file still exists: %v", err)
  1563  	}
  1564  }
  1565  
  1566  func TestRemoveFileWhileOpenReadingAcrossMounts(t *testing.T) {
  1567  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1568  	defer testCleanupDelayer(ctx, t)
  1569  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  1570  		"user2")
  1571  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  1572  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  1573  	defer mnt1.Close()
  1574  	defer cancelFn1()
  1575  
  1576  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  1577  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  1578  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  1579  	defer mnt2.Close()
  1580  	defer cancelFn2()
  1581  
  1582  	if !mnt2.Conn.Protocol().HasInvalidate() {
  1583  		t.Skip("Old FUSE protocol")
  1584  	}
  1585  
  1586  	p1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "myfile")
  1587  	const input = "hello, world\n"
  1588  	if err := ioutil.WriteFile(p1, []byte(input), 0644); err != nil {
  1589  		t.Fatal(err)
  1590  	}
  1591  	syncFilename(t, p1)
  1592  
  1593  	f, err := os.Open(p1)
  1594  	if err != nil {
  1595  		t.Fatalf("cannot open file: %v", err)
  1596  	}
  1597  	// Call in a closure since `f` is overridden below.
  1598  	defer func() { syncAndClose(t, f) }()
  1599  
  1600  	syncFolderToServer(t, "user1,user2", fs2)
  1601  
  1602  	p2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "myfile")
  1603  	if err := ioutil.Remove(p2); err != nil {
  1604  		t.Fatalf("cannot delete file: %v", err)
  1605  	}
  1606  	syncAll(t, "user1,user2", tlf.Private, fs2)
  1607  
  1608  	syncFolderToServer(t, "user1,user2", fs1)
  1609  
  1610  	buf, err := ioutil.ReadAll(f)
  1611  	if err != nil {
  1612  		t.Fatalf("cannot read unlinked file: %v", err)
  1613  	}
  1614  	if g, e := string(buf), input; g != e {
  1615  		t.Errorf("read wrong content: %q != %q", g, e)
  1616  	}
  1617  
  1618  	syncAndClose(t, f)
  1619  	f = nil
  1620  
  1621  	checkDir(t, path.Join(mnt1.Dir, PrivateName, "user1,user2"),
  1622  		map[string]fileInfoCheck{})
  1623  
  1624  	if _, err := ioutil.ReadFile(p1); !ioutil.IsNotExist(err) {
  1625  		t.Errorf("file still exists: %v", err)
  1626  	}
  1627  }
  1628  
  1629  func TestRenameOverFileWhileOpenReadingAcrossMounts(t *testing.T) {
  1630  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1631  	defer testCleanupDelayer(ctx, t)
  1632  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  1633  		"user2")
  1634  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  1635  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  1636  	defer mnt1.Close()
  1637  	defer cancelFn1()
  1638  
  1639  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  1640  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  1641  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  1642  	defer mnt2.Close()
  1643  	defer cancelFn2()
  1644  
  1645  	if !mnt2.Conn.Protocol().HasInvalidate() {
  1646  		t.Skip("Old FUSE protocol")
  1647  	}
  1648  
  1649  	p1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "myfile")
  1650  	const input = "hello, world\n"
  1651  	if err := ioutil.WriteFile(p1, []byte(input), 0644); err != nil {
  1652  		t.Fatal(err)
  1653  	}
  1654  	syncFilename(t, p1)
  1655  
  1656  	p1Other := path.Join(mnt1.Dir, PrivateName, "user1,user2", "other")
  1657  	const inputOther = "hello, other\n"
  1658  	if err := ioutil.WriteFile(p1Other, []byte(inputOther), 0644); err != nil {
  1659  		t.Fatal(err)
  1660  	}
  1661  	syncFilename(t, p1Other)
  1662  
  1663  	f, err := os.Open(p1)
  1664  	if err != nil {
  1665  		t.Fatalf("cannot open file: %v", err)
  1666  	}
  1667  	// Call in a closure since `f` is overridden below.
  1668  	defer func() { syncAndClose(t, f) }()
  1669  
  1670  	syncFolderToServer(t, "user1,user2", fs2)
  1671  
  1672  	p2Other := path.Join(mnt2.Dir, PrivateName, "user1,user2", "other")
  1673  	p2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "myfile")
  1674  	if err := ioutil.Rename(p2Other, p2); err != nil {
  1675  		t.Fatalf("cannot rename file: %v", err)
  1676  	}
  1677  	syncAll(t, "user1,user2", tlf.Private, fs2)
  1678  
  1679  	syncFolderToServer(t, "user1,user2", fs1)
  1680  
  1681  	buf, err := ioutil.ReadAll(f)
  1682  	if err != nil {
  1683  		t.Fatalf("cannot read unlinked file: %v", err)
  1684  	}
  1685  	if g, e := string(buf), input; g != e {
  1686  		t.Errorf("read wrong content: %q != %q", g, e)
  1687  	}
  1688  
  1689  	syncAndClose(t, f)
  1690  	f = nil
  1691  
  1692  	checkDir(t, path.Join(mnt1.Dir, PrivateName, "user1,user2"),
  1693  		map[string]fileInfoCheck{
  1694  			"myfile": nil,
  1695  		})
  1696  
  1697  	if _, err := ioutil.ReadFile(p1Other); !ioutil.IsNotExist(err) {
  1698  		t.Errorf("other file still exists: %v", err)
  1699  	}
  1700  
  1701  	buf, err = ioutil.ReadFile(p1)
  1702  	if err != nil {
  1703  		t.Errorf("read error: %v", err)
  1704  	}
  1705  	if g, e := string(buf), inputOther; g != e {
  1706  		t.Errorf("bad file contents: %q != %q", g, e)
  1707  	}
  1708  }
  1709  
  1710  func TestTruncateGrow(t *testing.T) {
  1711  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1712  	defer testCleanupDelayer(ctx, t)
  1713  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1714  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1715  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1716  	defer mnt.Close()
  1717  	defer cancelFn()
  1718  
  1719  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1720  	const input = "hello, world\n"
  1721  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1722  		t.Fatal(err)
  1723  	}
  1724  	syncFilename(t, p)
  1725  
  1726  	const newSize = 100
  1727  	if err := os.Truncate(p, newSize); err != nil {
  1728  		t.Fatal(err)
  1729  	}
  1730  	syncFilename(t, p)
  1731  
  1732  	fi, err := ioutil.Lstat(p)
  1733  	if err != nil {
  1734  		t.Fatal(err)
  1735  	}
  1736  	if g, e := fi.Size(), int64(newSize); g != e {
  1737  		t.Errorf("wrong size: %v != %v", g, e)
  1738  	}
  1739  
  1740  	buf, err := ioutil.ReadFile(p)
  1741  	if err != nil {
  1742  		t.Fatalf("cannot read unlinked file: %v", err)
  1743  	}
  1744  	if g, e := string(buf), input+strings.Repeat("\x00", newSize-len(input)); g != e {
  1745  		t.Errorf("read wrong content: %q != %q", g, e)
  1746  	}
  1747  }
  1748  
  1749  func TestTruncateShrink(t *testing.T) {
  1750  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1751  	defer testCleanupDelayer(ctx, t)
  1752  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1753  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1754  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1755  	defer mnt.Close()
  1756  	defer cancelFn()
  1757  
  1758  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1759  	const input = "hello, world\n"
  1760  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1761  		t.Fatal(err)
  1762  	}
  1763  	syncFilename(t, p)
  1764  
  1765  	const newSize = 4
  1766  	if err := os.Truncate(p, newSize); err != nil {
  1767  		t.Fatal(err)
  1768  	}
  1769  	syncFilename(t, p)
  1770  
  1771  	fi, err := ioutil.Lstat(p)
  1772  	if err != nil {
  1773  		t.Fatal(err)
  1774  	}
  1775  	if g, e := fi.Size(), int64(newSize); g != e {
  1776  		t.Errorf("wrong size: %v != %v", g, e)
  1777  	}
  1778  
  1779  	buf, err := ioutil.ReadFile(p)
  1780  	if err != nil {
  1781  		t.Fatalf("cannot read unlinked file: %v", err)
  1782  	}
  1783  	if g, e := string(buf), input[:newSize]; g != e {
  1784  		t.Errorf("read wrong content: %q != %q", g, e)
  1785  	}
  1786  }
  1787  
  1788  func TestChmodExec(t *testing.T) {
  1789  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1790  	defer testCleanupDelayer(ctx, t)
  1791  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1792  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1793  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1794  	defer mnt.Close()
  1795  	defer cancelFn()
  1796  
  1797  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1798  	const input = "hello, world\n"
  1799  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1800  		t.Fatal(err)
  1801  	}
  1802  	syncFilename(t, p)
  1803  
  1804  	if err := os.Chmod(p, 0744); err != nil {
  1805  		t.Fatal(err)
  1806  	}
  1807  
  1808  	fi, err := ioutil.Lstat(p)
  1809  	if err != nil {
  1810  		t.Fatal(err)
  1811  	}
  1812  	if g, e := fi.Mode().String(), `-rwx------`; g != e {
  1813  		t.Errorf("wrong mode: %q != %q", g, e)
  1814  	}
  1815  }
  1816  
  1817  func TestChmodNonExec(t *testing.T) {
  1818  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1819  	defer testCleanupDelayer(ctx, t)
  1820  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1821  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1822  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1823  	defer mnt.Close()
  1824  	defer cancelFn()
  1825  
  1826  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1827  	const input = "hello, world\n"
  1828  	if err := ioutil.WriteFile(p, []byte(input), 0755); err != nil {
  1829  		t.Fatal(err)
  1830  	}
  1831  	syncFilename(t, p)
  1832  
  1833  	if err := os.Chmod(p, 0655); err != nil {
  1834  		t.Fatal(err)
  1835  	}
  1836  
  1837  	fi, err := ioutil.Lstat(p)
  1838  	if err != nil {
  1839  		t.Fatal(err)
  1840  	}
  1841  	if g, e := fi.Mode().String(), `-rw-------`; g != e {
  1842  		t.Errorf("wrong mode: %q != %q", g, e)
  1843  	}
  1844  }
  1845  
  1846  func TestChownFileIgnored(t *testing.T) {
  1847  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1848  	defer testCleanupDelayer(ctx, t)
  1849  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1850  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1851  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1852  	defer mnt.Close()
  1853  	defer cancelFn()
  1854  
  1855  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1856  	const input = "hello, world\n"
  1857  	if err := ioutil.WriteFile(p, []byte(input), 0755); err != nil {
  1858  		t.Fatal(err)
  1859  	}
  1860  	syncFilename(t, p)
  1861  
  1862  	fi, err := ioutil.Lstat(p)
  1863  	if err != nil {
  1864  		t.Fatal(err)
  1865  	}
  1866  	oldOwner := int(fi.Sys().(*syscall.Stat_t).Uid)
  1867  
  1868  	if err := os.Chown(p, oldOwner+1, oldOwner+1); err != nil {
  1869  		t.Fatalf("Expecting the file chown to get swallowed silently, "+
  1870  			"but got: %v", err)
  1871  	}
  1872  
  1873  	newFi, err := ioutil.Lstat(p)
  1874  	if err != nil {
  1875  		t.Fatal(err)
  1876  	}
  1877  	newOwner := int(newFi.Sys().(*syscall.Stat_t).Uid)
  1878  	if oldOwner != newOwner {
  1879  		t.Fatalf("Owner changed unexpectedly to %d after a chown", newOwner)
  1880  	}
  1881  }
  1882  
  1883  func TestChmodDirIgnored(t *testing.T) {
  1884  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1885  	defer testCleanupDelayer(ctx, t)
  1886  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1887  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1888  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1889  	defer mnt.Close()
  1890  	defer cancelFn()
  1891  
  1892  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  1893  	if err := ioutil.Mkdir(p, 0755); err != nil {
  1894  		t.Fatal(err)
  1895  	}
  1896  
  1897  	if err := os.Chmod(p, 0655); err != nil {
  1898  		t.Fatalf("Expecting the dir chmod to get swallowed silently, "+
  1899  			"but got: %v", err)
  1900  	}
  1901  }
  1902  
  1903  func TestChownDirIgnored(t *testing.T) {
  1904  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1905  	defer testCleanupDelayer(ctx, t)
  1906  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1907  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1908  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1909  	defer mnt.Close()
  1910  	defer cancelFn()
  1911  
  1912  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  1913  	if err := ioutil.Mkdir(p, 0755); err != nil {
  1914  		t.Fatal(err)
  1915  	}
  1916  
  1917  	fi, err := ioutil.Lstat(p)
  1918  	if err != nil {
  1919  		t.Fatal(err)
  1920  	}
  1921  	oldOwner := int(fi.Sys().(*syscall.Stat_t).Uid)
  1922  
  1923  	if err := os.Chown(p, 1, 1); err != nil {
  1924  		t.Fatalf("Expecting the dir chown to get swallowed silently, "+
  1925  			"but got: %v", err)
  1926  	}
  1927  
  1928  	newFi, err := ioutil.Lstat(p)
  1929  	if err != nil {
  1930  		t.Fatal(err)
  1931  	}
  1932  	newOwner := int(newFi.Sys().(*syscall.Stat_t).Uid)
  1933  	if oldOwner != newOwner {
  1934  		t.Fatalf("Owner changed unexpectedly to %d after a chown", newOwner)
  1935  	}
  1936  }
  1937  
  1938  func TestSetattrFileMtime(t *testing.T) {
  1939  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1940  	defer testCleanupDelayer(ctx, t)
  1941  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1942  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1943  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1944  	defer mnt.Close()
  1945  	defer cancelFn()
  1946  
  1947  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1948  	const input = "hello, world\n"
  1949  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1950  		t.Fatal(err)
  1951  	}
  1952  	syncFilename(t, p)
  1953  
  1954  	mtime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.Local)
  1955  	// KBFS does not respect atime (which is ok), but we need to give
  1956  	// something to the syscall.
  1957  	atime := time.Date(2015, 7, 8, 9, 10, 11, 12, time.Local)
  1958  	if err := os.Chtimes(p, atime, mtime); err != nil {
  1959  		t.Fatal(err)
  1960  	}
  1961  
  1962  	fi, err := ioutil.Lstat(p)
  1963  	if err != nil {
  1964  		t.Fatal(err)
  1965  	}
  1966  	if g, e := fi.ModTime(), mtime; !libfs.TimeEqual(g, e) {
  1967  		t.Errorf("wrong mtime: %v !~= %v", g, e)
  1968  	}
  1969  }
  1970  
  1971  func TestSetattrFileMtimeAfterWrite(t *testing.T) {
  1972  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1973  	defer testCleanupDelayer(ctx, t)
  1974  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  1975  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  1976  	mnt, _, cancelFn := makeFS(ctx, t, config)
  1977  	defer mnt.Close()
  1978  	defer cancelFn()
  1979  
  1980  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  1981  	const input = "hello, world\n"
  1982  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  1983  		t.Fatal(err)
  1984  	}
  1985  	syncFilename(t, p)
  1986  
  1987  	const input2 = "second round of content"
  1988  	{
  1989  		ctx := libcontext.BackgroundContextWithCancellationDelayer()
  1990  		defer testCleanupDelayer(ctx, t)
  1991  
  1992  		jdoe := libkbfs.GetRootNodeOrBust(ctx, t, config, "jdoe", tlf.Private)
  1993  
  1994  		ops := config.KBFSOps()
  1995  		myfile, _, err := ops.Lookup(ctx, jdoe, jdoe.ChildName("myfile"))
  1996  		if err != nil {
  1997  			t.Fatal(err)
  1998  		}
  1999  		if err := ops.Write(ctx, myfile, []byte(input2), 0); err != nil {
  2000  			t.Fatal(err)
  2001  		}
  2002  		// Don't sync
  2003  	}
  2004  
  2005  	mtime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.Local)
  2006  	// KBFS does not respect atime (which is ok), but we need to give
  2007  	// something to the syscall.
  2008  	atime := time.Date(2015, 7, 8, 9, 10, 11, 12, time.Local)
  2009  	if err := os.Chtimes(p, atime, mtime); err != nil {
  2010  		t.Fatal(err)
  2011  	}
  2012  
  2013  	fi, err := ioutil.Lstat(p)
  2014  	if err != nil {
  2015  		t.Fatal(err)
  2016  	}
  2017  	if g, e := fi.ModTime(), mtime; !libfs.TimeEqual(g, e) {
  2018  		t.Errorf("wrong mtime: %v !~= %v", g, e)
  2019  	}
  2020  	syncFilename(t, p)
  2021  }
  2022  
  2023  func TestSetattrFileMtimeNow(t *testing.T) {
  2024  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2025  	defer testCleanupDelayer(ctx, t)
  2026  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2027  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2028  	mnt, _, cancelFn := makeFS(ctx, t, config)
  2029  	defer mnt.Close()
  2030  	defer cancelFn()
  2031  
  2032  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  2033  	const input = "hello, world\n"
  2034  	if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  2035  		t.Fatal(err)
  2036  	}
  2037  	syncFilename(t, p)
  2038  
  2039  	mtime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.Local)
  2040  	// KBFS does not respect atime (which is ok), but we need to give
  2041  	// something to the syscall.
  2042  	atime := time.Date(2015, 7, 8, 9, 10, 11, 12, time.Local)
  2043  	if err := os.Chtimes(p, atime, mtime); err != nil {
  2044  		t.Fatal(err)
  2045  	}
  2046  
  2047  	// cause mtime to be set to now
  2048  	if err := unix.Utimes(p, nil); err != nil {
  2049  		t.Fatalf("touch failed: %v", err)
  2050  	}
  2051  	now := time.Now()
  2052  
  2053  	fi, err := ioutil.Lstat(p)
  2054  	if err != nil {
  2055  		t.Fatal(err)
  2056  	}
  2057  	if g, o := fi.ModTime(), mtime; !g.After(o) {
  2058  		t.Errorf("mtime did not progress: %v <= %v", g, o)
  2059  	}
  2060  	if g, e := fi.ModTime(), now; !timeEqualFuzzy(g, e, 1*time.Second) {
  2061  		t.Errorf("mtime is wrong: %v !~= %v", g, e)
  2062  	}
  2063  }
  2064  
  2065  func TestSetattrDirMtime(t *testing.T) {
  2066  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2067  	defer testCleanupDelayer(ctx, t)
  2068  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2069  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2070  	mnt, _, cancelFn := makeFS(ctx, t, config)
  2071  	defer mnt.Close()
  2072  	defer cancelFn()
  2073  
  2074  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  2075  	if err := ioutil.Mkdir(p, 0755); err != nil {
  2076  		t.Fatal(err)
  2077  	}
  2078  
  2079  	mtime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.Local)
  2080  	// KBFS does not respect atime (which is ok), but we need to give
  2081  	// something to the syscall.
  2082  	atime := time.Date(2015, 7, 8, 9, 10, 11, 12, time.Local)
  2083  	if err := os.Chtimes(p, atime, mtime); err != nil {
  2084  		t.Fatal(err)
  2085  	}
  2086  
  2087  	fi, err := ioutil.Lstat(p)
  2088  	if err != nil {
  2089  		t.Fatal(err)
  2090  	}
  2091  	if g, e := fi.ModTime(), mtime; !libfs.TimeEqual(g, e) {
  2092  		t.Errorf("wrong mtime: %v !~= %v", g, e)
  2093  	}
  2094  }
  2095  
  2096  func TestSetattrDirMtimeNow(t *testing.T) {
  2097  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2098  	defer testCleanupDelayer(ctx, t)
  2099  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2100  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2101  	mnt, _, cancelFn := makeFS(ctx, t, config)
  2102  	defer mnt.Close()
  2103  	defer cancelFn()
  2104  
  2105  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  2106  	if err := ioutil.Mkdir(p, 0755); err != nil {
  2107  		t.Fatal(err)
  2108  	}
  2109  
  2110  	mtime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.Local)
  2111  	// KBFS does not respect atime (which is ok), but we need to give
  2112  	// something to the syscall.
  2113  	atime := time.Date(2015, 7, 8, 9, 10, 11, 12, time.Local)
  2114  	if err := os.Chtimes(p, atime, mtime); err != nil {
  2115  		t.Fatal(err)
  2116  	}
  2117  
  2118  	// cause mtime to be set to now
  2119  	if err := unix.Utimes(p, nil); err != nil {
  2120  		t.Fatalf("touch failed: %v", err)
  2121  	}
  2122  	now := time.Now()
  2123  
  2124  	fi, err := ioutil.Lstat(p)
  2125  	if err != nil {
  2126  		t.Fatal(err)
  2127  	}
  2128  	if g, o := fi.ModTime(), mtime; !g.After(o) {
  2129  		t.Errorf("mtime did not progress: %v <= %v", g, o)
  2130  	}
  2131  	if g, e := fi.ModTime(), now; !timeEqualFuzzy(g, e, 1*time.Second) {
  2132  		t.Errorf("mtime is wrong: %v !~= %v", g, e)
  2133  	}
  2134  }
  2135  
  2136  func TestFsync(t *testing.T) {
  2137  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2138  	defer testCleanupDelayer(ctx, t)
  2139  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2140  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2141  	mnt, _, cancelFn := makeFS(ctx, t, config)
  2142  	defer mnt.Close()
  2143  	defer cancelFn()
  2144  
  2145  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  2146  	f, err := os.Create(p)
  2147  	if err != nil {
  2148  		t.Fatal(err)
  2149  	}
  2150  	// Call in a closure since `f` is overridden below.
  2151  	defer func() { syncAndClose(t, f) }()
  2152  	const input = "hello, world\n"
  2153  	if _, err := io.WriteString(f, input); err != nil {
  2154  		t.Fatalf("write error: %v", err)
  2155  	}
  2156  	if err := f.Sync(); err != nil {
  2157  		t.Fatalf("fsync error: %v", err)
  2158  	}
  2159  	if err := f.Close(); err != nil {
  2160  		t.Fatalf("close error: %v", err)
  2161  	}
  2162  	f = nil
  2163  }
  2164  
  2165  func TestReaddirMyPublic(t *testing.T) {
  2166  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2167  	defer testCleanupDelayer(ctx, t)
  2168  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2169  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2170  	mnt, _, cancelFn := makeFS(ctx, t, config)
  2171  	defer mnt.Close()
  2172  	defer cancelFn()
  2173  
  2174  	files := map[string]fileInfoCheck{
  2175  		"one": nil,
  2176  		"two": nil,
  2177  	}
  2178  	for filename := range files {
  2179  		p := path.Join(mnt.Dir, PublicName, "jdoe", filename)
  2180  		if err := ioutil.WriteFile(
  2181  			p, []byte("data for "+filename), 0644); err != nil {
  2182  			t.Fatal(err)
  2183  		}
  2184  		syncFilename(t, p)
  2185  	}
  2186  
  2187  	checkDir(t, path.Join(mnt.Dir, PublicName, "jdoe"), files)
  2188  }
  2189  
  2190  func TestReaddirOtherFolderAsReader(t *testing.T) {
  2191  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2192  	defer testCleanupDelayer(ctx, t)
  2193  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2194  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2195  	func() {
  2196  		mnt, _, cancelFn := makeFS(ctx, t, config)
  2197  		defer mnt.Close()
  2198  		defer cancelFn()
  2199  
  2200  		// cause the folder to exist
  2201  		p := path.Join(mnt.Dir, PrivateName, "jdoe#wsmith", "myfile")
  2202  		if err := ioutil.WriteFile(
  2203  			p, []byte("data for myfile"), 0644); err != nil {
  2204  			t.Fatal(err)
  2205  		}
  2206  		syncFilename(t, p)
  2207  	}()
  2208  
  2209  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2210  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2211  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2212  	defer mnt.Close()
  2213  	defer cancelFn()
  2214  
  2215  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe#wsmith"), map[string]fileInfoCheck{
  2216  		"myfile": nil,
  2217  	})
  2218  }
  2219  
  2220  func TestReaddirMissingOtherFolderAsReader(t *testing.T) {
  2221  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2222  	defer testCleanupDelayer(ctx, t)
  2223  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2224  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2225  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2226  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2227  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2228  	defer mnt.Close()
  2229  	defer cancelFn()
  2230  
  2231  	// Check that folder that doesn't exist yet looks empty
  2232  	checkDir(t, path.Join(mnt.Dir, PrivateName, "jdoe#wsmith"),
  2233  		map[string]fileInfoCheck{})
  2234  }
  2235  
  2236  func TestLookupMissingOtherFolderAsReader(t *testing.T) {
  2237  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2238  	defer testCleanupDelayer(ctx, t)
  2239  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2240  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2241  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2242  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2243  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2244  	defer mnt.Close()
  2245  	defer cancelFn()
  2246  
  2247  	p := path.Join(mnt.Dir, PrivateName, "jdoe#wsmith", "foo")
  2248  	if _, err := ioutil.Stat(p); !ioutil.IsNotExist(err) {
  2249  		t.Errorf("Expected ENOENT, but got: %v", err)
  2250  	}
  2251  }
  2252  
  2253  func TestStatOtherFolder(t *testing.T) {
  2254  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2255  	defer testCleanupDelayer(ctx, t)
  2256  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2257  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2258  	func() {
  2259  		mnt, _, cancelFn := makeFS(ctx, t, config)
  2260  		defer mnt.Close()
  2261  		defer cancelFn()
  2262  
  2263  		// cause the folder to exist
  2264  		p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  2265  		if err := ioutil.WriteFile(
  2266  			p, []byte("data for myfile"), 0644); err != nil {
  2267  			t.Fatal(err)
  2268  		}
  2269  		syncFilename(t, p)
  2270  	}()
  2271  
  2272  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2273  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2274  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2275  	defer mnt.Close()
  2276  	defer cancelFn()
  2277  
  2278  	switch _, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName, "jdoe")); err := errors.Cause(err).(type) {
  2279  	case *os.PathError:
  2280  		if g, e := err.Err, syscall.EACCES; g != e {
  2281  			t.Fatalf("wrong error: %v != %v", g, e)
  2282  		}
  2283  	default:
  2284  		t.Fatalf("expected a PathError, got %T: %v", err, err)
  2285  	}
  2286  }
  2287  
  2288  func TestStatOtherFolderFirstUse(t *testing.T) {
  2289  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2290  	defer testCleanupDelayer(ctx, t)
  2291  	// This triggers a different error than with the warmup.
  2292  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2293  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2294  
  2295  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2296  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2297  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2298  	defer mnt.Close()
  2299  	defer cancelFn()
  2300  
  2301  	switch _, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName, "jdoe")); err := errors.Cause(err).(type) {
  2302  	case *os.PathError:
  2303  		if g, e := err.Err, syscall.EACCES; g != e {
  2304  			t.Fatalf("wrong error: %v != %v", g, e)
  2305  		}
  2306  	default:
  2307  		t.Fatalf("expected a PathError, got %T: %v", err, err)
  2308  	}
  2309  }
  2310  
  2311  func TestStatOtherFolderPublic(t *testing.T) {
  2312  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2313  	defer testCleanupDelayer(ctx, t)
  2314  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2315  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2316  	func() {
  2317  		mnt, _, cancelFn := makeFS(ctx, t, config)
  2318  		defer mnt.Close()
  2319  		defer cancelFn()
  2320  
  2321  		// cause the folder to exist
  2322  		p := path.Join(mnt.Dir, PublicName, "jdoe", "myfile")
  2323  		if err := ioutil.WriteFile(
  2324  			p, []byte("data for myfile"), 0644); err != nil {
  2325  			t.Fatal(err)
  2326  		}
  2327  		syncFilename(t, p)
  2328  	}()
  2329  
  2330  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2331  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2332  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2333  	defer mnt.Close()
  2334  	defer cancelFn()
  2335  
  2336  	fi, err := ioutil.Lstat(path.Join(mnt.Dir, PublicName, "jdoe"))
  2337  	if err != nil {
  2338  		t.Fatal(err)
  2339  	}
  2340  	// TODO figure out right modes, note owner is the person running
  2341  	// fuse, not the person owning the folder
  2342  	if g, e := fi.Mode().String(), `dr-x------`; g != e {
  2343  		t.Errorf("wrong mode for folder: %q != %q", g, e)
  2344  	}
  2345  }
  2346  
  2347  func TestReadPublicFile(t *testing.T) {
  2348  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2349  	defer testCleanupDelayer(ctx, t)
  2350  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2351  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2352  	const input = "hello, world\n"
  2353  	func() {
  2354  		mnt, _, cancelFn := makeFS(ctx, t, config)
  2355  		defer mnt.Close()
  2356  		defer cancelFn()
  2357  
  2358  		// cause the folder to exist
  2359  		p := path.Join(mnt.Dir, PublicName, "jdoe", "myfile")
  2360  		if err := ioutil.WriteFile(p, []byte(input), 0644); err != nil {
  2361  			t.Fatal(err)
  2362  		}
  2363  		syncFilename(t, p)
  2364  	}()
  2365  
  2366  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2367  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2368  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2369  	defer mnt.Close()
  2370  	defer cancelFn()
  2371  
  2372  	buf, err := ioutil.ReadFile(path.Join(mnt.Dir, PublicName, "jdoe", "myfile"))
  2373  	if err != nil {
  2374  		t.Fatal(err)
  2375  	}
  2376  	if g, e := string(buf), input; g != e {
  2377  		t.Errorf("bad file contents: %q != %q", g, e)
  2378  	}
  2379  }
  2380  
  2381  func TestReaddirOtherFolderPublicAsAnyone(t *testing.T) {
  2382  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2383  	defer testCleanupDelayer(ctx, t)
  2384  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2385  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2386  	func() {
  2387  		mnt, _, cancelFn := makeFS(ctx, t, config)
  2388  		defer mnt.Close()
  2389  		defer cancelFn()
  2390  
  2391  		// cause the folder to exist
  2392  		p := path.Join(mnt.Dir, PublicName, "jdoe", "myfile")
  2393  		if err := ioutil.WriteFile(
  2394  			p, []byte("data for myfile"), 0644); err != nil {
  2395  			t.Fatal(err)
  2396  		}
  2397  		syncFilename(t, p)
  2398  	}()
  2399  
  2400  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2401  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2402  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2403  	defer mnt.Close()
  2404  	defer cancelFn()
  2405  
  2406  	checkDir(t, path.Join(mnt.Dir, PublicName, "jdoe"), map[string]fileInfoCheck{
  2407  		"myfile": nil,
  2408  	})
  2409  }
  2410  
  2411  func TestReaddirMissingFolderPublicAsAnyone(t *testing.T) {
  2412  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2413  	defer testCleanupDelayer(ctx, t)
  2414  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2415  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2416  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2417  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2418  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2419  	defer mnt.Close()
  2420  	defer cancelFn()
  2421  
  2422  	// Make sure a public folder, not yet created by its writer, looks empty.
  2423  	checkDir(t, path.Join(mnt.Dir, PublicName, "jdoe"),
  2424  		map[string]fileInfoCheck{})
  2425  }
  2426  
  2427  func TestReaddirOtherFolderAsAnyone(t *testing.T) {
  2428  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2429  	defer testCleanupDelayer(ctx, t)
  2430  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2431  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2432  	func() {
  2433  		mnt, _, cancelFn := makeFS(ctx, t, config)
  2434  		defer mnt.Close()
  2435  		defer cancelFn()
  2436  
  2437  		// cause the folder to exist
  2438  		p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  2439  		if err := ioutil.WriteFile(
  2440  			p, []byte("data for myfile"), 0644); err != nil {
  2441  			t.Fatal(err)
  2442  		}
  2443  		syncFilename(t, p)
  2444  	}()
  2445  
  2446  	c2 := libkbfs.ConfigAsUser(config, "wsmith")
  2447  	defer libkbfs.CheckConfigAndShutdown(ctx, t, c2)
  2448  	mnt, _, cancelFn := makeFS(ctx, t, c2)
  2449  	defer mnt.Close()
  2450  	defer cancelFn()
  2451  
  2452  	switch _, err := ioutil.ReadDir(path.Join(mnt.Dir, PrivateName, "jdoe")); err := errors.Cause(err).(type) {
  2453  	case *os.PathError:
  2454  		if g, e := err.Err, syscall.EACCES; g != e {
  2455  			t.Fatalf("wrong error: %v != %v", g, e)
  2456  		}
  2457  	default:
  2458  		t.Fatalf("expected a PathError, got %T: %v", err, err)
  2459  	}
  2460  }
  2461  
  2462  func syncFolderToServerHelper(t *testing.T, tlf string, ty tlf.Type, fs *FS) {
  2463  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2464  	defer testCleanupDelayer(ctx, t)
  2465  	root := libkbfs.GetRootNodeOrBust(ctx, t, fs.config, tlf, ty)
  2466  	err := fs.config.KBFSOps().SyncFromServer(ctx,
  2467  		root.GetFolderBranch(), nil)
  2468  	if err != nil {
  2469  		t.Fatalf("Couldn't sync from server: %v", err)
  2470  	}
  2471  	fs.NotificationGroupWait()
  2472  }
  2473  
  2474  func syncFolderToServer(t *testing.T, name string, fs *FS) {
  2475  	syncFolderToServerHelper(t, name, tlf.Private, fs)
  2476  }
  2477  
  2478  func syncPublicFolderToServer(t *testing.T, name string, fs *FS) {
  2479  	syncFolderToServerHelper(t, name, tlf.Public, fs)
  2480  }
  2481  
  2482  func TestInvalidateDataOnWrite(t *testing.T) {
  2483  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2484  	defer testCleanupDelayer(ctx, t)
  2485  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2486  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2487  	mnt1, _, cancelFn1 := makeFS(ctx, t, config)
  2488  	defer mnt1.Close()
  2489  	defer cancelFn1()
  2490  	config2 := libkbfs.ConfigAsUser(config, "jdoe")
  2491  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  2492  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  2493  	defer mnt2.Close()
  2494  	defer cancelFn2()
  2495  
  2496  	if !mnt2.Conn.Protocol().HasInvalidate() {
  2497  		t.Skip("Old FUSE protocol")
  2498  	}
  2499  
  2500  	const input1 = "input round one"
  2501  	p := path.Join(mnt1.Dir, PrivateName, "jdoe", "myfile")
  2502  	if err := ioutil.WriteFile(p, []byte(input1), 0644); err != nil {
  2503  		t.Fatal(err)
  2504  	}
  2505  	syncFilename(t, p)
  2506  
  2507  	syncFolderToServer(t, "jdoe", fs2)
  2508  
  2509  	f, err := os.Open(path.Join(mnt2.Dir, PrivateName, "jdoe", "myfile"))
  2510  	if err != nil {
  2511  		t.Fatal(err)
  2512  	}
  2513  	defer syncAndClose(t, f)
  2514  
  2515  	{
  2516  		buf := make([]byte, 4096)
  2517  		n, err := f.ReadAt(buf, 0)
  2518  		if err != nil && err != io.EOF {
  2519  			t.Fatal(err)
  2520  		}
  2521  		if g, e := string(buf[:n]), input1; g != e {
  2522  			t.Errorf("wrong content: %q != %q", g, e)
  2523  		}
  2524  	}
  2525  
  2526  	const input2 = "second round of content"
  2527  	if err := ioutil.WriteFile(p, []byte(input2), 0644); err != nil {
  2528  		t.Fatal(err)
  2529  	}
  2530  	syncFilename(t, p)
  2531  
  2532  	syncFolderToServer(t, "jdoe", fs2)
  2533  
  2534  	{
  2535  		buf := make([]byte, 4096)
  2536  		n, err := f.ReadAt(buf, 0)
  2537  		if err != nil && err != io.EOF {
  2538  			t.Fatal(err)
  2539  		}
  2540  		if g, e := string(buf[:n]), input2; g != e {
  2541  			t.Errorf("wrong content: %q != %q", g, e)
  2542  		}
  2543  	}
  2544  }
  2545  
  2546  func TestInvalidatePublicDataOnWrite(t *testing.T) {
  2547  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2548  	defer testCleanupDelayer(ctx, t)
  2549  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2550  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2551  	mnt1, _, cancelFn1 := makeFS(ctx, t, config)
  2552  	defer mnt1.Close()
  2553  	defer cancelFn1()
  2554  	config2 := libkbfs.ConfigAsUser(config, "jdoe")
  2555  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  2556  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  2557  	defer mnt2.Close()
  2558  	defer cancelFn2()
  2559  
  2560  	if !mnt2.Conn.Protocol().HasInvalidate() {
  2561  		t.Skip("Old FUSE protocol")
  2562  	}
  2563  
  2564  	const input1 = "input round one"
  2565  	p := path.Join(mnt1.Dir, PublicName, "jdoe", "myfile")
  2566  	if err := ioutil.WriteFile(p, []byte(input1), 0644); err != nil {
  2567  		t.Fatal(err)
  2568  	}
  2569  	syncFilename(t, p)
  2570  
  2571  	syncPublicFolderToServer(t, "jdoe", fs2)
  2572  
  2573  	f, err := os.Open(path.Join(mnt2.Dir, PublicName, "jdoe", "myfile"))
  2574  	if err != nil {
  2575  		t.Fatal(err)
  2576  	}
  2577  	defer syncAndClose(t, f)
  2578  
  2579  	{
  2580  		buf := make([]byte, 4096)
  2581  		n, err := f.ReadAt(buf, 0)
  2582  		if err != nil && err != io.EOF {
  2583  			t.Fatal(err)
  2584  		}
  2585  		if g, e := string(buf[:n]), input1; g != e {
  2586  			t.Errorf("wrong content: %q != %q", g, e)
  2587  		}
  2588  	}
  2589  
  2590  	const input2 = "second round of content"
  2591  	if err := ioutil.WriteFile(p, []byte(input2), 0644); err != nil {
  2592  		t.Fatal(err)
  2593  	}
  2594  	syncFilename(t, p)
  2595  
  2596  	syncPublicFolderToServer(t, "jdoe", fs2)
  2597  
  2598  	{
  2599  		buf := make([]byte, 4096)
  2600  		n, err := f.ReadAt(buf, 0)
  2601  		if err != nil && err != io.EOF {
  2602  			t.Fatal(err)
  2603  		}
  2604  		if g, e := string(buf[:n]), input2; g != e {
  2605  			t.Errorf("wrong content: %q != %q", g, e)
  2606  		}
  2607  	}
  2608  }
  2609  
  2610  func TestInvalidateDataOnTruncate(t *testing.T) {
  2611  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2612  	defer testCleanupDelayer(ctx, t)
  2613  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2614  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2615  	mnt1, _, cancelFn1 := makeFS(ctx, t, config)
  2616  	defer mnt1.Close()
  2617  	defer cancelFn1()
  2618  	config2 := libkbfs.ConfigAsUser(config, "jdoe")
  2619  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  2620  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  2621  	defer mnt2.Close()
  2622  	defer cancelFn2()
  2623  
  2624  	if !mnt2.Conn.Protocol().HasInvalidate() {
  2625  		t.Skip("Old FUSE protocol")
  2626  	}
  2627  
  2628  	const input1 = "input round one"
  2629  	p := path.Join(mnt1.Dir, PrivateName, "jdoe", "myfile")
  2630  	if err := ioutil.WriteFile(p, []byte(input1), 0644); err != nil {
  2631  		t.Fatal(err)
  2632  	}
  2633  	syncFilename(t, p)
  2634  
  2635  	syncFolderToServer(t, "jdoe", fs2)
  2636  
  2637  	f, err := os.Open(path.Join(mnt2.Dir, PrivateName, "jdoe", "myfile"))
  2638  	if err != nil {
  2639  		t.Fatal(err)
  2640  	}
  2641  	defer syncAndClose(t, f)
  2642  
  2643  	{
  2644  		buf := make([]byte, 4096)
  2645  		n, err := f.ReadAt(buf, 0)
  2646  		if err != nil && err != io.EOF {
  2647  			t.Fatal(err)
  2648  		}
  2649  		if g, e := string(buf[:n]), input1; g != e {
  2650  			t.Errorf("wrong content: %q != %q", g, e)
  2651  		}
  2652  	}
  2653  
  2654  	const newSize = 3
  2655  	if err := os.Truncate(p, newSize); err != nil {
  2656  		t.Fatal(err)
  2657  	}
  2658  	syncFilename(t, p)
  2659  
  2660  	syncFolderToServer(t, "jdoe", fs2)
  2661  
  2662  	{
  2663  		buf := make([]byte, 4096)
  2664  		n, err := f.ReadAt(buf, 0)
  2665  		if err != nil && err != io.EOF {
  2666  			t.Fatal(err)
  2667  		}
  2668  		if g, e := string(buf[:n]), input1[:newSize]; g != e {
  2669  			t.Errorf("wrong content: %q != %q", g, e)
  2670  		}
  2671  	}
  2672  }
  2673  
  2674  func TestInvalidateDataOnLocalWrite(t *testing.T) {
  2675  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2676  	defer testCleanupDelayer(ctx, t)
  2677  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2678  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2679  	mnt, fs, cancelFn := makeFS(ctx, t, config)
  2680  	defer mnt.Close()
  2681  	defer cancelFn()
  2682  
  2683  	if !mnt.Conn.Protocol().HasInvalidate() {
  2684  		t.Skip("Old FUSE protocol")
  2685  	}
  2686  
  2687  	const input1 = "input round one"
  2688  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  2689  	if err := ioutil.WriteFile(p, []byte(input1), 0644); err != nil {
  2690  		t.Fatal(err)
  2691  	}
  2692  	syncFilename(t, p)
  2693  
  2694  	f, err := os.Open(path.Join(mnt.Dir, PrivateName, "jdoe", "myfile"))
  2695  	if err != nil {
  2696  		t.Fatal(err)
  2697  	}
  2698  	defer syncAndClose(t, f)
  2699  
  2700  	{
  2701  		buf := make([]byte, 4096)
  2702  		n, err := f.ReadAt(buf, 0)
  2703  		if err != nil && err != io.EOF {
  2704  			t.Fatal(err)
  2705  		}
  2706  		if g, e := string(buf[:n]), input1; g != e {
  2707  			t.Errorf("wrong content: %q != %q", g, e)
  2708  		}
  2709  	}
  2710  
  2711  	const input2 = "second round of content"
  2712  	{
  2713  		ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2714  		defer testCleanupDelayer(ctx, t)
  2715  
  2716  		jdoe := libkbfs.GetRootNodeOrBust(ctx, t, config, "jdoe", tlf.Private)
  2717  		ops := config.KBFSOps()
  2718  		myfile, _, err := ops.Lookup(ctx, jdoe, jdoe.ChildName("myfile"))
  2719  		if err != nil {
  2720  			t.Fatal(err)
  2721  		}
  2722  		if err := ops.Write(ctx, myfile, []byte(input2), 0); err != nil {
  2723  			t.Fatal(err)
  2724  		}
  2725  	}
  2726  
  2727  	// The Write above is a local change, and thus we can just do a
  2728  	// local wait without syncing to the server.
  2729  	fs.NotificationGroupWait()
  2730  
  2731  	{
  2732  		buf := make([]byte, 4096)
  2733  		n, err := f.ReadAt(buf, 0)
  2734  		if err != nil && err != io.EOF {
  2735  			t.Fatal(err)
  2736  		}
  2737  		if g, e := string(buf[:n]), input2; g != e {
  2738  			t.Errorf("wrong content: %q != %q", g, e)
  2739  		}
  2740  	}
  2741  }
  2742  
  2743  func TestInvalidateEntryOnDelete(t *testing.T) {
  2744  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2745  	defer testCleanupDelayer(ctx, t)
  2746  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe", "wsmith")
  2747  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2748  	mnt1, _, cancelFn1 := makeFS(ctx, t, config)
  2749  	defer mnt1.Close()
  2750  	defer cancelFn1()
  2751  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config)
  2752  	defer mnt2.Close()
  2753  	defer cancelFn2()
  2754  
  2755  	if !mnt2.Conn.Protocol().HasInvalidate() {
  2756  		t.Skip("Old FUSE protocol")
  2757  	}
  2758  
  2759  	const input1 = "input round one"
  2760  	p := path.Join(mnt1.Dir, PrivateName, "jdoe", "myfile")
  2761  	if err := ioutil.WriteFile(p, []byte(input1), 0644); err != nil {
  2762  		t.Fatal(err)
  2763  	}
  2764  	syncFilename(t, p)
  2765  
  2766  	syncFolderToServer(t, "jdoe", fs2)
  2767  
  2768  	buf, err := ioutil.ReadFile(path.Join(mnt2.Dir, PrivateName, "jdoe", "myfile"))
  2769  	if err != nil {
  2770  		t.Fatal(err)
  2771  	}
  2772  	if g, e := string(buf), input1; g != e {
  2773  		t.Errorf("wrong content: %q != %q", g, e)
  2774  	}
  2775  
  2776  	if err := ioutil.Remove(path.Join(mnt1.Dir, PrivateName, "jdoe", "myfile")); err != nil {
  2777  		t.Fatal(err)
  2778  	}
  2779  
  2780  	syncFolderToServer(t, "jdoe", fs2)
  2781  
  2782  	if buf, err := ioutil.ReadFile(path.Join(mnt2.Dir, PrivateName, "jdoe", "myfile")); !ioutil.IsNotExist(err) {
  2783  		t.Fatalf("expected ENOENT: %v: %q", err, buf)
  2784  	}
  2785  }
  2786  
  2787  func testForErrorText(t *testing.T, path string, expectedErr error,
  2788  	fileType string) {
  2789  	buf, err := ioutil.ReadFile(path)
  2790  	if err != nil {
  2791  		t.Fatalf("Bad error reading %s error file: %v", path, err)
  2792  	}
  2793  
  2794  	var errors []libfs.JSONReportedError
  2795  	err = json.Unmarshal(buf, &errors)
  2796  	if err != nil {
  2797  		t.Fatalf("Couldn't unmarshal error file: %v. Full contents: %s",
  2798  			err, string(buf))
  2799  	}
  2800  
  2801  	found := false
  2802  	for _, e := range errors {
  2803  		if e.Error == expectedErr.Error() {
  2804  			found = true
  2805  			break
  2806  		}
  2807  	}
  2808  
  2809  	if !found {
  2810  		t.Errorf("%s error file did not contain the error %s. "+
  2811  			"Full contents: %s", fileType, expectedErr, buf)
  2812  	}
  2813  }
  2814  
  2815  func TestErrorFile(t *testing.T) {
  2816  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2817  	defer testCleanupDelayer(ctx, t)
  2818  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  2819  	config.SetReporter(libkbfs.NewReporterSimple(config.Clock(), 0))
  2820  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  2821  	mnt, _, cancelFn := makeFS(ctx, t, config)
  2822  	defer mnt.Close()
  2823  	defer cancelFn()
  2824  
  2825  	libfs.AddRootWrapper(config)
  2826  
  2827  	// cause an error by stating a non-existent user
  2828  	_, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName, "janedoe"))
  2829  	if err == nil {
  2830  		t.Fatal("Stat of non-existent user worked!")
  2831  	}
  2832  
  2833  	// Make sure the root error file reads as expected
  2834  	expectedErr := fuse.ENOENT
  2835  
  2836  	// test both the root error file and one in a directory
  2837  	testForErrorText(t, path.Join(mnt.Dir, libfs.ErrorFileName),
  2838  		expectedErr, "root")
  2839  	testForErrorText(t, path.Join(mnt.Dir, PublicName, libfs.ErrorFileName),
  2840  		expectedErr, "root")
  2841  	testForErrorText(t, path.Join(mnt.Dir, PrivateName, libfs.ErrorFileName),
  2842  		expectedErr, "root")
  2843  
  2844  	// Create public and private jdoe TLFs.
  2845  	const b = "hello world"
  2846  	p := path.Join(mnt.Dir, PublicName, "jdoe", "myfile")
  2847  	if err := ioutil.WriteFile(p, []byte(b), 0644); err != nil {
  2848  		t.Fatal(err)
  2849  	}
  2850  	syncFilename(t, p)
  2851  	p = path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  2852  	if err := ioutil.WriteFile(p, []byte(b), 0644); err != nil {
  2853  		t.Fatal(err)
  2854  	}
  2855  	syncFilename(t, p)
  2856  
  2857  	testForErrorText(
  2858  		t, path.Join(mnt.Dir, PublicName, "jdoe", libfs.ErrorFileName),
  2859  		expectedErr, "dir")
  2860  	testForErrorText(
  2861  		t, path.Join(mnt.Dir, PrivateName, "jdoe", libfs.ErrorFileName),
  2862  		expectedErr, "dir")
  2863  }
  2864  
  2865  func TestInvalidateAcrossMounts(t *testing.T) {
  2866  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2867  	defer testCleanupDelayer(ctx, t)
  2868  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  2869  		"user2")
  2870  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  2871  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  2872  	defer mnt1.Close()
  2873  	defer cancelFn1()
  2874  
  2875  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  2876  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  2877  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  2878  	defer mnt2.Close()
  2879  	defer cancelFn2()
  2880  
  2881  	if !mnt2.Conn.Protocol().HasInvalidate() {
  2882  		t.Skip("Old FUSE protocol")
  2883  	}
  2884  
  2885  	// user 1 writes one file to root and one to a sub directory
  2886  	const input1 = "input round one"
  2887  	myfile1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "myfile")
  2888  	if err := ioutil.WriteFile(myfile1, []byte(input1), 0644); err != nil {
  2889  		t.Fatal(err)
  2890  	}
  2891  	syncFilename(t, myfile1)
  2892  	mydir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir")
  2893  	if err := ioutil.Mkdir(mydir1, 0755); err != nil {
  2894  		t.Fatal(err)
  2895  	}
  2896  	mydira1 := path.Join(mydir1, "a")
  2897  	if err := ioutil.WriteFile(mydira1, []byte(input1), 0644); err != nil {
  2898  		t.Fatal(err)
  2899  	}
  2900  	syncFilename(t, mydira1)
  2901  
  2902  	syncFolderToServer(t, "user1,user2", fs2)
  2903  
  2904  	myfile2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "myfile")
  2905  	buf, err := ioutil.ReadFile(myfile2)
  2906  	if err != nil {
  2907  		t.Fatal(err)
  2908  	}
  2909  	if g, e := string(buf), input1; g != e {
  2910  		t.Errorf("wrong content: %q != %q", g, e)
  2911  	}
  2912  
  2913  	mydir2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "mydir")
  2914  	mydira2 := path.Join(mydir2, "a")
  2915  	buf, err = ioutil.ReadFile(mydira2)
  2916  	if err != nil {
  2917  		t.Fatal(err)
  2918  	}
  2919  	if g, e := string(buf), input1; g != e {
  2920  		t.Errorf("wrong content: %q != %q", g, e)
  2921  	}
  2922  
  2923  	// now remove the first file, and rename the second
  2924  	if err := ioutil.Remove(myfile1); err != nil {
  2925  		t.Fatal(err)
  2926  	}
  2927  	mydirb1 := path.Join(mydir1, "b")
  2928  	if err := ioutil.Rename(mydira1, mydirb1); err != nil {
  2929  		t.Fatal(err)
  2930  	}
  2931  	syncAll(t, "user1,user2", tlf.Private, fs1)
  2932  
  2933  	syncFolderToServer(t, "user1,user2", fs2)
  2934  
  2935  	// check everything from user 2's perspective
  2936  	if buf, err := ioutil.ReadFile(myfile2); !ioutil.IsNotExist(err) {
  2937  		t.Fatalf("expected ENOENT: %v: %q", err, buf)
  2938  	}
  2939  	if buf, err := ioutil.ReadFile(mydira2); !ioutil.IsNotExist(err) {
  2940  		t.Fatalf("expected ENOENT: %v: %q", err, buf)
  2941  	}
  2942  
  2943  	checkDir(t, mydir2, map[string]fileInfoCheck{
  2944  		"b": func(fi os.FileInfo) error {
  2945  			return mustBeFileWithSize(fi, int64(len(input1)))
  2946  		},
  2947  	})
  2948  
  2949  	mydirb2 := path.Join(mydir2, "b")
  2950  	buf, err = ioutil.ReadFile(mydirb2)
  2951  	if err != nil {
  2952  		t.Fatal(err)
  2953  	}
  2954  	if g, e := string(buf), input1; g != e {
  2955  		t.Errorf("wrong content: %q != %q", g, e)
  2956  	}
  2957  }
  2958  
  2959  func TestInvalidateAppendAcrossMounts(t *testing.T) {
  2960  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  2961  	defer testCleanupDelayer(ctx, t)
  2962  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  2963  		"user2")
  2964  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  2965  	mnt1, _, cancelFn1 := makeFS(ctx, t, config1)
  2966  	defer mnt1.Close()
  2967  	defer cancelFn1()
  2968  
  2969  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  2970  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  2971  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  2972  	defer mnt2.Close()
  2973  	defer cancelFn2()
  2974  
  2975  	if !mnt2.Conn.Protocol().HasInvalidate() {
  2976  		t.Skip("Old FUSE protocol")
  2977  	}
  2978  
  2979  	// user 1 writes one file to root and one to a sub directory
  2980  	const input1 = "input round one"
  2981  	myfile1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "myfile")
  2982  	if err := ioutil.WriteFile(myfile1, []byte(input1), 0644); err != nil {
  2983  		t.Fatal(err)
  2984  	}
  2985  	syncFilename(t, myfile1)
  2986  	syncFolderToServer(t, "user1,user2", fs2)
  2987  	myfile2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "myfile")
  2988  	buf, err := ioutil.ReadFile(myfile2)
  2989  	if err != nil {
  2990  		t.Fatal(err)
  2991  	}
  2992  	if g, e := string(buf), input1; g != e {
  2993  		t.Errorf("wrong content: %q != %q", g, e)
  2994  	}
  2995  
  2996  	// user 1 append using libkbfs, to ensure that it doesn't flush
  2997  	// the whole page.
  2998  	const input2 = "input round two"
  2999  	{
  3000  		ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3001  		defer testCleanupDelayer(ctx, t)
  3002  
  3003  		jdoe := libkbfs.GetRootNodeOrBust(ctx, t, config1, "user1,user2", tlf.Private)
  3004  
  3005  		ops := config1.KBFSOps()
  3006  		myfile, _, err := ops.Lookup(ctx, jdoe, jdoe.ChildName("myfile"))
  3007  		if err != nil {
  3008  			t.Fatal(err)
  3009  		}
  3010  		if err := ops.Write(
  3011  			ctx, myfile, []byte(input2), int64(len(input1))); err != nil {
  3012  			t.Fatal(err)
  3013  		}
  3014  		if err := ops.SyncAll(ctx, myfile.GetFolderBranch()); err != nil {
  3015  			t.Fatal(err)
  3016  		}
  3017  	}
  3018  
  3019  	syncFolderToServer(t, "user1,user2", fs2)
  3020  
  3021  	// check everything from user 2's perspective
  3022  	buf, err = ioutil.ReadFile(myfile2)
  3023  	if err != nil {
  3024  		t.Fatal(err)
  3025  	}
  3026  	if g, e := string(buf), input1+input2; g != e {
  3027  		t.Errorf("wrong content: %q != %q", g, e)
  3028  	}
  3029  }
  3030  
  3031  func TestInvalidateRenameToUncachedDir(t *testing.T) {
  3032  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3033  	defer testCleanupDelayer(ctx, t)
  3034  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  3035  		"user2")
  3036  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3037  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  3038  	defer mnt1.Close()
  3039  	defer cancelFn1()
  3040  
  3041  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3042  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3043  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3044  	defer mnt2.Close()
  3045  	defer cancelFn2()
  3046  
  3047  	if !mnt2.Conn.Protocol().HasInvalidate() {
  3048  		t.Skip("Old FUSE protocol")
  3049  	}
  3050  
  3051  	// user 1 writes one file to root and one to a sub directory
  3052  	const input1 = "input round one"
  3053  	myfile1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "myfile")
  3054  	if err := ioutil.WriteFile(myfile1, []byte(input1), 0644); err != nil {
  3055  		t.Fatal(err)
  3056  	}
  3057  	syncFilename(t, myfile1)
  3058  	mydir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir")
  3059  	if err := ioutil.Mkdir(mydir1, 0755); err != nil {
  3060  		t.Fatal(err)
  3061  	}
  3062  	mydirfile1 := path.Join(mydir1, "myfile")
  3063  
  3064  	syncFolderToServer(t, "user1,user2", fs2)
  3065  	myfile2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "myfile")
  3066  	f, err := os.OpenFile(myfile2, os.O_RDWR, 0644)
  3067  	if err != nil {
  3068  		t.Fatal(err)
  3069  	}
  3070  	// Call in a closure since `f` is overridden below.
  3071  	defer func() { syncAndClose(t, f) }()
  3072  
  3073  	{
  3074  		buf := make([]byte, 4096)
  3075  		n, err := f.ReadAt(buf, 0)
  3076  		if err != nil && err != io.EOF {
  3077  			t.Fatal(err)
  3078  		}
  3079  		if g, e := string(buf[:n]), input1; g != e {
  3080  			t.Errorf("wrong content: %q != %q", g, e)
  3081  		}
  3082  	}
  3083  
  3084  	// now rename the second into a directory that user 2 hasn't seen
  3085  	if err := ioutil.Rename(myfile1, mydirfile1); err != nil {
  3086  		t.Fatal(err)
  3087  	}
  3088  	syncAll(t, "user1,user2", tlf.Private, fs1)
  3089  
  3090  	syncFolderToServer(t, "user1,user2", fs2)
  3091  
  3092  	// user 2 should be able to write to its open file, and user 1
  3093  	// will see the change
  3094  	const input2 = "input round two"
  3095  	{
  3096  		n, err := f.WriteAt([]byte(input2), 0)
  3097  		if err != nil || n != len(input2) {
  3098  			t.Fatal(err)
  3099  		}
  3100  	}
  3101  	syncAndClose(t, f)
  3102  	f = nil
  3103  
  3104  	syncFolderToServer(t, "user1,user2", fs1)
  3105  
  3106  	buf, err := ioutil.ReadFile(mydirfile1)
  3107  	if err != nil {
  3108  		t.Fatal(err)
  3109  	}
  3110  	if g, e := string(buf), input2; g != e {
  3111  		t.Errorf("wrong content: %q != %q", g, e)
  3112  	}
  3113  }
  3114  
  3115  func TestStatusFile(t *testing.T) {
  3116  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3117  	defer testCleanupDelayer(ctx, t)
  3118  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  3119  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  3120  	mnt, _, cancelFn := makeFS(ctx, t, config)
  3121  	defer mnt.Close()
  3122  	defer cancelFn()
  3123  
  3124  	libfs.AddRootWrapper(config)
  3125  
  3126  	jdoe := libkbfs.GetRootNodeOrBust(ctx, t, config, "jdoe", tlf.Public)
  3127  	mydir := path.Join(mnt.Dir, PublicName, "jdoe", "mydir")
  3128  	err := ioutil.Mkdir(mydir, 0755)
  3129  	require.NoError(t, err)
  3130  
  3131  	ops := config.KBFSOps()
  3132  	status, _, err := ops.FolderStatus(ctx, jdoe.GetFolderBranch())
  3133  	require.NoError(t, err)
  3134  
  3135  	checkStatus := func(dir string) {
  3136  		// Simply make sure the status in the file matches what we'd
  3137  		// expect.  Checking the exact content should be left for tests
  3138  		// within libkbfs.
  3139  		buf, err := ioutil.ReadFile(path.Join(dir, libfs.StatusFileName))
  3140  		require.NoError(t, err)
  3141  
  3142  		var bufStatus libkbfs.FolderBranchStatus
  3143  		err = json.Unmarshal(buf, &bufStatus)
  3144  		require.NoError(t, err)
  3145  
  3146  		// Use a fuzzy check on the timestamps, since it could include
  3147  		// monotonic clock stuff.
  3148  		require.True(t, timeEqualFuzzy(
  3149  			status.LocalTimestamp, bufStatus.LocalTimestamp, time.Millisecond))
  3150  		status.LocalTimestamp = bufStatus.LocalTimestamp
  3151  
  3152  		// It's safe to compare the path slices with DeepEqual since
  3153  		// they will all be null for this test (nothing is dirtied).
  3154  		require.True(t, reflect.DeepEqual(status, bufStatus))
  3155  	}
  3156  	checkStatus(path.Join(mnt.Dir, PublicName, "jdoe"))
  3157  	checkStatus(mydir)
  3158  }
  3159  
  3160  // TODO: remove once we have automatic conflict resolution tests
  3161  func TestUnstageFile(t *testing.T) {
  3162  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3163  	defer testCleanupDelayer(ctx, t)
  3164  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  3165  		"user2")
  3166  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3167  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  3168  	defer mnt1.Close()
  3169  	defer cancelFn1()
  3170  
  3171  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3172  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3173  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3174  	defer mnt2.Close()
  3175  	defer cancelFn2()
  3176  
  3177  	if !mnt2.Conn.Protocol().HasInvalidate() {
  3178  		t.Skip("Old FUSE protocol")
  3179  	}
  3180  
  3181  	// both users read the root dir first
  3182  	myroot1 := path.Join(mnt1.Dir, PrivateName, "user1,user2")
  3183  	myroot2 := path.Join(mnt2.Dir, PrivateName, "user1,user2")
  3184  	checkDir(t, myroot1, map[string]fileInfoCheck{})
  3185  	checkDir(t, myroot2, map[string]fileInfoCheck{})
  3186  
  3187  	// turn updates off for user 2
  3188  	rootNode2 := libkbfs.GetRootNodeOrBust(ctx, t, config2, "user1,user2", tlf.Private)
  3189  	_, err := libkbfs.DisableUpdatesForTesting(config2,
  3190  		rootNode2.GetFolderBranch())
  3191  	if err != nil {
  3192  		t.Fatalf("Couldn't pause user 2 updates")
  3193  	}
  3194  	err = libkbfs.DisableCRForTesting(config2, rootNode2.GetFolderBranch())
  3195  	if err != nil {
  3196  		t.Fatalf("Couldn't disable user 2 CR")
  3197  	}
  3198  
  3199  	// user1 writes a file and makes a few directories
  3200  	const input1 = "input round one"
  3201  	myfile1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "myfile")
  3202  	if err := ioutil.WriteFile(myfile1, []byte(input1), 0644); err != nil {
  3203  		t.Fatal(err)
  3204  	}
  3205  	syncFilename(t, myfile1)
  3206  	mydir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir")
  3207  	if err := ioutil.Mkdir(mydir1, 0755); err != nil {
  3208  		t.Fatal(err)
  3209  	}
  3210  	mysubdir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir",
  3211  		"mysubdir")
  3212  	if err := ioutil.Mkdir(mysubdir1, 0755); err != nil {
  3213  		t.Fatal(err)
  3214  	}
  3215  	syncAll(t, "user1,user2", tlf.Private, fs1)
  3216  
  3217  	// user2 does similar
  3218  	const input2 = "input round two"
  3219  	myfile2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "myfile")
  3220  	if err := ioutil.WriteFile(myfile2, []byte(input2), 0644); err != nil {
  3221  		t.Fatal(err)
  3222  	}
  3223  	syncFilename(t, myfile2)
  3224  	mydir2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "mydir")
  3225  	if err := ioutil.Mkdir(mydir2, 0755); err != nil {
  3226  		t.Fatal(err)
  3227  	}
  3228  	myothersubdir2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "mydir",
  3229  		"myothersubdir")
  3230  	if err := ioutil.Mkdir(myothersubdir2, 0755); err != nil {
  3231  		t.Fatal(err)
  3232  	}
  3233  	syncAll(t, "user1,user2", tlf.Private, fs2)
  3234  
  3235  	// verify that they don't see each other's files
  3236  	checkDir(t, mydir1, map[string]fileInfoCheck{
  3237  		"mysubdir": mustBeDir,
  3238  	})
  3239  	checkDir(t, mydir2, map[string]fileInfoCheck{
  3240  		"myothersubdir": mustBeDir,
  3241  	})
  3242  
  3243  	// now unstage user 2 and they should see the same stuff
  3244  	unstageFile2 := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3245  		libfs.UnstageFileName)
  3246  	if err := ioutil.WriteFile(unstageFile2, []byte{1}, 0222); err != nil {
  3247  		t.Fatal(err)
  3248  	}
  3249  
  3250  	syncFolderToServer(t, "user1,user2", fs2)
  3251  
  3252  	// They should see identical folders now
  3253  	checkDir(t, mydir1, map[string]fileInfoCheck{
  3254  		"mysubdir": mustBeDir,
  3255  	})
  3256  	checkDir(t, mydir2, map[string]fileInfoCheck{
  3257  		"mysubdir": mustBeDir,
  3258  	})
  3259  
  3260  	buf, err := ioutil.ReadFile(myfile1)
  3261  	if err != nil {
  3262  		t.Fatal(err)
  3263  	}
  3264  	if g, e := string(buf), input1; g != e {
  3265  		t.Errorf("wrong content: %q != %q", g, e)
  3266  	}
  3267  	buf, err = ioutil.ReadFile(myfile2)
  3268  	if err != nil {
  3269  		t.Fatal(err)
  3270  	}
  3271  	if g, e := string(buf), input1; g != e {
  3272  		t.Errorf("wrong content: %q != %q", g, e)
  3273  	}
  3274  }
  3275  
  3276  func TestSimpleCRNoConflict(t *testing.T) {
  3277  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3278  	defer testCleanupDelayer(ctx, t)
  3279  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  3280  		"user2")
  3281  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  3282  	defer mnt1.Close()
  3283  	defer cancelFn1()
  3284  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3285  
  3286  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3287  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3288  	defer mnt2.Close()
  3289  	defer cancelFn2()
  3290  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3291  
  3292  	if !mnt2.Conn.Protocol().HasInvalidate() {
  3293  		t.Skip("Old FUSE protocol")
  3294  	}
  3295  
  3296  	root1 := path.Join(mnt1.Dir, PrivateName, "user1,user2")
  3297  	root2 := path.Join(mnt2.Dir, PrivateName, "user1,user2")
  3298  	// Please create TLF here first
  3299  	d1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "D")
  3300  	d2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "E")
  3301  	if err := ioutil.Mkdir(d1, 0755); err != nil {
  3302  		t.Fatal("Mkdir failed")
  3303  	}
  3304  	syncAll(t, "user1,user2", tlf.Private, fs1)
  3305  	syncFolderToServer(t, "user1,user2", fs2)
  3306  	if err := ioutil.Mkdir(d2, 0755); err != nil {
  3307  		t.Fatal("Mkdir failed")
  3308  	}
  3309  	syncAll(t, "user1,user2", tlf.Private, fs2)
  3310  	syncFolderToServer(t, "user1,user2", fs1)
  3311  
  3312  	// disable updates for user 2
  3313  	disableUpdatesFile := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3314  		libfs.DisableUpdatesFileName)
  3315  	if err := ioutil.WriteFile(disableUpdatesFile,
  3316  		[]byte("off"), 0644); err != nil {
  3317  		t.Fatal(err)
  3318  	}
  3319  
  3320  	// user1 writes a file and makes a few directories
  3321  	const input1 = "input round one"
  3322  	file1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "file1")
  3323  	if err := ioutil.WriteFile(file1, []byte(input1), 0644); err != nil {
  3324  		t.Fatal(err)
  3325  	}
  3326  	syncFilename(t, file1)
  3327  	dir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "dir")
  3328  	if err := ioutil.Mkdir(dir1, 0755); err != nil {
  3329  		t.Fatal(err)
  3330  	}
  3331  	subdir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "dir", "subdir1")
  3332  	if err := ioutil.Mkdir(subdir1, 0755); err != nil {
  3333  		t.Fatal(err)
  3334  	}
  3335  	syncAll(t, "user1,user2", tlf.Private, fs1)
  3336  
  3337  	// user2 does similar
  3338  	const input2 = "input round two two two"
  3339  	file2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "file2")
  3340  	if err := ioutil.WriteFile(file2, []byte(input2), 0644); err != nil {
  3341  		t.Fatal(err)
  3342  	}
  3343  	syncFilename(t, file2)
  3344  	dir2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "dir")
  3345  	if err := ioutil.Mkdir(dir2, 0755); err != nil {
  3346  		t.Fatal(err)
  3347  	}
  3348  	subdir2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "dir", "subdir2")
  3349  	if err := ioutil.Mkdir(subdir2, 0755); err != nil {
  3350  		t.Fatal(err)
  3351  	}
  3352  	syncAll(t, "user1,user2", tlf.Private, fs2)
  3353  
  3354  	// verify that they don't see each other's files
  3355  	checkDir(t, root1, map[string]fileInfoCheck{
  3356  		"file1": func(fi os.FileInfo) error {
  3357  			return mustBeFileWithSize(fi, int64(len(input1)))
  3358  		},
  3359  		"dir": mustBeDir,
  3360  		"D":   mustBeDir,
  3361  		"E":   mustBeDir,
  3362  	})
  3363  	checkDir(t, dir1, map[string]fileInfoCheck{
  3364  		"subdir1": mustBeDir,
  3365  	})
  3366  	checkDir(t, root2, map[string]fileInfoCheck{
  3367  		"file2": func(fi os.FileInfo) error {
  3368  			return mustBeFileWithSize(fi, int64(len(input2)))
  3369  		},
  3370  		"dir": mustBeDir,
  3371  		"D":   mustBeDir,
  3372  		"E":   mustBeDir,
  3373  	})
  3374  	checkDir(t, dir2, map[string]fileInfoCheck{
  3375  		"subdir2": mustBeDir,
  3376  	})
  3377  
  3378  	// now re-enable user 2 updates and CR, and the merge should happen
  3379  	enableUpdatesFile := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3380  		libfs.EnableUpdatesFileName)
  3381  	if err := ioutil.WriteFile(enableUpdatesFile,
  3382  		[]byte("on"), 0644); err != nil {
  3383  		t.Fatal(err)
  3384  	}
  3385  
  3386  	syncFolderToServer(t, "user1,user2", fs2)
  3387  	syncFolderToServer(t, "user1,user2", fs1)
  3388  
  3389  	// They should see identical folders now (conflict-free merge)
  3390  	checkDir(t, root1, map[string]fileInfoCheck{
  3391  		"file1": func(fi os.FileInfo) error {
  3392  			return mustBeFileWithSize(fi, int64(len(input1)))
  3393  		},
  3394  		"file2": func(fi os.FileInfo) error {
  3395  			return mustBeFileWithSize(fi, int64(len(input2)))
  3396  		},
  3397  		"dir": mustBeDir,
  3398  		"D":   mustBeDir,
  3399  		"E":   mustBeDir,
  3400  	})
  3401  	checkDir(t, dir1, map[string]fileInfoCheck{
  3402  		"subdir1": mustBeDir,
  3403  		"subdir2": mustBeDir,
  3404  	})
  3405  	checkDir(t, root2, map[string]fileInfoCheck{
  3406  		"file1": func(fi os.FileInfo) error {
  3407  			return mustBeFileWithSize(fi, int64(len(input1)))
  3408  		},
  3409  		"file2": func(fi os.FileInfo) error {
  3410  			return mustBeFileWithSize(fi, int64(len(input2)))
  3411  		},
  3412  		"dir": mustBeDir,
  3413  		"D":   mustBeDir,
  3414  		"E":   mustBeDir,
  3415  	})
  3416  	checkDir(t, dir2, map[string]fileInfoCheck{
  3417  		"subdir1": mustBeDir,
  3418  		"subdir2": mustBeDir,
  3419  	})
  3420  
  3421  	buf, err := ioutil.ReadFile(file1)
  3422  	if err != nil {
  3423  		t.Fatal(err)
  3424  	}
  3425  	if g, e := string(buf), input1; g != e {
  3426  		t.Errorf("wrong content: %q != %q", g, e)
  3427  	}
  3428  	file2u1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "file2")
  3429  	buf, err = ioutil.ReadFile(file2u1)
  3430  	if err != nil {
  3431  		t.Fatal(err)
  3432  	}
  3433  	if g, e := string(buf), input2; g != e {
  3434  		t.Errorf("wrong content: %q != %q", g, e)
  3435  	}
  3436  
  3437  	file1u2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "file1")
  3438  	buf, err = ioutil.ReadFile(file1u2)
  3439  	if err != nil {
  3440  		t.Fatal(err)
  3441  	}
  3442  	if g, e := string(buf), input1; g != e {
  3443  		t.Errorf("wrong content: %q != %q", g, e)
  3444  	}
  3445  	buf, err = ioutil.ReadFile(file2)
  3446  	if err != nil {
  3447  		t.Fatal(err)
  3448  	}
  3449  	if g, e := string(buf), input2; g != e {
  3450  		t.Errorf("wrong content: %q != %q", g, e)
  3451  	}
  3452  }
  3453  
  3454  func TestSimpleCRConflictOnOpenFiles(t *testing.T) {
  3455  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3456  	defer testCleanupDelayer(ctx, t)
  3457  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  3458  		"user2")
  3459  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  3460  	defer mnt1.Close()
  3461  	defer cancelFn1()
  3462  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3463  
  3464  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3465  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3466  	defer mnt2.Close()
  3467  	defer cancelFn2()
  3468  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3469  
  3470  	if !mnt2.Conn.Protocol().HasInvalidate() {
  3471  		t.Skip("Old FUSE protocol")
  3472  	}
  3473  
  3474  	now := time.Now()
  3475  	var clock clocktest.TestClock
  3476  	clock.Set(now)
  3477  	config2.SetClock(&clock)
  3478  
  3479  	root1 := path.Join(mnt1.Dir, PrivateName, "user1,user2")
  3480  	root2 := path.Join(mnt2.Dir, PrivateName, "user1,user2")
  3481  
  3482  	// both users should mutate the dir first
  3483  	d1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "D")
  3484  	d2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "E")
  3485  	if err := ioutil.Mkdir(d1, 0755); err != nil {
  3486  		t.Fatal("Mkdir failed")
  3487  	}
  3488  	syncFolderToServer(t, "user1,user2", fs2)
  3489  	if err := ioutil.Mkdir(d2, 0755); err != nil {
  3490  		t.Fatal("Mkdir failed")
  3491  	}
  3492  	syncFolderToServer(t, "user1,user2", fs1)
  3493  
  3494  	// disable updates for user 2
  3495  	disableUpdatesFile := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3496  		libfs.DisableUpdatesFileName)
  3497  	if err := ioutil.WriteFile(disableUpdatesFile,
  3498  		[]byte("off"), 0644); err != nil {
  3499  		t.Fatal(err)
  3500  	}
  3501  
  3502  	// user1 creates and writes a file
  3503  	file1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "f")
  3504  	f1, err := os.Create(file1)
  3505  	if err != nil {
  3506  		t.Fatal(err)
  3507  	}
  3508  	defer syncAndClose(t, f1)
  3509  
  3510  	const input1 = "hello"
  3511  	{
  3512  		n, err := f1.WriteAt([]byte(input1), 0)
  3513  		if err != nil || n != len(input1) {
  3514  			t.Fatal(err)
  3515  		}
  3516  		if err := f1.Sync(); err != nil {
  3517  			t.Fatal(err)
  3518  		}
  3519  	}
  3520  
  3521  	// user2 creates and writes a file
  3522  	file2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "f")
  3523  	f2, err := os.Create(file2)
  3524  	if err != nil {
  3525  		t.Fatal(err)
  3526  	}
  3527  	defer syncAndClose(t, f2)
  3528  
  3529  	const input2 = "ohell"
  3530  	{
  3531  		n, err := f2.WriteAt([]byte(input2), 0)
  3532  		if err != nil || n != len(input2) {
  3533  			t.Fatal(err)
  3534  		}
  3535  		if err := f2.Sync(); err != nil {
  3536  			t.Fatal(err)
  3537  		}
  3538  	}
  3539  
  3540  	// now re-enable user 2 updates and CR, and the merge should happen
  3541  	enableUpdatesFile := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3542  		libfs.EnableUpdatesFileName)
  3543  	if err := ioutil.WriteFile(enableUpdatesFile,
  3544  		[]byte("on"), 0644); err != nil {
  3545  		t.Fatal(err)
  3546  	}
  3547  
  3548  	syncFolderToServer(t, "user1,user2", fs2)
  3549  	syncFolderToServer(t, "user1,user2", fs1)
  3550  
  3551  	// They should both be able to read their past writes.
  3552  	{
  3553  		buf := make([]byte, len(input1))
  3554  		n, err := f1.ReadAt(buf, 0)
  3555  		if err != nil || n != len(input1) {
  3556  			t.Fatal(err)
  3557  		}
  3558  		if g, e := string(buf), input1; g != e {
  3559  			t.Errorf("Unexpected read on f2: %s vs %s", g, e)
  3560  		}
  3561  	}
  3562  	{
  3563  		buf := make([]byte, len(input2))
  3564  		n, err := f2.ReadAt(buf, 0)
  3565  		if err != nil || n != len(input2) {
  3566  			t.Fatal(err)
  3567  		}
  3568  		if g, e := string(buf), input2; g != e {
  3569  			t.Errorf("Unexpected read on f2: %s vs %s", g, e)
  3570  		}
  3571  	}
  3572  
  3573  	// They should see the conflict.
  3574  	cre := libkbfs.WriterDeviceDateConflictRenamer{}
  3575  	checkDir(t, root1, map[string]fileInfoCheck{
  3576  		"f": func(fi os.FileInfo) error {
  3577  			return mustBeFileWithSize(fi, int64(len(input1)))
  3578  		},
  3579  		cre.ConflictRenameHelper(now, "user2", "dev1", "f"): func(fi os.FileInfo) error {
  3580  			return mustBeFileWithSize(fi, int64(len(input2)))
  3581  		},
  3582  		"D": mustBeDir,
  3583  		"E": mustBeDir,
  3584  	})
  3585  	checkDir(t, root2, map[string]fileInfoCheck{
  3586  		"f": func(fi os.FileInfo) error {
  3587  			return mustBeFileWithSize(fi, int64(len(input1)))
  3588  		},
  3589  		cre.ConflictRenameHelper(now, "user2", "dev1", "f"): func(fi os.FileInfo) error {
  3590  			return mustBeFileWithSize(fi, int64(len(input2)))
  3591  		},
  3592  		"D": mustBeDir,
  3593  		"E": mustBeDir,
  3594  	})
  3595  
  3596  	input3 := " world"
  3597  	{
  3598  		n, err := f1.WriteAt([]byte(input3), int64(len(input1)))
  3599  		if err != nil || n != len(input3) {
  3600  			t.Fatal(err)
  3601  		}
  3602  		if err := f1.Sync(); err != nil {
  3603  			t.Fatal(err)
  3604  		}
  3605  	}
  3606  
  3607  	syncFolderToServer(t, "user1,user2", fs2)
  3608  
  3609  	input4 := " dlrow"
  3610  	{
  3611  		n, err := f2.WriteAt([]byte(input4), int64(len(input2)))
  3612  		if err != nil || n != len(input4) {
  3613  			t.Fatal(err)
  3614  		}
  3615  		if err := f2.Sync(); err != nil {
  3616  			t.Fatal(err)
  3617  		}
  3618  	}
  3619  
  3620  	syncFolderToServer(t, "user1,user2", fs1)
  3621  
  3622  	buf, err := ioutil.ReadFile(file1)
  3623  	if err != nil {
  3624  		t.Fatal(err)
  3625  	}
  3626  	if g, e := string(buf), input1+input3; g != e {
  3627  		t.Errorf("wrong content: %q != %q", g, e)
  3628  	}
  3629  	buf, err = ioutil.ReadFile(file2)
  3630  	if err != nil {
  3631  		t.Fatal(err)
  3632  	}
  3633  	if g, e := string(buf), input1+input3; g != e {
  3634  		t.Errorf("wrong content: %q != %q", g, e)
  3635  	}
  3636  
  3637  	filec1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", cre.ConflictRenameHelper(now, "user2", "dev1", "f"))
  3638  	filec2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", cre.ConflictRenameHelper(now, "user2", "dev1", "f"))
  3639  	buf, err = ioutil.ReadFile(filec1)
  3640  	if err != nil {
  3641  		t.Fatal(err)
  3642  	}
  3643  	if g, e := string(buf), input2+input4; g != e {
  3644  		t.Errorf("wrong content: %q != %q", g, e)
  3645  	}
  3646  	buf, err = ioutil.ReadFile(filec2)
  3647  	if err != nil {
  3648  		t.Fatal(err)
  3649  	}
  3650  	if g, e := string(buf), input2+input4; g != e {
  3651  		t.Errorf("wrong content: %q != %q", g, e)
  3652  	}
  3653  }
  3654  
  3655  func TestSimpleCRConflictOnOpenMergedFile(t *testing.T) {
  3656  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3657  	defer testCleanupDelayer(ctx, t)
  3658  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1",
  3659  		"user2")
  3660  	mnt1, fs1, cancelFn1 := makeFS(ctx, t, config1)
  3661  	defer mnt1.Close()
  3662  	defer cancelFn1()
  3663  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3664  
  3665  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3666  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3667  	defer mnt2.Close()
  3668  	defer cancelFn2()
  3669  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3670  
  3671  	if !mnt2.Conn.Protocol().HasInvalidate() {
  3672  		t.Skip("Old FUSE protocol")
  3673  	}
  3674  
  3675  	now := time.Now()
  3676  	var clock clocktest.TestClock
  3677  	clock.Set(now)
  3678  	config2.SetClock(&clock)
  3679  
  3680  	root1 := path.Join(mnt1.Dir, PrivateName, "user1,user2")
  3681  	root2 := path.Join(mnt2.Dir, PrivateName, "user1,user2")
  3682  	// both users should mutate the dir first
  3683  	d1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "D")
  3684  	d2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "E")
  3685  	if err := ioutil.Mkdir(d1, 0755); err != nil {
  3686  		t.Fatal("Mkdir failed")
  3687  	}
  3688  	syncFolderToServer(t, "user1,user2", fs2)
  3689  	if err := ioutil.Mkdir(d2, 0755); err != nil {
  3690  		t.Fatal("Mkdir failed")
  3691  	}
  3692  	syncFolderToServer(t, "user1,user2", fs1)
  3693  
  3694  	// disable updates for user 2
  3695  	disableUpdatesFile := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3696  		libfs.DisableUpdatesFileName)
  3697  	if err := ioutil.WriteFile(disableUpdatesFile,
  3698  		[]byte("off"), 0644); err != nil {
  3699  		t.Fatal(err)
  3700  	}
  3701  
  3702  	// user1 creates and writes a file
  3703  	file1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "f")
  3704  	f1, err := os.Create(file1)
  3705  	if err != nil {
  3706  		t.Fatal(err)
  3707  	}
  3708  	defer syncAndClose(t, f1)
  3709  
  3710  	const input1 = "hello"
  3711  	{
  3712  		n, err := f1.WriteAt([]byte(input1), 0)
  3713  		if err != nil || n != len(input1) {
  3714  			t.Fatal(err)
  3715  		}
  3716  		if err := f1.Sync(); err != nil {
  3717  			t.Fatal(err)
  3718  		}
  3719  	}
  3720  
  3721  	// user2 creates a directory and writes a file to it
  3722  	dir2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "f")
  3723  	if err := ioutil.Mkdir(dir2, 0755); err != nil {
  3724  		t.Fatal(err)
  3725  	}
  3726  	file2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "f", "foo")
  3727  	f2, err := os.Create(file2)
  3728  	if err != nil {
  3729  		t.Fatal(err)
  3730  	}
  3731  	defer syncAndClose(t, f2)
  3732  
  3733  	const input2 = "ohell"
  3734  	{
  3735  		n, err := f2.WriteAt([]byte(input2), 0)
  3736  		if err != nil || n != len(input2) {
  3737  			t.Fatal(err)
  3738  		}
  3739  		if err := f2.Sync(); err != nil {
  3740  			t.Fatal(err)
  3741  		}
  3742  	}
  3743  
  3744  	// now re-enable user 2 updates and CR, and the merge should happen
  3745  	enableUpdatesFile := path.Join(mnt2.Dir, PrivateName, "user1,user2",
  3746  		libfs.EnableUpdatesFileName)
  3747  	if err := ioutil.WriteFile(enableUpdatesFile,
  3748  		[]byte("on"), 0644); err != nil {
  3749  		t.Fatal(err)
  3750  	}
  3751  
  3752  	syncFolderToServer(t, "user1,user2", fs2)
  3753  	syncFolderToServer(t, "user1,user2", fs1)
  3754  
  3755  	// They should both be able to read their past writes.
  3756  	{
  3757  		buf := make([]byte, len(input1))
  3758  		n, err := f1.ReadAt(buf, 0)
  3759  		if err != nil || n != len(input1) {
  3760  			t.Fatal(err)
  3761  		}
  3762  		if g, e := string(buf), input1; g != e {
  3763  			t.Errorf("Unexpected read on f2: %s vs %s", g, e)
  3764  		}
  3765  	}
  3766  	{
  3767  		buf := make([]byte, len(input2))
  3768  		n, err := f2.ReadAt(buf, 0)
  3769  		if err != nil || n != len(input2) {
  3770  			t.Fatal(err)
  3771  		}
  3772  		if g, e := string(buf), input2; g != e {
  3773  			t.Errorf("Unexpected read on f2: %s vs %s", g, e)
  3774  		}
  3775  	}
  3776  
  3777  	// They should see the conflict.
  3778  	cre := libkbfs.WriterDeviceDateConflictRenamer{}
  3779  	fcr := cre.ConflictRenameHelper(now, "user1", "dev1", "f")
  3780  	checkDir(t, root1, map[string]fileInfoCheck{
  3781  		fcr: func(fi os.FileInfo) error {
  3782  			return mustBeFileWithSize(fi, int64(len(input1)))
  3783  		},
  3784  		"f": mustBeDir,
  3785  		"D": mustBeDir,
  3786  		"E": mustBeDir,
  3787  	})
  3788  	checkDir(t, root2, map[string]fileInfoCheck{
  3789  		fcr: func(fi os.FileInfo) error {
  3790  			return mustBeFileWithSize(fi, int64(len(input1)))
  3791  		},
  3792  		"f": mustBeDir,
  3793  		"D": mustBeDir,
  3794  		"E": mustBeDir,
  3795  	})
  3796  
  3797  	input3 := " world"
  3798  	{
  3799  		n, err := f1.WriteAt([]byte(input3), int64(len(input1)))
  3800  		if err != nil || n != len(input3) {
  3801  			t.Fatal(err)
  3802  		}
  3803  		if err := f1.Sync(); err != nil {
  3804  			t.Fatal(err)
  3805  		}
  3806  	}
  3807  
  3808  	syncFolderToServer(t, "user1,user2", fs2)
  3809  
  3810  	input4 := " dlrow"
  3811  	{
  3812  		n, err := f2.WriteAt([]byte(input4), int64(len(input2)))
  3813  		if err != nil || n != len(input4) {
  3814  			t.Fatal(err)
  3815  		}
  3816  		if err := f2.Sync(); err != nil {
  3817  			t.Fatal(err)
  3818  		}
  3819  	}
  3820  
  3821  	syncFolderToServer(t, "user1,user2", fs1)
  3822  
  3823  	file2u1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "f", "foo")
  3824  	buf, err := ioutil.ReadFile(file2u1)
  3825  	if err != nil {
  3826  		t.Fatal(err)
  3827  	}
  3828  	if g, e := string(buf), input2+input4; g != e {
  3829  		t.Errorf("wrong content: %q != %q", g, e)
  3830  	}
  3831  	buf, err = ioutil.ReadFile(file2)
  3832  	if err != nil {
  3833  		t.Fatal(err)
  3834  	}
  3835  	if g, e := string(buf), input2+input4; g != e {
  3836  		t.Errorf("wrong content: %q != %q", g, e)
  3837  	}
  3838  
  3839  	filec1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", fcr)
  3840  	filec2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", fcr)
  3841  	buf, err = ioutil.ReadFile(filec1)
  3842  	if err != nil {
  3843  		t.Fatal(err)
  3844  	}
  3845  	if g, e := string(buf), input1+input3; g != e {
  3846  		t.Errorf("wrong content: %q != %q", g, e)
  3847  	}
  3848  	buf, err = ioutil.ReadFile(filec2)
  3849  	if err != nil {
  3850  		t.Fatal(err)
  3851  	}
  3852  	if g, e := string(buf), input1+input3; g != e {
  3853  		t.Errorf("wrong content: %q != %q", g, e)
  3854  	}
  3855  }
  3856  
  3857  func TestKbfsFileInfo(t *testing.T) {
  3858  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3859  	defer testCleanupDelayer(ctx, t)
  3860  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1", "user2")
  3861  	mnt1, _, cancelFn1 := makeFS(ctx, t, config1)
  3862  	defer mnt1.Close()
  3863  	defer cancelFn1()
  3864  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3865  
  3866  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3867  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3868  	defer mnt2.Close()
  3869  	defer cancelFn2()
  3870  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3871  
  3872  	// Turn off the prefetcher to avoid races when reading the file info file.
  3873  	ch := config2.BlockOps().TogglePrefetcher(false)
  3874  	select {
  3875  	case <-ch:
  3876  	case <-ctx.Done():
  3877  		t.Fatal(ctx.Err())
  3878  	}
  3879  
  3880  	mydir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir")
  3881  	if err := ioutil.Mkdir(mydir1, 0755); err != nil {
  3882  		t.Fatal(err)
  3883  	}
  3884  	myfile1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir", "myfile")
  3885  	if err := ioutil.WriteFile(myfile1, []byte("foo"), 0644); err != nil {
  3886  		t.Fatal(err)
  3887  	}
  3888  	syncFilename(t, myfile1)
  3889  	syncFolderToServer(t, "user1,user2", fs2)
  3890  	fi2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "mydir", libfs.FileInfoPrefix+"myfile")
  3891  	bs, err := ioutil.ReadFile(fi2)
  3892  	if err != nil {
  3893  		t.Fatal(err)
  3894  	}
  3895  	var dst libkbfs.NodeMetadata
  3896  	err = json.Unmarshal(bs, &dst)
  3897  	if err != nil {
  3898  		t.Fatal(err)
  3899  	}
  3900  	if dst.LastWriterUnverified != kbname.NormalizedUsername("user1") {
  3901  		t.Fatalf("Expected user1, %v raw %X", dst, bs)
  3902  	}
  3903  }
  3904  
  3905  func TestDirSyncAll(t *testing.T) {
  3906  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3907  	defer testCleanupDelayer(ctx, t)
  3908  	config1 := libkbfs.MakeTestConfigOrBust(t, "user1", "user2")
  3909  	mnt1, _, cancelFn1 := makeFS(ctx, t, config1)
  3910  	defer mnt1.Close()
  3911  	defer cancelFn1()
  3912  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config1)
  3913  
  3914  	config2 := libkbfs.ConfigAsUser(config1, "user2")
  3915  	mnt2, fs2, cancelFn2 := makeFS(ctx, t, config2)
  3916  	defer mnt2.Close()
  3917  	defer cancelFn2()
  3918  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config2)
  3919  
  3920  	mydir1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir")
  3921  	if err := ioutil.Mkdir(mydir1, 0755); err != nil {
  3922  		t.Fatal(err)
  3923  	}
  3924  	myfile1 := path.Join(mnt1.Dir, PrivateName, "user1,user2", "mydir", "myfile")
  3925  	data := []byte("foo")
  3926  	if err := ioutil.WriteFile(myfile1, data, 0644); err != nil {
  3927  		t.Fatal(err)
  3928  	}
  3929  
  3930  	d, err := os.Open(mydir1)
  3931  	if err != nil {
  3932  		t.Fatal(err)
  3933  	}
  3934  	defer d.Close()
  3935  	err = d.Sync()
  3936  	if err != nil {
  3937  		t.Fatal(err)
  3938  	}
  3939  
  3940  	syncFolderToServer(t, "user1,user2", fs2)
  3941  	myfile2 := path.Join(mnt2.Dir, PrivateName, "user1,user2", "mydir", "myfile")
  3942  	gotData, err := ioutil.ReadFile(myfile2)
  3943  	if err != nil {
  3944  		t.Fatal(err)
  3945  	}
  3946  	if !bytes.Equal(data, gotData) {
  3947  		t.Fatalf("Expected=%v, got=%v", data, gotData)
  3948  	}
  3949  }
  3950  
  3951  // Regression test for KBFS-2853.
  3952  func TestInodes(t *testing.T) {
  3953  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  3954  	defer testCleanupDelayer(ctx, t)
  3955  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  3956  	mnt, _, cancelFn := makeFS(ctx, t, config)
  3957  	defer mnt.Close()
  3958  	defer cancelFn()
  3959  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  3960  
  3961  	p := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  3962  	if err := ioutil.WriteFile(p, []byte("fake binary"), 0755); err != nil {
  3963  		t.Fatal(err)
  3964  	}
  3965  	syncFilename(t, p)
  3966  
  3967  	getInode := func(p string) uint64 {
  3968  		fi, err := ioutil.Lstat(p)
  3969  		if err != nil {
  3970  			t.Fatal(err)
  3971  		}
  3972  		stat, ok := fi.Sys().(*syscall.Stat_t)
  3973  		if !ok {
  3974  			t.Fatalf("Not a syscall.Stat_t")
  3975  		}
  3976  		return stat.Ino
  3977  	}
  3978  	inode := getInode(p)
  3979  
  3980  	t.Log("Rename file and make sure inode hasn't changed.")
  3981  	p2 := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile2")
  3982  	if err := ioutil.Rename(p, p2); err != nil {
  3983  		t.Fatal(err)
  3984  	}
  3985  	syncFilename(t, p2)
  3986  
  3987  	inode2 := getInode(p2)
  3988  	if inode != inode2 {
  3989  		t.Fatalf("Inode changed after rename: %d vs %d", inode, inode2)
  3990  	}
  3991  
  3992  	t.Log("A new file with the previous name should get a new inode")
  3993  
  3994  	if err := ioutil.WriteFile(p, []byte("more fake data"), 0755); err != nil {
  3995  		t.Fatal(err)
  3996  	}
  3997  	syncFilename(t, p)
  3998  
  3999  	inode3 := getInode(p)
  4000  	if inode == inode3 {
  4001  		t.Fatal("New and old files have the same inode")
  4002  	}
  4003  }
  4004  
  4005  func TestHardLinkNotSupported(t *testing.T) {
  4006  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  4007  	defer testCleanupDelayer(ctx, t)
  4008  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  4009  	mnt, _, cancelFn := makeFS(ctx, t, config)
  4010  	defer mnt.Close()
  4011  	defer cancelFn()
  4012  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  4013  
  4014  	checkLinkErr := func(old, new string, checkPermErr bool) {
  4015  		err := os.Link(old, new)
  4016  		linkErr, ok := errors.Cause(err).(*os.LinkError)
  4017  		require.True(t, ok)
  4018  		if checkPermErr && runtime.GOOS == "darwin" {
  4019  			// On macOS, in directories without the write bit set like
  4020  			// /keybase and /keybase/private, the `Link` call gets an
  4021  			// `EPERM` error back from the `Access()` Fuse request,
  4022  			// and never even tries calling `Link()`.
  4023  			require.Equal(t, syscall.EPERM, linkErr.Err)
  4024  		} else {
  4025  			require.Equal(t, syscall.ENOTSUP, linkErr.Err)
  4026  		}
  4027  	}
  4028  
  4029  	t.Log("Test hardlink in root of TLF")
  4030  	old := path.Join(mnt.Dir, PrivateName, "jdoe", "myfile")
  4031  	err := ioutil.WriteFile(old, []byte("hello"), 0755)
  4032  	require.NoError(t, err)
  4033  	syncFilename(t, old)
  4034  	new := path.Join(mnt.Dir, PrivateName, "jdoe", "hardlink")
  4035  	checkLinkErr(old, new, false)
  4036  
  4037  	t.Log("Test hardlink in subdir of TLF")
  4038  	mydir := path.Join(mnt.Dir, PrivateName, "jdoe", "mydir")
  4039  	err = ioutil.Mkdir(mydir, 0755)
  4040  	require.NoError(t, err)
  4041  	old2 := path.Join(mydir, "myfile")
  4042  	err = ioutil.WriteFile(old2, []byte("hello"), 0755)
  4043  	require.NoError(t, err)
  4044  	syncFilename(t, old2)
  4045  	new2 := path.Join(mydir, "hardlink")
  4046  	checkLinkErr(old2, new2, false)
  4047  
  4048  	t.Log("Test hardlink in folder list")
  4049  	old3 := path.Join(mnt.Dir, PrivateName, ".kbfs_status")
  4050  	new3 := path.Join(mnt.Dir, PrivateName, "hardlink")
  4051  	checkLinkErr(old3, new3, true)
  4052  
  4053  	t.Log("Test hardlink in root")
  4054  	old4 := path.Join(mnt.Dir, ".kbfs_status")
  4055  	new4 := path.Join(mnt.Dir, "hardlink")
  4056  	checkLinkErr(old4, new4, true)
  4057  }
  4058  
  4059  func TestOpenFileCount(t *testing.T) {
  4060  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  4061  	defer testCleanupDelayer(ctx, t)
  4062  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  4063  	mnt, _, cancelFn := makeFS(ctx, t, config)
  4064  	defer mnt.Close()
  4065  	defer cancelFn()
  4066  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  4067  
  4068  	p := path.Join(mnt.Dir, libfs.OpenFileCountFileName)
  4069  	checkCount := func(expected int64) {
  4070  		f, err := os.Open(p)
  4071  		require.NoError(t, err)
  4072  		defer f.Close()
  4073  
  4074  		b, err := ioutil.ReadAll(f)
  4075  		require.NoError(t, err)
  4076  
  4077  		i, err := strconv.ParseInt(string(b), 10, 64)
  4078  		require.NoError(t, err)
  4079  		require.Equal(t, expected, i)
  4080  	}
  4081  
  4082  	checkCount(0)
  4083  
  4084  	_, err := ioutil.Lstat(path.Join(mnt.Dir, PrivateName))
  4085  	require.NoError(t, err)
  4086  	checkCount(1)
  4087  
  4088  	_, err = ioutil.Lstat(path.Join(mnt.Dir, PublicName))
  4089  	require.NoError(t, err)
  4090  	checkCount(2)
  4091  
  4092  	_, err = ioutil.Lstat(path.Join(mnt.Dir, PrivateName))
  4093  	require.NoError(t, err)
  4094  	checkCount(2)
  4095  
  4096  	err = ioutil.Mkdir(
  4097  		path.Join(mnt.Dir, PrivateName, "jdoe", "d"), os.ModeDir)
  4098  	require.NoError(t, err)
  4099  	checkCount(4)
  4100  }
  4101  
  4102  func TestUpdateHistoryFile(t *testing.T) {
  4103  	ctx := libcontext.BackgroundContextWithCancellationDelayer()
  4104  	defer testCleanupDelayer(ctx, t)
  4105  	config := libkbfs.MakeTestConfigOrBust(t, "jdoe")
  4106  	mnt, _, cancelFn := makeFS(ctx, t, config)
  4107  	defer mnt.Close()
  4108  	defer cancelFn()
  4109  	defer libkbfs.CheckConfigAndShutdown(ctx, t, config)
  4110  
  4111  	libfs.AddRootWrapper(config)
  4112  
  4113  	t.Log("Make several revisions")
  4114  	p := path.Join(mnt.Dir, PrivateName, "jdoe")
  4115  	for i := 0; i < 10; i++ {
  4116  		file := path.Join(p, fmt.Sprintf("foo-%d", i))
  4117  		f, err := os.Create(file)
  4118  		require.NoError(t, err)
  4119  		syncAndClose(t, f)
  4120  	}
  4121  
  4122  	t.Log("Read a revision range")
  4123  	histPrefix := path.Join(p, libfs.UpdateHistoryFileName)
  4124  	fRange, err := os.Open(histPrefix + ".3-5")
  4125  	require.NoError(t, err)
  4126  	defer fRange.Close()
  4127  	b, err := ioutil.ReadAll(fRange)
  4128  	require.NoError(t, err)
  4129  	var histRange libkbfs.TLFUpdateHistory
  4130  	err = json.Unmarshal(b, &histRange)
  4131  	require.NoError(t, err)
  4132  	require.Len(t, histRange.Updates, 3)
  4133  
  4134  	t.Log("Read a single revision")
  4135  	fSingle, err := os.Open(histPrefix + ".7")
  4136  	require.NoError(t, err)
  4137  	defer fSingle.Close()
  4138  	b, err = ioutil.ReadAll(fSingle)
  4139  	require.NoError(t, err)
  4140  	var histSingle libkbfs.TLFUpdateHistory
  4141  	err = json.Unmarshal(b, &histSingle)
  4142  	require.NoError(t, err)
  4143  	require.Len(t, histSingle.Updates, 1)
  4144  
  4145  	t.Log("Read the entire history")
  4146  	fAll, err := os.Open(histPrefix)
  4147  	require.NoError(t, err)
  4148  	defer fAll.Close()
  4149  	b, err = ioutil.ReadAll(fAll)
  4150  	require.NoError(t, err)
  4151  	var histAll libkbfs.TLFUpdateHistory
  4152  	err = json.Unmarshal(b, &histAll)
  4153  	require.NoError(t, err)
  4154  	require.Len(t, histAll.Updates, 11)
  4155  }