blob: de4802a10aaa674f973edb3d0b984e3dd7358bc5 [file] [log] [blame]
package filetilestore
import (
"encoding/gob"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"
"skia.googlesource.com/buildbot.git/perf/go/types"
)
func makeFakeTile(filename string, t *types.Tile) error {
f, err := os.Create(filename)
if err != nil {
return fmt.Errorf("File creation failed before test start: %s", err)
}
defer f.Close()
enc := gob.NewEncoder(f)
err = enc.Encode(t)
if err != nil {
return fmt.Errorf("Tile globbed failed before test start: %s", err)
}
f.Sync()
return nil
}
// TestFileTileGet tests FileTileStore's implementation of TileStore.Get.
// It does so by creating a tile gob and seeing if it is successfully read from,
// then rewriting it and seeing if it reads the new copy.
func TestFileTileGet(t *testing.T) {
randomPath, err := ioutil.TempDir("", "filestore_test")
if err != nil {
t.Fatalf("Failing to create temporary directory: %s", err)
return
}
defer os.RemoveAll(randomPath)
// The test file needs to be created in the 0/ subdirectory of the path.
randomFullPath := filepath.Join(randomPath, "test", "0")
if err := os.MkdirAll(randomFullPath, 0775); err != nil {
t.Fatalf("Failing to create temporary subdirectory: %s", err)
return
}
// NOTE: This needs to match what's created by tileFilename
fileName := filepath.Join(randomFullPath, "0000.gob")
err = makeFakeTile(fileName, &types.Tile{
Traces: map[string]types.Trace{
"test": &types.PerfTrace{
Values: []float64{0.0, 1.4, -2},
Params_: map[string]string{"test": "parameter"},
},
},
ParamSet: map[string][]string{
"test": []string{"parameter"},
},
Commits: []*types.Commit{
&types.Commit{
CommitTime: 42,
Hash: "ffffffffffffffffffffffffffffffffffffffff",
Author: "test@test.cz",
},
},
Scale: 0,
TileIndex: 0,
})
if err != nil {
t.Fatalf("Failed to create fake tile: %s", err)
return
}
ts := NewFileTileStore(randomPath, "test", 10*time.Millisecond)
t.Log("First test set started. Testing basic tile Get().")
getValue, err := ts.Get(0, 0)
if err != nil {
t.Errorf("FileTileStore.Get failed: %s\n", err)
} else {
if got, want := getValue.Scale, 0; got != want {
t.Errorf("FileTileStore.Get failed: scale values not matching\n")
dumpTile(getValue, t)
}
if got, want := getValue.TileIndex, 0; got != want {
t.Errorf("FileTileStore.Get failed: tile index values not matching\n")
dumpTile(getValue, t)
}
if got, want := len(getValue.Traces), 1; got != want {
t.Errorf("FileTileStore.Get failed: traces not matching\n")
dumpTile(getValue, t)
}
}
t.Log("First test set completed.")
err = makeFakeTile(fileName, &types.Tile{
Traces: map[string]types.Trace{},
ParamSet: map[string][]string{
"test": []string{"parameter"},
},
Commits: []*types.Commit{
&types.Commit{
CommitTime: 42,
Hash: "0000000000000000000000000000000000000000",
Author: "test@test.cz",
},
},
Scale: 0,
TileIndex: 0,
})
if err != nil {
t.Fatalf("Failed to create fake tile: %s", err)
return
}
// Test to see if changing the disk copy of it changes the copy
// we get back as well.
t.Log("Second test set started. Testing changed tile Get().")
getValue2, err := ts.Get(0, 0)
if err != nil {
t.Errorf("FileTileStore.Get failed: %s\n", err)
} else {
if got, want := getValue2.Scale, 0; got != want {
t.Errorf("FileTileStore.Get failed: scale values not matching\n")
dumpTile(getValue2, t)
}
if got, want := getValue2.TileIndex, 0; got != want {
t.Errorf("FileTileStore.Get failed: tile index values not matching\n")
dumpTile(getValue2, t)
}
if got, want := len(getValue2.Traces), 0; got != want {
t.Errorf("FileTileStore.Get failed: traces not matching: Got %d Want %d\n", got, want)
dumpTile(getValue2, t)
}
}
t.Log("Second test set completed.")
// Test its ability to find the last tile, which should be the same as
// the 0th tile, since there's only one tile in storage.
t.Log("Third test set started. Testing last tile Get().")
// Sleep for a few milliseconds to allow the lastTile updater to run.
time.Sleep(3 * time.Millisecond)
getValue3, err := ts.Get(0, -1)
if err != nil {
t.Errorf("FileTileStore.Get failed: %s\n", err)
} else {
if got, want := getValue3.Scale, 0; got != want {
t.Errorf("FileTileStore.Get failed: scale values not matching\n")
dumpTile(getValue3, t)
}
if got, want := getValue3.TileIndex, 0; got != want {
t.Errorf("FileTileStore.Get failed: tile index values not matching\n")
dumpTile(getValue3, t)
}
if got, want := len(getValue3.Traces), 0; got != want {
t.Errorf("FileTileStore.Get failed: traces not matching\n")
dumpTile(getValue3, t)
}
}
t.Log("Third test set completed.")
// Test if it returns an error when there's a request for a nonexistent
// tile.
t.Log("Fourth test set started. Testing non existent tile Get().")
getValue4, err := ts.Get(0, 42)
if err != nil {
t.Errorf("FileTileStore.Get failed on nonexistent tile: %s\n", err)
}
if getValue4 != nil {
t.Errorf("FileTileStore.Get returns nonnil on nonexistent tile: %s\n", err)
dumpTile(getValue4, t)
}
t.Log("Fourth test set completed.")
t.Log("Fifth test start. Testing GetModifiable().")
getValue5, err := ts.GetModifiable(0, 0)
if err != nil {
t.Errorf("FileTileStore.GetModifiable failed: %s\n", err)
} else {
getValue5.TileIndex = 7
getValue5, err := ts.Get(0, 0)
if err != nil {
t.Errorf("FileTileStore.Get failed: %s\n", err)
} else {
if got, want := getValue5.TileIndex, 0; got != want {
t.Errorf("FileTileStore.Get failed: tile index modified via GetModifiable call\n")
}
}
}
t.Log("Fifth test set completed.")
t.Log("Sixth test set start. Testing empty tile Put() and Get().")
if err := ts.Put(0, 0, types.NewTile()); err != nil {
t.Fatalf("Failed to Put(): %s", err)
}
fi, err := os.Stat(filepath.Join(randomPath, TEMP_TILE_DIR_NAME))
if err != nil {
t.Fatalf("Failed to stat directory where temp files are created: %s", err)
}
if !fi.IsDir() {
t.Fatalf("Should be a directory.")
}
_, err = ts.Get(0, 0)
if err != nil {
t.Errorf("FileTileStore.GetModifiable failed: %s\n", err)
}
t.Log("Sixth test set completed.")
}
func dumpTile(tile *types.Tile, t *testing.T) {
if tile != nil {
t.Log(*tile)
t.Log("Traces: ", tile.Traces)
for _, trace := range tile.Traces {
if trace != nil {
t.Log(trace)
} else {
t.Log("nil trace")
}
}
t.Log("ParamSet: ", tile.ParamSet)
for key, val := range tile.ParamSet {
if val != nil {
t.Log(key, ": ", val)
} else {
t.Log(key, ": nil value")
}
}
t.Log("Commits: ", tile.Commits)
for _, commit := range tile.Commits {
if commit != nil {
t.Log(*commit)
} else {
t.Log("nil commit")
}
}
} else {
t.Log("nil tile")
}
}