func TestDigestStore(t *testing.T) {
	assert.Nil(t, os.MkdirAll(TEST_DATA_DIR, 0755))
	defer testutils.RemoveAll(t, TEST_DATA_DIR)

	digestStore, err := New(TEST_DATA_DIR)
	assert.Nil(t, err)
	testDigestStore(t, digestStore)
}
// TestModeHistory verifies that we correctly track mode history.
func TestModeHistory(t *testing.T) {
	testutils.SkipIfShort(t)

	// Create the ModeHistory.
	tmpDir, err := ioutil.TempDir("", "test_autoroll_mode_")
	assert.Nil(t, err)
	defer testutils.RemoveAll(t, tmpDir)
	mh, err := NewModeHistory(path.Join(tmpDir, "test.db"))
	assert.Nil(t, err)
	defer func() {
		assert.Nil(t, mh.Close())
	}()

	// Use this function for checking expectations.
	check := func(expect, actual []*ModeChange) {
		assert.Equal(t, len(expect), len(actual))
		for i, e := range expect {
			assert.Equal(t, e.Mode, actual[i].Mode)
			assert.Equal(t, e.Message, actual[i].Message)
			assert.Equal(t, e.User, actual[i].User)
		}

	}

	// Initial mode, set automatically.
	mc0 := &ModeChange{
		Message: "Setting initial mode.",
		Mode:    MODE_RUNNING,
		User:    "******",
	}

	expect := []*ModeChange{mc0}
	setModeAndCheck := func(mc *ModeChange) {
		assert.Nil(t, mh.Add(mc.Mode, mc.User, mc.Message))
		assert.Equal(t, mc.Mode, mh.CurrentMode())
		expect = append([]*ModeChange{mc}, expect...)
		check(expect, mh.GetHistory())
	}

	// Ensure that we set our initial state properly.
	assert.Equal(t, mc0.Mode, mh.CurrentMode())
	check(expect, mh.GetHistory())

	// Change the mode.
	setModeAndCheck(&ModeChange{
		Message: "Stop the presses!",
		Mode:    MODE_STOPPED,
		User:    "******",
	})

	// Change a few times.
	setModeAndCheck(&ModeChange{
		Message: "Resume!",
		Mode:    MODE_RUNNING,
		User:    "******",
	})
}
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)

	tileBuilder := mocks.NewMockTileBuilderFromJson(t, TEST_DATA_PATH)
	testStatusWatcher(t, tileBuilder)
}
func TestBlamerWithLiveData(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)
	testBlamerWithLiveData(t, tileStore)
}
func TestFileSystemResultFileLocations(t *testing.T) {
	testutils.SkipIfShort(t)

	err := testutils.DownloadTestDataArchive(t, TEST_DATA_STORAGE_PATH, TEST_DATA_DIR)
	assert.Nil(t, err)
	defer testutils.RemoveAll(t, TEST_DATA_DIR)

	src, err := NewFileSystemSource("test-fs-source", TEST_DATA_DIR)
	assert.Nil(t, err)
	testSource(t, src)
}
func TestIngestCommits(t *testing.T) {
	// Get a known Git repo with 34 commits in it setup.
	tr := util.NewTempRepo()
	defer tr.Cleanup()

	// Create a temporary place for a filetilestore.
	tileDir, err := ioutil.TempDir("", "skiaperf")
	if err != nil {
		t.Fatal("Failed to create testing Tile dir: ", err)
	}
	defer testutils.RemoveAll(t, tileDir)

	git, err := gitinfo.NewGitInfo(filepath.Join(tr.Dir, "testrepo"), false, false)
	if err != nil {
		glog.Fatalf("Failed loading Git info: %s\n", err)
	}

	// Construct an Ingestor and have it UpdateCommitInfo.
	i, err := ingester.NewIngester(git, tileDir, config.DATASET_NANO, NewNanoBenchIngester(), 1, time.Second, map[string]string{}, "", "")
	if err != nil {
		t.Fatal("Failed to create ingester:", err)
	}

	if err := i.UpdateCommitInfo(false); err != nil {
		t.Fatal("Failed to ingest commits:", err)
	}

	// Validate the generated Tiles.
	store := filetilestore.NewFileTileStore(tileDir, config.DATASET_NANO, 0)
	if !validator.ValidateDataset(store, false, false) {
		t.Error("Failed to validate the created Tiles:", err)
	}

	// Test TileTracker while were here.
	tt := ingester.NewTileTracker(store, i.HashToNumber())
	err = tt.Move("7a6fe813047d1a84107ef239e81f310f27861473")
	if err != nil {
		t.Fatal(err)
	}
	if got, want := tt.LastTileNum(), 2; got != want {
		t.Errorf("Move failed, wrong tile: Got %d Want %d", got, want)
	}
	err = tt.Move("87709bc360f35de52c2f2bc2fc70962fb234db2d")
	if err != nil {
		t.Fatal(err)
	}
	if got, want := tt.LastTileNum(), 2; got != want {
		t.Errorf("Move failed, wrong tile: Got %d Want %d", got, want)
	}
}
func BenchmarkHistory(b *testing.B) {
	assert.Nil(b, os.MkdirAll(TEST_DATA_DIR, 0755))
	defer testutils.RemoveAll(b, TEST_DATA_DIR)

	digestStore, err := digeststore.New(TEST_DATA_DIR)
	assert.Nil(b, err)

	tileBuilder := mocks.GetTileBuilderFromEnv(b)
	storages := &storage.Storage{
		MasterTileBuilder: tileBuilder,
		DigestStore:       digestStore,
		EventBus:          eventbus.New(nil),
	}

	tile := tileBuilder.GetTile()
	assert.Nil(b, Init(storages, 0))

	// Gather the runtimes of the testname/digest lookup.
	runtimes := make([]int64, 0, 1000000)
	timeIt := func(testName, digest string) (bool, error) {
		startTime := time.Now().UnixNano()
		_, found, err := digestStore.Get(testName, digest)
		runtimes = append(runtimes, (time.Now().UnixNano()-startTime)/1000)
		return found, err
	}

	b.ResetTimer()
	tileLen := tile.LastCommitIndex() + 1
	for _, trace := range tile.Traces {
		testName := trace.Params()[types.PRIMARY_KEY_FIELD]
		gTrace := trace.(*types.GoldenTrace)
		for _, digest := range gTrace.Values[:tileLen] {
			if digest != types.MISSING_DIGEST {
				found, err := timeIt(testName, digest)
				assert.Nil(b, err)
				assert.True(b, found)
			}
		}
	}

	var avg int64 = 0
	for _, val := range runtimes {
		avg += val
	}
	glog.Infof("Average lookup time: %.3fus", float64(avg)/float64(len(runtimes)))
	glog.Infof("Number of lookups  : %d", len(runtimes))
}
// Remove the 'Massive' prefix to run with massive test, takes around 2
// seconds to run.
func MassiveTestAbsPath_45Digests(t *testing.T) {
	defer timeTrack(time.Now(), "MassiveTestAbsPath")

	workingDir := filepath.Join(os.TempDir(), MASSIVE_TESTDATA_DIR)
	assert.Nil(t, os.Mkdir(workingDir, 0777))
	defer testutils.RemoveAll(t, workingDir)
	fds := getTestFileDiffStore(t, MASSIVE_TESTDATA_DIR, true)
	digestsToPaths := fds.AbsPath(
		[]string{MISSING_DIGEST, "0ff8bf090c7bcfa6e1333f1b27de34a2", "0f35601a05e4b70e571d383531d6475d", "0f38c862a94642632a7e1418ce0322dc", "0f422eb209256e4e94442b8bc7216fc4", "0f448bf24d6b1a2d59e8d61ca1864a40", "0f47abec25acbba9fcd8a9fffcc89db4", "0f4d6addbbf439d8a5d43880d06aad2b", "0f50439a1bfcea213b7cb53e64dc8c41", "0f5964ac9eeb3e830c2af590f5a5b417",
			"0f5ab81728a3fc617374dd01b5e9139c", "0f6227320e2ca014e2df9ec9d5b1ea0e", "0f654cb1f795e4f51672474d31e54df7", "0f6fd6ff6db45243f475644cc21675ac", "0f750afae368fc5094e9e2aaf93838dc", "0f77002c0d777a55aad75060a1988054", "0f7c3d2d6daea1e14e262adfd8956703", "0f802ed345aa011b3f645d935f115b5d", "0f81c4c1d4e29887cfe377090bff1e3d",
			"0f87072e6c003766135c40a6665ecd6e", "0f880aa7f6db1e50a6bc532581b52dc8", "0f915b5931e56817287fe5c355439a1a", "0f96f63917f0c62b2c9b8110ff20badc", "0f98bfd192b64eed137f9e6772683365", "0f9aa5700e3ec10bcec5ee74f357cb9d", "0fa1dad80143172942b9ebcb16a41dbf", "0fa50dc22558dc2cc39c48fb5f17f2d0", "0faacf520d0feae4dd7933eabb31d850",
			"0fafdb43076e5667c38ac0864af59142", "0fb0442568f8d9f16da8f26435bfe612", "0fba6eb3b0577c16b76ad84a1bb0f23b", "0fbcd5335eb08911873395c00840b74b", "0fbe8c55504d8a8420c4bef6a9d078f4", "0fc082cb3ca2b72869379c3c053e51c2", "0fc528ee84845f6044e516a1276caa46", "0fc587b905523f45ef287f2f9defb844", "0fcacb142d1517474b8d09b93072f2fc",
			"0fcbc9417b21e95b07f59495c1d8c29e", "0fce6e571aac26038cea582356065e34", "0fd21ebcb59b7f9fde71bc868c2bd77b", "0fdd731115695cc1b6c912ce8ab6e7e6", "0fe58f4a759d46a60198ac1853cb1d43", "0fe7a59b8a3caf68e83ae7fa4abe5052", "0fe88d578a0b1359dbced64a6063c4e9", "0ff48464b23d47af28d8c740507a1212", "0ff864fb2bab5daa74e67fced7eac536"})
	assert.Equal(t, 45, downloadSuccessCount.Count())
	assert.Equal(t, 1, downloadFailureCount.Count())
	assert.Equal(t, 45, len(digestsToPaths))
}
func TestCompareSources(t *testing.T) {
	testutils.SkipIfShort(t)

	gsSource, err := NewGoogleStorageSource("gs-test-src", TEST_GS_BUCKET, TEST_GS_DIR, http.DefaultClient)
	assert.Nil(t, err)

	err = testutils.DownloadTestDataArchive(t, TEST_DATA_STORAGE_PATH, TEST_DATA_DIR)
	assert.Nil(t, err)
	defer testutils.RemoveAll(t, TEST_DATA_DIR)

	fsSource, err := NewFileSystemSource("test-fs-source", TEST_DATA_DIR)
	assert.Nil(t, err)

	gsResults, err := gsSource.Poll(START_TIME, END_TIME)
	assert.Nil(t, err)

	fsResults, err := fsSource.Poll(START_TIME, END_TIME)
	assert.Nil(t, err)

	assert.Equal(t, len(gsResults), len(fsResults))
	sort.Sort(rflSlice(gsResults))
	sort.Sort(rflSlice(fsResults))

	// Only compare a subset of all files to limit the runtime of this test.
	gsResults = gsResults[:10]
	fsResults = fsResults[:10]

	for idx, result := range gsResults {
		// Check if the MD5 from GS and the file system match.
		assert.Equal(t, result.MD5(), fsResults[idx].MD5())

		// Check if the content is the same for both sources.
		file, err := result.Open()
		assert.Nil(t, err)
		c1, err := ioutil.ReadAll(file)
		assert.Nil(t, err)
		file, err = fsResults[idx].Open()
		c2, err := ioutil.ReadAll(file)
		assert.Nil(t, err)
		assert.Equal(t, string(c1), string(c2))
	}
}
func TestMerging(t *testing.T) {
	randomPath, err := ioutil.TempDir("", "mergedtiles_test")
	if err != nil {
		t.Fatalf("Failing to create temporary directory: %s", err)
		return
	}
	defer testutils.RemoveAll(t, 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
	}

	fileName := filepath.Join(randomFullPath, "0000.gob")
	makeFakeTile(t, fileName, &tiling.Tile{
		Traces: map[string]tiling.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: []*tiling.Commit{
			&tiling.Commit{
				CommitTime: 42,
				Hash:       "ffffffffffffffffffffffffffffffffffffffff",
				Author:     "*****@*****.**",
			},
			&tiling.Commit{
				CommitTime: 43,
				Hash:       "eeeeeeeeeee",
				Author:     "*****@*****.**",
			},
			&tiling.Commit{
				CommitTime: 44,
				Hash:       "aaaaaaaaaaa",
				Author:     "*****@*****.**",
			},
		},
		Scale:     0,
		TileIndex: 0,
	})

	ts := filetilestore.NewFileTileStore(randomPath, "test", 10*time.Millisecond)
	m := NewMergedTiles(ts, 2)

	_, err = m.Get(0, 0, 1)
	if err == nil {
		t.Fatalf("Failed to error when requesting a merged tile that doesn't exist: %s", err)
	}

	fileName = filepath.Join(randomFullPath, "0001.gob")
	makeFakeTile(t, fileName, &tiling.Tile{
		Traces: map[string]tiling.Trace{},
		ParamSet: map[string][]string{
			"test": []string{"parameter"},
		},
		Commits: []*tiling.Commit{
			&tiling.Commit{
				CommitTime: 45,
				Hash:       "0000000000000000000000000000000000000000",
				Author:     "*****@*****.**",
			},
		},
		Scale:     0,
		TileIndex: 0,
	})

	_, err = m.Get(0, 0, 1)
	if err != nil {
		t.Fatalf("Failed to error when requesting a merged tile that doesn't exist: %s", err)
	}
}