|
|
|
@ -1251,13 +1251,13 @@ var posixReadFileWithVerifyTests = []struct { |
|
|
|
|
{file: "myobject", offset: 25, length: 74, algorithm: SHA256, expError: nil}, // 1
|
|
|
|
|
{file: "myobject", offset: 29, length: 70, algorithm: SHA256, expError: nil}, // 2
|
|
|
|
|
{file: "myobject", offset: 100, length: 0, algorithm: SHA256, expError: nil}, // 3
|
|
|
|
|
{file: "myobject", offset: 1, length: 120, algorithm: SHA256, expError: hashMismatchError{}}, // 4
|
|
|
|
|
{file: "myobject", offset: 1, length: 120, algorithm: SHA256, expError: HashMismatchError{}}, // 4
|
|
|
|
|
{file: "myobject", offset: 3, length: 1100, algorithm: SHA256, expError: nil}, // 5
|
|
|
|
|
{file: "myobject", offset: 2, length: 100, algorithm: SHA256, expError: hashMismatchError{}}, // 6
|
|
|
|
|
{file: "myobject", offset: 2, length: 100, algorithm: SHA256, expError: HashMismatchError{}}, // 6
|
|
|
|
|
{file: "myobject", offset: 1000, length: 1001, algorithm: SHA256, expError: nil}, // 7
|
|
|
|
|
{file: "myobject", offset: 0, length: 100, algorithm: BLAKE2b512, expError: hashMismatchError{}}, // 8
|
|
|
|
|
{file: "myobject", offset: 0, length: 100, algorithm: BLAKE2b512, expError: HashMismatchError{}}, // 8
|
|
|
|
|
{file: "myobject", offset: 25, length: 74, algorithm: BLAKE2b512, expError: nil}, // 9
|
|
|
|
|
{file: "myobject", offset: 29, length: 70, algorithm: BLAKE2b512, expError: hashMismatchError{}}, // 10
|
|
|
|
|
{file: "myobject", offset: 29, length: 70, algorithm: BLAKE2b512, expError: HashMismatchError{}}, // 10
|
|
|
|
|
{file: "myobject", offset: 100, length: 0, algorithm: BLAKE2b512, expError: nil}, // 11
|
|
|
|
|
{file: "myobject", offset: 1, length: 120, algorithm: BLAKE2b512, expError: nil}, // 12
|
|
|
|
|
{file: "myobject", offset: 3, length: 1100, algorithm: BLAKE2b512, expError: nil}, // 13
|
|
|
|
@ -1296,7 +1296,7 @@ func TestPosixReadFileWithVerify(t *testing.T) { |
|
|
|
|
if test.expError != nil { |
|
|
|
|
expected := h.Sum(nil) |
|
|
|
|
h.Write([]byte{0}) |
|
|
|
|
test.expError = hashMismatchError{hex.EncodeToString(h.Sum(nil)), hex.EncodeToString(expected)} |
|
|
|
|
test.expError = HashMismatchError{hex.EncodeToString(h.Sum(nil)), hex.EncodeToString(expected)} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
buffer := make([]byte, test.length) |
|
|
|
@ -1763,6 +1763,97 @@ func TestPosixStatFile(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Test posix.VerifyFile()
|
|
|
|
|
func TestPosixVerifyFile(t *testing.T) { |
|
|
|
|
// We test 4 cases:
|
|
|
|
|
// 1) Whole-file bitrot check on proper file
|
|
|
|
|
// 2) Whole-file bitrot check on corrupted file
|
|
|
|
|
// 3) Streaming bitrot check on proper file
|
|
|
|
|
// 4) Streaming bitrot check on corrupted file
|
|
|
|
|
|
|
|
|
|
// create posix test setup
|
|
|
|
|
posixStorage, path, err := newPosixTestSetup() |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("Unable to create posix test setup, %s", err) |
|
|
|
|
} |
|
|
|
|
defer os.RemoveAll(path) |
|
|
|
|
|
|
|
|
|
volName := "testvol" |
|
|
|
|
fileName := "testfile" |
|
|
|
|
if err := posixStorage.MakeVol(volName); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 1) Whole-file bitrot check on proper file
|
|
|
|
|
size := int64(4*1024*1024 + 100*1024) // 4.1 MB
|
|
|
|
|
data := make([]byte, size) |
|
|
|
|
if _, err := rand.Read(data); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
algo := HighwayHash256 |
|
|
|
|
h := algo.New() |
|
|
|
|
h.Write(data) |
|
|
|
|
hashBytes := h.Sum(nil) |
|
|
|
|
if err := posixStorage.WriteAll(volName, fileName, bytes.NewBuffer(data)); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
if err := posixStorage.VerifyFile(volName, fileName, algo, hashBytes, 0); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2) Whole-file bitrot check on corrupted file
|
|
|
|
|
if err := posixStorage.AppendFile(volName, fileName, []byte("a")); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
if err := posixStorage.VerifyFile(volName, fileName, algo, hashBytes, 0); err == nil { |
|
|
|
|
t.Fatal("expected to fail bitrot check") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if err := posixStorage.DeleteFile(volName, fileName); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3) Streaming bitrot check on proper file
|
|
|
|
|
algo = HighwayHash256S |
|
|
|
|
shardSize := int64(1024 * 1024) |
|
|
|
|
shard := make([]byte, shardSize) |
|
|
|
|
w := newStreamingBitrotWriter(posixStorage, volName, fileName, size, algo, shardSize) |
|
|
|
|
reader := bytes.NewReader(data) |
|
|
|
|
for { |
|
|
|
|
// Using io.CopyBuffer instead of this loop will not work for us as io.CopyBuffer
|
|
|
|
|
// will use bytes.Buffer.ReadFrom() which will not do shardSize'ed writes causing error.
|
|
|
|
|
n, err := reader.Read(shard) |
|
|
|
|
w.Write(shard[:n]) |
|
|
|
|
if err == nil { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
if err == io.EOF { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
w.Close() |
|
|
|
|
if err := posixStorage.VerifyFile(volName, fileName, algo, nil, shardSize); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4) Streaming bitrot check on corrupted file
|
|
|
|
|
filePath := pathJoin(posixStorage.String(), volName, fileName) |
|
|
|
|
f, err := os.OpenFile(filePath, os.O_WRONLY, 0644) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
if _, err := f.WriteString("a"); err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
f.Close() |
|
|
|
|
if err := posixStorage.VerifyFile(volName, fileName, algo, nil, shardSize); err == nil { |
|
|
|
|
t.Fatal("expected to fail bitrot check") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Checks for restrictions for min total disk space and inodes.
|
|
|
|
|
func TestCheckDiskTotalMin(t *testing.T) { |
|
|
|
|
testCases := []struct { |
|
|
|
|