convert_test.go 5.34 KB
Newer Older
1 2 3 4 5 6
package flatfs_test

import (
	"bytes"
	"encoding/hex"
	"io/ioutil"
7
	"math/rand"
8 9 10
	"os"
	"path/filepath"
	"testing"
11
	"time"
12 13 14 15 16 17 18 19 20 21

	"github.com/ipfs/go-datastore"
	"github.com/ipfs/go-ds-flatfs"
)

func TestMove(t *testing.T) {
	tempdir, cleanup := tempdir(t)
	defer cleanup()

	v1dir := filepath.Join(tempdir, "v1")
Kevin Atkinson's avatar
Kevin Atkinson committed
22 23 24
	createDatastore(t, v1dir, flatfs.Prefix(3))

	err := ioutil.WriteFile(filepath.Join(v1dir, "README_ALSO"), []byte("something"), 0666)
25
	if err != nil {
Kevin Atkinson's avatar
Kevin Atkinson committed
26
		t.Fatalf("WriteFile fail: %v\n", err)
27
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
28 29 30 31 32 33 34

	keys, blocks := populateDatastore(t, v1dir)

	v2dir := filepath.Join(tempdir, "v2")
	createDatastore(t, v2dir, flatfs.NextToLast(2))

	err = flatfs.Move(v1dir, v2dir, nil)
35
	if err != nil {
Kevin Atkinson's avatar
Kevin Atkinson committed
36
		t.Fatalf("%v\n", err)
37
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
38 39 40 41 42 43

	// make sure the directory empty
	rmEmptyDatastore(t, v1dir)

	// make sure the README file moved
	_, err = os.Stat(filepath.Join(v2dir, "README_ALSO"))
44
	if err != nil {
Kevin Atkinson's avatar
Kevin Atkinson committed
45
		t.Fatalf(err.Error())
46 47
	}

Kevin Atkinson's avatar
Kevin Atkinson committed
48 49
	// check that all keys are available
	checkKeys(t, v2dir, keys, blocks)
50

Kevin Atkinson's avatar
Kevin Atkinson committed
51 52 53 54 55
	// check that a key is in the correct format
	shard := filepath.Join(v2dir, flatfs.NextToLast(2).Func()(keys[0].String()))
	_, err = os.Stat(shard)
	if err != nil {
		t.Fatalf(err.Error())
56
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
57
}
58

Kevin Atkinson's avatar
Kevin Atkinson committed
59 60 61 62 63
func TestMoveRestart(t *testing.T) {
	tempdir, cleanup := tempdir(t)
	defer cleanup()

	v1dir := filepath.Join(tempdir, "v1")
64
	v2dir := filepath.Join(tempdir, "v2")
Kevin Atkinson's avatar
Kevin Atkinson committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78

	createDatastore(t, v1dir, flatfs.Prefix(3))

	createDatastore(t, v2dir, flatfs.NextToLast(5))

	keys, blocks := populateDatastore(t, v1dir)
	checkKeys(t, v1dir, keys, blocks)

	// get a directory in the datastore
	noslash := keys[0].String()[1:]
	aDir := filepath.Join(tempdir, "v1", flatfs.Prefix(3).Func()(noslash))

	// create a permission problem on the directory
	err := os.Chmod(aDir, 0500)
79
	if err != nil {
Kevin Atkinson's avatar
Kevin Atkinson committed
80
		t.Fatalf("%v\n", err)
81 82
	}

Kevin Atkinson's avatar
Kevin Atkinson committed
83 84 85
	// try the move it should fail partly through
	err = flatfs.Move(v1dir, v2dir, nil)
	if err == nil {
Steven Allen's avatar
Steven Allen committed
86
		t.Fatal("Move should have failed.", err)
87 88
	}

Kevin Atkinson's avatar
Kevin Atkinson committed
89 90
	// okay try to undo should be okay
	err = flatfs.Move(v2dir, v1dir, nil)
91
	if err != nil {
Steven Allen's avatar
Steven Allen committed
92
		t.Fatal("Could not undo the move.", err)
93
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
94
	checkKeys(t, v1dir, keys, blocks)
95

Kevin Atkinson's avatar
Kevin Atkinson committed
96 97
	// there should be nothing left in the new datastore
	rmEmptyDatastore(t, v2dir)
98

Kevin Atkinson's avatar
Kevin Atkinson committed
99 100 101 102
	// try the move again, again should fail
	createDatastore(t, v2dir, flatfs.NextToLast(2))
	err = flatfs.Move(v1dir, v2dir, nil)
	if err == nil {
Steven Allen's avatar
Steven Allen committed
103
		t.Fatal("Move should have failed.", err)
104 105
	}

Kevin Atkinson's avatar
Kevin Atkinson committed
106 107
	// fix the permission problem
	err = os.Chmod(aDir, 0700)
108
	if err != nil {
Kevin Atkinson's avatar
Kevin Atkinson committed
109
		t.Fatalf("%v\n", err)
110
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
111 112 113 114 115

	// restart the move, it should be okay now
	err = flatfs.Move(v1dir, v2dir, nil)
	if err != nil {
		t.Fatalf("Move not okay: %v\n", err)
116 117
	}

Kevin Atkinson's avatar
Kevin Atkinson committed
118 119 120 121 122 123 124
	// make sure everything moved by removing the old directory
	rmEmptyDatastore(t, v1dir)

	// make sure everything moved by checking all keys
	checkKeys(t, v2dir, keys, blocks)

	// check that a key is in the correct format
125 126 127 128 129 130
	shard := filepath.Join(v2dir, flatfs.NextToLast(2).Func()(keys[0].String()))
	_, err = os.Stat(shard)
	if err != nil {
		t.Fatalf(err.Error())
	}
}
Kevin Atkinson's avatar
Kevin Atkinson committed
131 132 133 134 135 136 137 138 139 140

func TestUpgradeDownload(t *testing.T) {
	tempdir, cleanup := tempdir(t)
	defer cleanup()

	createDatastore(t, tempdir, flatfs.Prefix(3))

	keys, blocks := populateDatastore(t, tempdir)
	checkKeys(t, tempdir, keys, blocks)

141 142 143 144
	err := flatfs.UpgradeV0toV1(tempdir, 3)
	if err == nil {
		t.Fatalf("UpgradeV0toV1 on already v1 should fail.")
	}
Kevin Atkinson's avatar
Kevin Atkinson committed
145

146
	err = flatfs.DowngradeV1toV0(tempdir)
Kevin Atkinson's avatar
Kevin Atkinson committed
147 148 149 150 151 152
	if err != nil {
		t.Fatalf("DowngradeV1toV0 fail: %v\n", err)
	}

	_, err = os.Stat(filepath.Join(tempdir, flatfs.SHARDING_FN))
	if err == nil {
Steven Allen's avatar
Steven Allen committed
153
		t.Fatalf("%v not in v0 format, SHARDING FILE exists", tempdir)
Kevin Atkinson's avatar
Kevin Atkinson committed
154 155 156 157 158 159 160 161 162 163 164 165 166
	} else if !os.IsNotExist(err) {
		t.Fatalf("Stat fail: %v\n", err)
	}

	err = flatfs.UpgradeV0toV1(tempdir, 3)
	if err != nil {
		t.Fatalf("UpgradeV0toV1 fail %v\n", err)
	}

	// This will fail unless the repository is in the new version
	checkKeys(t, tempdir, keys, blocks)
}

167 168 169 170 171 172 173 174
func TestDownloadNonPrefix(t *testing.T) {
	tempdir, cleanup := tempdir(t)
	defer cleanup()

	createDatastore(t, tempdir, flatfs.NextToLast(2))

	err := flatfs.DowngradeV1toV0(tempdir)
	if err == nil {
Steven Allen's avatar
Steven Allen committed
175
		t.Fatal("DowngradeV1toV0 should have failed", err)
176 177 178
	}
}

Kevin Atkinson's avatar
Kevin Atkinson committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
func createDatastore(t *testing.T, dir string, fun *flatfs.ShardIdV1) {
	err := flatfs.Create(dir, fun)
	if err != nil {
		t.Fatalf("Create fail: %s: %v\n", dir, err)
	}
}

func rmEmptyDatastore(t *testing.T, dir string) {
	err := os.Remove(dir)
	if err != nil {
		t.Fatalf("Remove fail: %v\n", err)
	}
}

func populateDatastore(t *testing.T, dir string) ([]datastore.Key, [][]byte) {
	ds, err := flatfs.Open(dir, false)
	if err != nil {
		t.Fatalf("Open fail: %v\n", err)
	}
198
	defer ds.Close()
Kevin Atkinson's avatar
Kevin Atkinson committed
199

200
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
Kevin Atkinson's avatar
Kevin Atkinson committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
	var blocks [][]byte
	var keys []datastore.Key
	for i := 0; i < 256; i++ {
		blk := make([]byte, 1000)
		r.Read(blk)
		blocks = append(blocks, blk)

		key := "x" + hex.EncodeToString(blk[:8])
		keys = append(keys, datastore.NewKey(key))
		err := ds.Put(keys[i], blocks[i])
		if err != nil {
			t.Fatalf("Put fail: %v\n", err)
		}
	}

	return keys, blocks
}

func checkKeys(t *testing.T, dir string, keys []datastore.Key, blocks [][]byte) {
	ds, err := flatfs.Open(dir, false)
	if err != nil {
		t.Fatalf("Open fail: %v\n", err)
	}
224
	defer ds.Close()
Kevin Atkinson's avatar
Kevin Atkinson committed
225 226 227 228 229 230

	for i, key := range keys {
		data, err := ds.Get(key)
		if err != nil {
			t.Fatalf("Get fail: %v\n", err)
		}
231
		if !bytes.Equal(data, blocks[i]) {
Kevin Atkinson's avatar
Kevin Atkinson committed
232 233 234 235
			t.Fatalf("block context differ for key %s\n", key.String())
		}
	}
}