blob: c771f9f9f40a367bf7504088c1068a66ee816700 [file]
package status
import (
"math/rand"
"os"
"testing"
"time"
assert "github.com/stretchr/testify/require"
"go.skia.org/infra/go/eventbus"
"go.skia.org/infra/go/testutils"
"go.skia.org/infra/golden/go/digeststore"
"go.skia.org/infra/golden/go/expstorage"
"go.skia.org/infra/golden/go/mocks"
"go.skia.org/infra/golden/go/storage"
"go.skia.org/infra/golden/go/types"
pconfig "go.skia.org/infra/perf/go/config"
"go.skia.org/infra/perf/go/filetilestore"
ptypes "go.skia.org/infra/perf/go/types"
)
var (
// Directory with testdata.
TEST_DATA_DIR = "./testdata"
// Local file location of the test data.
TEST_DATA_PATH = TEST_DATA_DIR + "/goldentile.json.zip"
// Folder in the testdata bucket. See go/testutils for details.
TEST_DATA_STORAGE_PATH = "gold-testdata/goldentile.json.gz"
)
func TestStatusWatcher(t *testing.T) {
testutils.SkipIfShort(t)
err := testutils.DownloadTestDataFile(t, TEST_DATA_STORAGE_PATH, TEST_DATA_PATH)
assert.Nil(t, err, "Unable to download testdata.")
defer testutils.RemoveAll(t, TEST_DATA_DIR)
tileStore := mocks.NewMockTileStoreFromJson(t, TEST_DATA_PATH)
testStatusWatcher(t, tileStore)
}
func BenchmarkStatusWatcher(b *testing.B) {
// Get the TEST_TILE environment variable that points to the
// tile to read.
tileDir := os.Getenv("TEST_TILE_DIR")
assert.NotEqual(b, "", tileDir, "Please define the TEST_TILE_DIR environment variable to point to a live tile store.")
tileStore := filetilestore.NewFileTileStore(tileDir, pconfig.DATASET_GOLD, 2*time.Minute)
storages := &storage.Storage{
TileStore: tileStore,
}
// Load the tile into memory and reset the timer to avoid measuring
// disk load time.
_, err := storages.GetLastTileTrimmed(true)
assert.Nil(b, err)
b.ResetTimer()
testStatusWatcher(b, tileStore)
}
func testStatusWatcher(t assert.TestingT, tileStore ptypes.TileStore) {
eventBus := eventbus.New()
storages := &storage.Storage{
ExpectationsStore: expstorage.NewMemExpectationsStore(eventBus),
TileStore: tileStore,
DigestStore: &MockDigestStore{},
EventBus: eventBus,
}
watcher, err := New(storages)
assert.Nil(t, err)
// Go through all corpora and change all the Items to positive.
status := watcher.GetStatus()
assert.NotNil(t, status)
for idx, corpStatus := range status.CorpStatus {
// Make sure no digests has any issues attached.
storages.DigestStore.(*MockDigestStore).issueIDs = nil
assert.False(t, corpStatus.OK)
tile, err := storages.GetLastTileTrimmed(true)
assert.Nil(t, err)
changes := map[string]types.TestClassification{}
posOrNeg := []types.Label{types.POSITIVE, types.NEGATIVE}
for _, trace := range tile.Traces {
if trace.Params()[types.CORPUS_FIELD] == corpStatus.Name {
gTrace := trace.(*ptypes.GoldenTrace)
testName := gTrace.Params()[types.PRIMARY_KEY_FIELD]
for _, digest := range gTrace.Values {
if _, ok := changes[testName]; !ok {
changes[testName] = map[string]types.Label{}
}
changes[testName][digest] = posOrNeg[rand.Int()%2]
}
}
}
// Update the expecations and wait for the status to change.
assert.Nil(t, storages.ExpectationsStore.AddChange(changes, ""))
time.Sleep(1 * time.Second)
newStatus := watcher.GetStatus()
assert.False(t, newStatus.CorpStatus[idx].OK)
assert.False(t, newStatus.OK)
// Make sure all tests have an issue attached to each DigestInfo and
// trigger another expectations update.
storages.DigestStore.(*MockDigestStore).issueIDs = []int{1}
assert.Nil(t, storages.ExpectationsStore.AddChange(changes, ""))
time.Sleep(1 * time.Second)
// Make sure the current corpus is now ok.
newStatus = watcher.GetStatus()
assert.True(t, newStatus.CorpStatus[idx].OK)
}
// All corpora are ok therefore the overall status should be ok.
newStatus := watcher.GetStatus()
assert.True(t, newStatus.OK)
}
type MockDigestStore struct {
issueIDs []int
}
func (m *MockDigestStore) Get(testName, digest string) (*digeststore.DigestInfo, bool, error) {
return &digeststore.DigestInfo{
IssueIDs: m.issueIDs,
}, true, nil
}
func (m *MockDigestStore) Update([]*digeststore.DigestInfo) error {
return nil
}