Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1005)

Unified Diff: build_scheduler/go/db/local_db/local_db_test.go

Issue 2246933002: Add Task DB implementation using a local BoltDB. (Closed) Base URL: https://skia.googlesource.com/buildbot@taskdb-impl-track
Patch Set: Fix bad merge. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: build_scheduler/go/db/local_db/local_db_test.go
diff --git a/build_scheduler/go/db/local_db/local_db_test.go b/build_scheduler/go/db/local_db/local_db_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..1bb30a9361de6bfee1517cf7d838f933a0634a0e
--- /dev/null
+++ b/build_scheduler/go/db/local_db/local_db_test.go
@@ -0,0 +1,236 @@
+package local_db
+
+import (
+ "io/ioutil"
+ "path/filepath"
+ "sort"
+ "testing"
+ "time"
+
+ assert "github.com/stretchr/testify/require"
+ "go.skia.org/infra/build_scheduler/go/db"
+ "go.skia.org/infra/go/testutils"
+ "go.skia.org/infra/go/util"
+)
+
+// Check that formatId and parseId are inverse operations and produce the
+// expected result.
+func TestFormatParseId(t *testing.T) {
+ testCases := []struct {
+ ts time.Time
+ seq uint64
+ id string
+ }{
+ {
+ ts: time.Date(2009, time.November, 10, 23, 45, 6, 1500, time.UTC),
+ seq: 0,
+ id: "20091110T234506.000001500Z_0000000000000000",
+ },
+ {
+ ts: time.Date(2001, time.February, 3, 4, 5, 6, 0, time.FixedZone("fake", 45*60)),
+ seq: 1,
+ // Subtract 45 minutes due to zone.
+ id: "20010203T032006.000000000Z_0000000000000001",
+ },
+ {
+ ts: time.Date(2001, time.January, 1, 1, 1, 1, 100000000, time.UTC),
+ seq: 15,
+ id: "20010101T010101.100000000Z_000000000000000f",
+ },
+ {
+ ts: time.Date(2001, time.January, 1, 1, 1, 1, 100000000, time.UTC),
+ seq: 16,
+ id: "20010101T010101.100000000Z_0000000000000010",
+ },
+ {
+ ts: time.Date(2001, time.January, 1, 1, 1, 1, 100000000, time.UTC),
+ seq: 255,
+ id: "20010101T010101.100000000Z_00000000000000ff",
+ },
+ {
+ ts: time.Date(2001, time.January, 1, 1, 1, 1, 100000000, time.UTC),
+ seq: 0xFFFFFFFFFFFFFFFF,
+ id: "20010101T010101.100000000Z_ffffffffffffffff",
+ },
+ }
+ for _, testCase := range testCases {
+ assert.Equal(t, testCase.id, formatId(testCase.ts, testCase.seq))
+ ts, seq, err := parseId(testCase.id)
+ assert.NoError(t, err)
+ assert.True(t, testCase.ts.Equal(ts))
+ assert.Equal(t, testCase.seq, seq)
+ assert.Equal(t, time.UTC, ts.Location())
+ }
+
+ // Invalid timestamps:
+ for _, invalidId := range []string{
+ // Missing seq num.
+ "20091110T234506.000001500Z",
+ // Two-digit year.
+ "091110T234506.000001500Z_0000000000000000",
+ // Invalid month.
+ "20010001T010101.100000000Z_000000000000000f",
+ // Missing T.
+ "20010101010101.100000000Z_000000000000000f",
+ // Missing Z.
+ "20010101T010101.100000000_000000000000000f",
+ // Empty seq num.
+ "20010101T010101.100000000Z_",
+ // Invalid char in seq num.
+ "20010101T010101.100000000Z_000000000000000g",
+ // Invalid char in seq num.
+ "20010101T010101.100000000Z_g000000000000000",
+ // Empty timestamp.
+ "_000000000000000f",
+ // Sequence num overflows.
+ "20010101T010101.100000000Z_1ffffffffffffffff",
+ } {
+ _, _, err := parseId(invalidId)
+ assert.Error(t, err, "No error for Id: %q", invalidId)
+ }
+}
+
+// Create a localDB for testing. Call defer util.RemoveAll() on the second
+// return value.
+func makeDB(t *testing.T, name string) (db.DB, string) {
+ //testutils.SkipIfShort(t)
+ tmpdir, err := ioutil.TempDir("", name)
+ assert.NoError(t, err)
+ d, err := NewDB(name, filepath.Join(tmpdir, "task.db"))
+ assert.NoError(t, err)
+ return d, tmpdir
+}
+
+// Test that AssignId returns an error if Id is set.
+func TestAssignIdAlreadyAssigned(t *testing.T) {
+ d, tmpdir := makeDB(t, "TestAssignIdsFromCreatedTs")
+ defer util.RemoveAll(tmpdir)
+ defer testutils.AssertCloses(t, d)
+
+ task := &db.Task{}
+ assert.NoError(t, d.AssignId(task))
+ assert.Error(t, d.AssignId(task))
+}
+
+// Test that AssignId uses created timestamp when set, and generates unique IDs
+// for the same timestamp.
+func TestAssignIdsFromCreatedTs(t *testing.T) {
+ d, tmpdir := makeDB(t, "TestAssignIdsFromCreatedTs")
+ defer util.RemoveAll(tmpdir)
+ defer testutils.AssertCloses(t, d)
+
+ tasks := []*db.Task{}
+ addTask := func(ts time.Time) {
+ task := &db.Task{
+ Created: ts,
+ }
+ assert.NoError(t, d.AssignId(task))
+ tasks = append(tasks, task)
+ }
+
+ // Add tasks with various creation timestamps.
+ addTask(time.Date(2008, time.August, 8, 8, 8, 8, 8, time.UTC))
+ addTask(time.Date(1776, time.July, 4, 13, 0, 0, 0, time.UTC))
+ addTask(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC))
+ addTask(time.Date(2016, time.December, 31, 23, 59, 59, 999999999, time.UTC))
+ // Repeated timestamps.
+ addTask(time.Date(2008, time.August, 8, 8, 8, 8, 8, time.UTC))
+ addTask(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC))
+ for i := 0; i < 256; i++ {
+ addTask(time.Date(2008, time.August, 8, 8, 8, 8, 8, time.UTC))
+ }
+
+ // Collect IDs. Assert Id is set.
+ ids := make([]string, 0, len(tasks))
+ for _, task := range tasks {
+ assert.NotEqual(t, "", task.Id)
+ ids = append(ids, task.Id)
+ }
+
+ // Stable-sort tasks.
+ sort.Stable(db.TaskSlice(tasks))
+
+ // Sort IDs.
+ sort.Strings(ids)
+
+ // Validate that sorted IDs match sorted Tasks. Check that there are no
+ // duplicate IDs. Check that ID timestamp matches created timestamp.
+ prevId := ""
+ for i := 0; i < len(tasks); i++ {
+ assert.Equal(t, ids[i], tasks[i].Id)
+ assert.NotEqual(t, prevId, ids[i])
+ ts, _, err := parseId(ids[i])
+ assert.NoError(t, err)
+ assert.True(t, ts.Equal(tasks[i].Created))
+ prevId = ids[i]
+ }
+}
+
+// Test that AssignId can generate ids when created timestamp is not set, and
+// generates unique IDs for PutTasks.
+func TestAssignIdsFromCurrentTime(t *testing.T) {
+ d, tmpdir := makeDB(t, "TestAssignIdsFromCreatedTs")
+ defer util.RemoveAll(tmpdir)
+ defer testutils.AssertCloses(t, d)
+
+ tasks := []*db.Task{}
+ for i := 0; i < 260; i++ {
+ tasks = append(tasks, &db.Task{})
+ }
+
+ begin := time.Now()
+
+ // Test AssignId.
+ assert.NoError(t, d.AssignId(tasks[5]))
+ assert.NoError(t, d.AssignId(tasks[6]))
+ id5, id6 := tasks[5].Id, tasks[6].Id
+
+ // Test PutTasks.
+ assert.NoError(t, d.PutTasks(tasks))
+
+ end := time.Now()
+
+ // Check that PutTasks did not change existing Ids.
+ assert.Equal(t, id5, tasks[5].Id)
+ assert.Equal(t, id6, tasks[6].Id)
+
+ // Order tasks by time of ID assignment.
+ first2 := []*db.Task{tasks[5], tasks[6]}
+ copy(tasks[2:7], tasks[0:5])
+ copy(tasks[0:2], first2)
+
+ // Collect IDs. Assert Id is set.
+ ids := make([]string, 0, len(tasks))
+ for _, task := range tasks {
+ assert.NotEqual(t, "", task.Id)
+ ids = append(ids, task.Id)
+ }
+
+ // Sort IDs.
+ sort.Strings(ids)
+
+ // Validate that sorted IDs match Tasks by insertion order. Check that there
+ // are no duplicate IDs. Check that begin <= ID timestamp <= end.
+ prevId := ""
+ for i := 0; i < len(tasks); i++ {
+ assert.Equal(t, ids[i], tasks[i].Id)
+ assert.NotEqual(t, prevId, ids[i])
+ ts, _, err := parseId(ids[i])
+ assert.NoError(t, err)
+ assert.True(t, begin.Before(ts) || begin.Equal(ts))
+ assert.True(t, ts.Before(end) || ts.Equal(end))
+ prevId = ids[i]
+ }
+}
+
+func TestLocalDB(t *testing.T) {
+ d, tmpdir := makeDB(t, "TestLocalDB")
+ defer util.RemoveAll(tmpdir)
+ db.TestDB(t, d)
+}
+
+func TestLocalDBTooManyUsers(t *testing.T) {
+ d, tmpdir := makeDB(t, "TestLocalDBTooManyUsers")
+ defer util.RemoveAll(tmpdir)
+ db.TestTooManyUsers(t, d)
+}

Powered by Google App Engine
This is Rietveld 408576698