github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/fuse/ipns/ipns_test.go (about)

     1  package ipns
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"io/ioutil"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  	"time"
    11  
    12  	fstest "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs/fstestutil"
    13  	core "github.com/jbenet/go-ipfs/core"
    14  	u "github.com/jbenet/go-ipfs/util"
    15  )
    16  
    17  func maybeSkipFuseTests(t *testing.T) bool {
    18  	v := "TEST_NO_FUSE"
    19  	n := strings.ToLower(os.Getenv(v))
    20  	skip := n != "" && n != "false" && n != "f"
    21  
    22  	if skip {
    23  		t.Skipf("Skipping FUSE tests (%s=%s)", v, n)
    24  	}
    25  	return skip
    26  }
    27  
    28  func randBytes(size int) []byte {
    29  	b := make([]byte, size)
    30  	rand.Read(b)
    31  	return b
    32  }
    33  
    34  func writeFile(t *testing.T, size int, path string) []byte {
    35  	return writeFileData(t, randBytes(size), path)
    36  }
    37  
    38  func writeFileData(t *testing.T, data []byte, path string) []byte {
    39  	fi, err := os.Create(path)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  
    44  	n, err := fi.Write(data)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	if n != len(data) {
    50  		t.Fatal("Didnt write proper amount!")
    51  	}
    52  
    53  	err = fi.Close()
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	return data
    59  }
    60  
    61  func setupIpnsTest(t *testing.T, node *core.IpfsNode) (*core.IpfsNode, *fstest.Mount) {
    62  	maybeSkipFuseTests(t)
    63  
    64  	var err error
    65  	if node == nil {
    66  		node, err = core.NewMockNode()
    67  		if err != nil {
    68  			t.Fatal(err)
    69  		}
    70  	}
    71  
    72  	fs, err := NewIpns(node, "")
    73  	if err != nil {
    74  		t.Fatal(err)
    75  	}
    76  	mnt, err := fstest.MountedT(t, fs)
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	return node, mnt
    82  }
    83  
    84  // Test writing a file and reading it back
    85  func TestIpnsBasicIO(t *testing.T) {
    86  	_, mnt := setupIpnsTest(t, nil)
    87  	defer mnt.Close()
    88  
    89  	fname := mnt.Dir + "/local/testfile"
    90  	data := writeFile(t, 12345, fname)
    91  
    92  	rbuf, err := ioutil.ReadFile(fname)
    93  	if err != nil {
    94  		t.Fatal(err)
    95  	}
    96  
    97  	if !bytes.Equal(rbuf, data) {
    98  		t.Fatal("Incorrect Read!")
    99  	}
   100  }
   101  
   102  // Test to make sure file changes persist over mounts of ipns
   103  func TestFilePersistence(t *testing.T) {
   104  	node, mnt := setupIpnsTest(t, nil)
   105  
   106  	fname := "/local/atestfile"
   107  	data := writeFile(t, 127, mnt.Dir+fname)
   108  
   109  	// Wait for publish: TODO: make publish happen faster in tests
   110  	time.Sleep(time.Millisecond * 40)
   111  
   112  	mnt.Close()
   113  
   114  	node, mnt = setupIpnsTest(t, node)
   115  	defer mnt.Close()
   116  
   117  	rbuf, err := ioutil.ReadFile(mnt.Dir + fname)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	if !bytes.Equal(rbuf, data) {
   123  		t.Fatalf("File data changed between mounts! sizes differ: %d != %d", len(data), len(rbuf))
   124  	}
   125  }
   126  
   127  // Test to make sure the filesystem reports file sizes correctly
   128  func TestFileSizeReporting(t *testing.T) {
   129  	_, mnt := setupIpnsTest(t, nil)
   130  	defer mnt.Close()
   131  
   132  	fname := mnt.Dir + "/local/sizecheck"
   133  	data := writeFile(t, 5555, fname)
   134  
   135  	finfo, err := os.Stat(fname)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	if finfo.Size() != int64(len(data)) {
   141  		t.Fatal("Read incorrect size from stat!")
   142  	}
   143  }
   144  
   145  // Test to make sure you cant create multiple entries with the same name
   146  func TestDoubleEntryFailure(t *testing.T) {
   147  	_, mnt := setupIpnsTest(t, nil)
   148  	defer mnt.Close()
   149  
   150  	dname := mnt.Dir + "/local/thisisadir"
   151  	err := os.Mkdir(dname, 0777)
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	err = os.Mkdir(dname, 0777)
   157  	if err == nil {
   158  		t.Fatal("Should have gotten error one creating new directory.")
   159  	}
   160  }
   161  
   162  func TestAppendFile(t *testing.T) {
   163  	_, mnt := setupIpnsTest(t, nil)
   164  	defer mnt.Close()
   165  
   166  	fname := mnt.Dir + "/local/file"
   167  	data := writeFile(t, 1300, fname)
   168  
   169  	fi, err := os.OpenFile(fname, os.O_RDWR|os.O_APPEND, 0666)
   170  	if err != nil {
   171  		t.Fatal(err)
   172  	}
   173  
   174  	nudata := randBytes(500)
   175  
   176  	n, err := fi.Write(nudata)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	err = fi.Close()
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	if n != len(nudata) {
   186  		t.Fatal("Failed to write enough bytes.")
   187  	}
   188  
   189  	data = append(data, nudata...)
   190  
   191  	rbuf, err := ioutil.ReadFile(fname)
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  	if !bytes.Equal(rbuf, data) {
   196  		t.Fatal("Data inconsistent!")
   197  	}
   198  }
   199  
   200  func TestFastRepublish(t *testing.T) {
   201  
   202  	// make timeout noticeable.
   203  	osrt := shortRepublishTimeout
   204  	shortRepublishTimeout = time.Millisecond * 100
   205  
   206  	olrt := longRepublishTimeout
   207  	longRepublishTimeout = time.Second
   208  
   209  	node, mnt := setupIpnsTest(t, nil)
   210  
   211  	h, err := node.Identity.PrivKey().GetPublic().Hash()
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  	pubkeyHash := u.Key(h).Pretty()
   216  
   217  	// set them back
   218  	defer func() {
   219  		shortRepublishTimeout = osrt
   220  		longRepublishTimeout = olrt
   221  		mnt.Close()
   222  	}()
   223  
   224  	closed := make(chan struct{})
   225  	dataA := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
   226  	dataB := []byte("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
   227  
   228  	fname := mnt.Dir + "/local/file"
   229  
   230  	// get first resolved hash
   231  	log.Debug("publishing first hash")
   232  	writeFileData(t, dataA, fname) // random
   233  	<-time.After(shortRepublishTimeout * 11 / 10)
   234  	log.Debug("resolving first hash")
   235  	resolvedHash, err := node.Namesys.Resolve(pubkeyHash)
   236  	if err != nil {
   237  		t.Fatal("resolve err:", pubkeyHash, err)
   238  	}
   239  
   240  	// constantly keep writing to the file
   241  	go func(timeout time.Duration) {
   242  		for {
   243  			select {
   244  			case <-closed:
   245  				return
   246  
   247  			case <-time.After(timeout * 8 / 10):
   248  				writeFileData(t, dataB, fname)
   249  			}
   250  		}
   251  	}(shortRepublishTimeout)
   252  
   253  	hasPublished := func() bool {
   254  		res, err := node.Namesys.Resolve(pubkeyHash)
   255  		if err != nil {
   256  			t.Fatalf("resolve err: %v", err)
   257  		}
   258  		return res != resolvedHash
   259  	}
   260  
   261  	// test things
   262  
   263  	// at this point, should not have written dataA and not have written dataB
   264  	rbuf, err := ioutil.ReadFile(fname)
   265  	if err != nil || !bytes.Equal(rbuf, dataA) {
   266  		t.Fatalf("Data inconsistent! %v %v", err, string(rbuf))
   267  	}
   268  
   269  	if hasPublished() {
   270  		t.Fatal("published (wrote)")
   271  	}
   272  
   273  	<-time.After(shortRepublishTimeout * 11 / 10)
   274  
   275  	// at this point, should have written written dataB, but not published it
   276  	rbuf, err = ioutil.ReadFile(fname)
   277  	if err != nil || !bytes.Equal(rbuf, dataB) {
   278  		t.Fatalf("Data inconsistent! %v %v", err, string(rbuf))
   279  	}
   280  
   281  	if hasPublished() {
   282  		t.Fatal("published (wrote)")
   283  	}
   284  
   285  	<-time.After(longRepublishTimeout * 11 / 10)
   286  
   287  	// at this point, should have written written dataB, and published it
   288  	rbuf, err = ioutil.ReadFile(fname)
   289  	if err != nil || !bytes.Equal(rbuf, dataB) {
   290  		t.Fatalf("Data inconsistent! %v %v", err, string(rbuf))
   291  	}
   292  
   293  	if !hasPublished() {
   294  		t.Fatal("not published")
   295  	}
   296  
   297  	close(closed)
   298  }
   299  
   300  // Test writing a medium sized file one byte at a time
   301  func TestMultiWrite(t *testing.T) {
   302  
   303  	_, mnt := setupIpnsTest(t, nil)
   304  	defer mnt.Close()
   305  
   306  	fpath := mnt.Dir + "/local/file"
   307  	fi, err := os.Create(fpath)
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	data := randBytes(1001)
   313  	for i := 0; i < len(data); i++ {
   314  		n, err := fi.Write(data[i : i+1])
   315  		if err != nil {
   316  			t.Fatal(err)
   317  		}
   318  		if n != 1 {
   319  			t.Fatal("Somehow wrote the wrong number of bytes! (n != 1)")
   320  		}
   321  	}
   322  	fi.Close()
   323  
   324  	rbuf, err := ioutil.ReadFile(fpath)
   325  	if err != nil {
   326  		t.Fatal(err)
   327  	}
   328  
   329  	if !bytes.Equal(rbuf, data) {
   330  		t.Fatal("File on disk did not match bytes written")
   331  	}
   332  }