syncthing/lib/fs/fakefs_test.go
Jakob Borg d27463268d lib/fs: Add fakefs (#5235)
* lib/fs: Add fakefs

This adds a new fake filesystem type. It's described rather extensively
in fakefs.go, but the main point is that it's for testing: when you want
to spin up a Syncthing and have a terabyte or two of random files that
can be synced somewhere, or an inifitely large filesystem to sync files
into.

It has pseudorandom properties such that data read from one fakefs can
be written into another fakefs and read back and it will look
consistent, without any of the data actually being stored.

To use:

    <folder id="default" path="whatever" ...>
        <filesystemType>fake</filesystemType>

This will create an empty fake filesystem. You can also specify that it
should be prefilled with files:

    <folder id="default" path="whatever?size=2000000" ...>
        <filesystemType>fake</filesystemType>

This will create a filesystem filled with 2TB of random data that can be
scanned and synced. There are more options, see fakefs.go.

Prefilled data is based on a deterministic seed, so you can index the
data and restart Syncthing and the index is still correct for all the
stored data.
2018-10-02 19:29:06 +01:00

155 lines
2.7 KiB
Go

// Copyright (C) 2018 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package fs
import (
"bytes"
"io/ioutil"
"os"
"testing"
)
func TestFakeFS(t *testing.T) {
// Test some basic aspects of the fakefs
fs := newFakeFilesystem("/foo/bar/baz")
// MkdirAll
err := fs.MkdirAll("dira/dirb", 0755)
if err != nil {
t.Fatal(err)
}
info, err := fs.Stat("dira/dirb")
if err != nil {
t.Fatal(err)
}
// Mkdir
err = fs.Mkdir("dira/dirb/dirc", 0755)
if err != nil {
t.Fatal(err)
}
info, err = fs.Stat("dira/dirb/dirc")
if err != nil {
t.Fatal(err)
}
// Create
fd, err := fs.Create("/dira/dirb/test")
if err != nil {
t.Fatal(err)
}
// Write
_, err = fd.Write([]byte("hello"))
if err != nil {
t.Fatal(err)
}
// Stat on fd
info, err = fd.Stat()
if err != nil {
t.Fatal(err)
}
if info.Name() != "test" {
t.Error("wrong name:", info.Name())
}
if info.Size() != 5 {
t.Error("wrong size:", info.Size())
}
// Stat on fs
info, err = fs.Stat("dira/dirb/test")
if err != nil {
t.Fatal(err)
}
if info.Name() != "test" {
t.Error("wrong name:", info.Name())
}
if info.Size() != 5 {
t.Error("wrong size:", info.Size())
}
// Seek
_, err = fd.Seek(1, os.SEEK_SET)
if err != nil {
t.Fatal(err)
}
// Read
bs0, err := ioutil.ReadAll(fd)
if err != nil {
t.Fatal(err)
}
if len(bs0) != 4 {
t.Error("wrong number of bytes:", len(bs0))
}
// Read again, same data hopefully
_, err = fd.Seek(0, os.SEEK_SET)
if err != nil {
t.Fatal(err)
}
bs1, err := ioutil.ReadAll(fd)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(bs0, bs1[1:]) {
t.Error("wrong data")
}
}
func TestFakeFSRead(t *testing.T) {
// Test some basic aspects of the fakefs
fs := newFakeFilesystem("/foo/bar/baz")
// Create
fd, _ := fs.Create("test")
fd.Truncate(3 * 1 << randomBlockShift)
// Read
fd.Seek(0, 0)
bs0, err := ioutil.ReadAll(fd)
if err != nil {
t.Fatal(err)
}
if len(bs0) != 3*1<<randomBlockShift {
t.Error("wrong number of bytes:", len(bs0))
}
// Read again, starting at an odd offset
fd.Seek(0, 0)
buf0 := make([]byte, 12345)
n, _ := fd.Read(buf0)
if n != len(buf0) {
t.Fatal("short read")
}
buf1, err := ioutil.ReadAll(fd)
if err != nil {
t.Fatal(err)
}
if len(buf1) != 3*1<<randomBlockShift-len(buf0) {
t.Error("wrong number of bytes:", len(buf1))
}
bs1 := append(buf0, buf1...)
if !bytes.Equal(bs0, bs1) {
t.Error("data mismatch")
}
// Read large block with ReadAt
bs2 := make([]byte, 3*1<<randomBlockShift)
_, err = fd.ReadAt(bs2, 0)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(bs0, bs2) {
t.Error("data mismatch")
}
}