From 492eb3031609abab12a5e65ef0d369dbe3833d34 Mon Sep 17 00:00:00 2001
From: Gabriel Handford
Date: Mon, 20 Jul 2020 11:58:51 -0700
Subject: [PATCH] events: Timestamp (ms)
---
docs/document_test.go | 8 +++----
docs/events/events.go | 3 +--
docs/events/events_test.go | 21 +++++++++----------
docs/mem.go | 15 ++++++-------
docs/mem_test.go | 8 +++----
sigchainstore.go | 23 +++++++-------------
sigchainstore_test.go | 4 ++--
tsutil/clock.go | 43 +++++++++++++++++++++++++++-----------
user/search_test.go | 24 ++++++++++-----------
9 files changed, 80 insertions(+), 69 deletions(-)
diff --git a/docs/document_test.go b/docs/document_test.go
index 7e8516e..f3195b1 100644
--- a/docs/document_test.go
+++ b/docs/document_test.go
@@ -16,21 +16,21 @@ import (
)
func TestDocument(t *testing.T) {
- db := docs.NewMem()
+ mem := docs.NewMem()
clock := tsutil.NewTestClock()
- db.SetTimeNow(clock.Now)
+ mem.SetClock(clock)
ctx := context.TODO()
paths := []string{}
for i := 0; i < 4; i++ {
p := docs.Path("test", strconv.Itoa(i))
- err := db.Create(ctx, p, []byte(fmt.Sprintf("value%d", i)))
+ err := mem.Create(ctx, p, []byte(fmt.Sprintf("value%d", i)))
require.NoError(t, err)
paths = append(paths, p)
}
sort.Strings(paths)
- iter, err := db.DocumentIterator(ctx, "test")
+ iter, err := mem.DocumentIterator(ctx, "test")
require.NoError(t, err)
out1, err := iter.Next()
require.NoError(t, err)
diff --git a/docs/events/events.go b/docs/events/events.go
index c9d9cb2..d495c54 100644
--- a/docs/events/events.go
+++ b/docs/events/events.go
@@ -2,7 +2,6 @@ package events
import (
"context"
- "time"
)
// Event in an event log.
@@ -16,7 +15,7 @@ type Event struct {
Index int64 `json:"idx" msgpack:"idx" firestore:"idx"`
// Timestamp (read only). The time at which the event was created.
// Firestore sets this to the document create time.
- Timestamp time.Time `json:"ts" msgpack:"ts" firestore:"-"`
+ Timestamp int64 `json:"ts" msgpack:"ts" firestore:"-"`
}
// Events describes an append only event log.
diff --git a/docs/events/events_test.go b/docs/events/events_test.go
index 3c332ce..1581bcb 100644
--- a/docs/events/events_test.go
+++ b/docs/events/events_test.go
@@ -20,7 +20,7 @@ func TestEvents(t *testing.T) {
// keys.SetLogger(keys.NewLogger(keys.DebugLevel))
eds := docs.NewMem()
clock := tsutil.NewTestClock()
- eds.SetTimeNow(clock.Now)
+ eds.SetClock(clock)
ctx := context.TODO()
path := docs.Path("test", "eds")
@@ -37,7 +37,7 @@ func TestEvents(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 40, len(out))
for i, event := range out {
- require.False(t, event.Timestamp.IsZero())
+ require.NotEmpty(t, event.Timestamp)
require.Equal(t, int64(i+1), event.Index)
}
@@ -52,7 +52,7 @@ func TestEvents(t *testing.T) {
if event == nil {
break
}
- require.False(t, event.Timestamp.IsZero())
+ require.NotEmpty(t, event.Timestamp)
require.Equal(t, int64(i+1), event.Index)
eventsValues = append(eventsValues, string(event.Data))
index = event.Index
@@ -159,25 +159,24 @@ func TestEventMarshal(t *testing.T) {
event := events.Event{
Data: []byte{0x01, 0x02, 0x03},
Index: 123,
- Timestamp: clock.Now(),
+ Timestamp: tsutil.Millis(clock.Now()),
}
out, err := msgpack.Marshal(event)
require.NoError(t, err)
- expected := `([]uint8) (len=36 cap=64) {
+ expected := `([]uint8) (len=35 cap=64) {
00000000 83 a3 64 61 74 c4 03 01 02 03 a3 69 64 78 d3 00 |..dat......idx..|
- 00000010 00 00 00 00 00 00 7b a2 74 73 d7 ff 00 3d 09 00 |......{.ts...=..|
- 00000020 49 96 02 d2 |I...|
+ 00000010 00 00 00 00 00 00 7b a2 74 73 d3 00 00 01 1f 71 |......{.ts.....q|
+ 00000020 fb 04 51 |..Q|
}
`
require.Equal(t, expected, spew.Sdump(out))
out, err = json.Marshal(event)
require.NoError(t, err)
- expected = `([]uint8) (len=57 cap=64) {
+ expected = `([]uint8) (len=44 cap=48) {
00000000 7b 22 64 61 74 61 22 3a 22 41 51 49 44 22 2c 22 |{"data":"AQID","|
- 00000010 69 64 78 22 3a 31 32 33 2c 22 74 73 22 3a 22 32 |idx":123,"ts":"2|
- 00000020 30 30 39 2d 30 32 2d 31 33 54 32 33 3a 33 31 3a |009-02-13T23:31:|
- 00000030 33 30 2e 30 30 31 5a 22 7d |30.001Z"}|
+ 00000010 69 64 78 22 3a 31 32 33 2c 22 74 73 22 3a 31 32 |idx":123,"ts":12|
+ 00000020 33 34 35 36 37 38 39 30 30 30 31 7d |34567890001}|
}
`
require.Equal(t, expected, spew.Sdump(out))
diff --git a/docs/mem.go b/docs/mem.go
index dca7b4a..486e62c 100644
--- a/docs/mem.go
+++ b/docs/mem.go
@@ -11,6 +11,7 @@ import (
"github.com/keys-pub/keys/docs/events"
"github.com/keys-pub/keys/encoding"
+ "github.com/keys-pub/keys/tsutil"
"github.com/pkg/errors"
)
@@ -23,7 +24,7 @@ type Mem struct {
paths *StringSet
values map[string][]byte
metadata map[string]*metadata
- nowFn func() time.Time
+ clock tsutil.Clock
inc map[string]int64
}
@@ -39,18 +40,18 @@ func NewMem() *Mem {
values: map[string][]byte{},
metadata: map[string]*metadata{},
inc: map[string]int64{},
- nowFn: time.Now,
+ clock: tsutil.NewClock(),
}
}
// Now returns current time.
func (m *Mem) Now() time.Time {
- return m.nowFn()
+ return m.clock.Now()
}
-// SetTimeNow to use a custom time.Now.
-func (m *Mem) SetTimeNow(nowFn func() time.Time) {
- m.nowFn = nowFn
+// SetClock to use a custom Clock (for testing).
+func (m *Mem) SetClock(clock tsutil.Clock) {
+ m.clock = clock
}
// Create at path.
@@ -301,7 +302,7 @@ func (m *Mem) EventsAdd(ctx context.Context, path string, data [][]byte) ([]*eve
event := &events.Event{
Data: b,
Index: inc,
- Timestamp: m.nowFn(),
+ Timestamp: tsutil.Millis(m.clock.Now()),
}
b, err := json.Marshal(event)
if err != nil {
diff --git a/docs/mem_test.go b/docs/mem_test.go
index 1c35003..0ef05fc 100644
--- a/docs/mem_test.go
+++ b/docs/mem_test.go
@@ -23,19 +23,19 @@ func TestClock(t *testing.T) {
func TestMem(t *testing.T) {
mem := docs.NewMem()
- mem.SetTimeNow(tsutil.NewTestClock().Now)
+ mem.SetClock(tsutil.NewTestClock())
testDocumentStore(t, mem)
}
func TestMemListOptions(t *testing.T) {
mem := docs.NewMem()
- mem.SetTimeNow(tsutil.NewTestClock().Now)
+ mem.SetClock(tsutil.NewTestClock())
testDocumentStoreListOptions(t, mem)
}
func TestMemMetadata(t *testing.T) {
mem := docs.NewMem()
- mem.SetTimeNow(tsutil.NewTestClock().Now)
+ mem.SetClock(tsutil.NewTestClock())
testMetadata(t, mem)
}
@@ -143,7 +143,7 @@ func testDocumentStore(t *testing.T, ds docs.Documents) {
func TestDocumentStorePath(t *testing.T) {
ds := docs.NewMem()
- ds.SetTimeNow(tsutil.NewTestClock().Now)
+ ds.SetClock(tsutil.NewTestClock())
ctx := context.TODO()
err := ds.Create(ctx, "test/1", []byte("value1"))
diff --git a/sigchainstore.go b/sigchainstore.go
index bb374ab..a4a780a 100644
--- a/sigchainstore.go
+++ b/sigchainstore.go
@@ -4,9 +4,9 @@ import (
"context"
"encoding/json"
"strings"
- "time"
"github.com/keys-pub/keys/docs"
+ "github.com/keys-pub/keys/tsutil"
"github.com/pkg/errors"
)
@@ -26,18 +26,16 @@ type SigchainStore interface {
// SigchainExists if true, has sigchain.
SigchainExists(kid ID) (bool, error)
- // Now is current time.
- Now() time.Time
- // SetTimeNow sets clock.
- SetTimeNow(nowFn func() time.Time)
+ // SetClock sets custom Clock.
+ SetClock(clock tsutil.Clock)
}
type sigchainStore struct {
ds docs.Documents
- nowFn func() time.Time
+ clock tsutil.Clock
}
-// NewSigchainStore creates a SigchainStore from a DocumentStore.
+// NewSigchainStore creates a SigchainStore from Documents.
func NewSigchainStore(ds docs.Documents) SigchainStore {
return newSigchainStore(ds)
}
@@ -45,18 +43,13 @@ func NewSigchainStore(ds docs.Documents) SigchainStore {
func newSigchainStore(ds docs.Documents) *sigchainStore {
return &sigchainStore{
ds: ds,
- nowFn: time.Now,
+ clock: tsutil.NewClock(),
}
}
-// Now returns current time.
-func (s sigchainStore) Now() time.Time {
- return s.nowFn()
-}
-
// SetTimeNow to use a custom time.Now.
-func (s sigchainStore) SetTimeNow(nowFn func() time.Time) {
- s.nowFn = nowFn
+func (s sigchainStore) SetClock(clock tsutil.Clock) {
+ s.clock = clock
}
func (s sigchainStore) KIDs() ([]ID, error) {
diff --git a/sigchainstore_test.go b/sigchainstore_test.go
index d6f6d67..b6b4b25 100644
--- a/sigchainstore_test.go
+++ b/sigchainstore_test.go
@@ -11,9 +11,9 @@ import (
func testSigchainStore(t *testing.T, clock tsutil.Clock) keys.SigchainStore {
mem := docs.NewMem()
- mem.SetTimeNow(clock.Now)
+ mem.SetClock(clock)
scs := keys.NewSigchainStore(mem)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
return scs
}
diff --git a/tsutil/clock.go b/tsutil/clock.go
index bf6dc10..59e98c0 100644
--- a/tsutil/clock.go
+++ b/tsutil/clock.go
@@ -2,13 +2,6 @@ package tsutil
import "time"
-// clock increments a millisecond on each access.
-// This is for testing.
-type clock struct {
- t time.Time
- tick time.Duration
-}
-
// Clock returns time.Time.
type Clock interface {
// Now returns current clock time.
@@ -18,37 +11,63 @@ type Clock interface {
Add(dt time.Duration)
}
+// testClock increments a millisecond on each access.
+// This is for testing.
+type testClock struct {
+ t time.Time
+ tick time.Duration
+}
+
// NewTestClock returns a test Clock starting at 1234567890000 millseconds since
// epoch. Each access to Now() increases time by 1 millisecond.
func NewTestClock() Clock {
t := ConvertMillis(1234567890000)
- return &clock{
+ return &testClock{
t: t,
tick: time.Millisecond,
}
}
// Now returns current clock time.
-func (c *clock) Now() time.Time {
+func (c *testClock) Now() time.Time {
c.t = c.t.Add(c.tick)
return c.t
}
// SetTick sets tick increment for clock.
-func (c *clock) SetTick(tick time.Duration) {
+func (c *testClock) SetTick(tick time.Duration) {
c.tick = tick
}
// Add to clock.
-func (c *clock) Add(dt time.Duration) {
+func (c *testClock) Add(dt time.Duration) {
c.t = c.t.Add(dt)
}
// NewTestClockAt creates a Clock starting at timestamp (millis).
func NewTestClockAt(ts int64) Clock {
t := ConvertMillis(ts)
- return &clock{
+ return &testClock{
t: t,
tick: time.Millisecond,
}
}
+
+// NewClock returns current clock time.
+func NewClock() Clock {
+ return &clock{
+ add: time.Duration(0),
+ }
+}
+
+type clock struct {
+ add time.Duration
+}
+
+func (c *clock) Now() time.Time {
+ return time.Now().Add(c.add)
+}
+
+func (c *clock) Add(dt time.Duration) {
+ c.add = c.add + dt
+}
diff --git a/user/search_test.go b/user/search_test.go
index 6198cb9..8595c10 100644
--- a/user/search_test.go
+++ b/user/search_test.go
@@ -22,9 +22,9 @@ func TestSearchUsers(t *testing.T) {
clock := tsutil.NewTestClock()
ds := docs.NewMem()
- ds.SetTimeNow(clock.Now)
+ ds.SetClock(clock)
scs := keys.NewSigchainStore(ds)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
req := request.NewMockRequestor()
ust := testStore(t, ds, scs, req, clock)
@@ -152,9 +152,9 @@ func TestSearchUsers(t *testing.T) {
func TestUserStoreEmpty(t *testing.T) {
clock := tsutil.NewTestClock()
ds := docs.NewMem()
- ds.SetTimeNow(clock.Now)
+ ds.SetClock(clock)
scs := keys.NewSigchainStore(ds)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
req := request.NewMockRequestor()
ust := testStore(t, ds, scs, req, clock)
@@ -175,9 +175,9 @@ func TestUserStoreEmpty(t *testing.T) {
func TestUserValidateName(t *testing.T) {
clock := tsutil.NewTestClock()
ds := docs.NewMem()
- ds.SetTimeNow(clock.Now)
+ ds.SetClock(clock)
scs := keys.NewSigchainStore(ds)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
req := request.NewMockRequestor()
ust := testStore(t, ds, scs, req, clock)
@@ -204,9 +204,9 @@ func TestUserValidateName(t *testing.T) {
func TestUserValidateUpdateInvalid(t *testing.T) {
clock := tsutil.NewTestClock()
ds := docs.NewMem()
- ds.SetTimeNow(clock.Now)
+ ds.SetClock(clock)
scs := keys.NewSigchainStore(ds)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
req := request.NewMockRequestor()
ust := testStore(t, ds, scs, req, clock)
@@ -254,9 +254,9 @@ func TestUserValidateUpdateInvalid(t *testing.T) {
func TestReddit(t *testing.T) {
clock := tsutil.NewTestClock()
ds := docs.NewMem()
- ds.SetTimeNow(clock.Now)
+ ds.SetClock(clock)
scs := keys.NewSigchainStore(ds)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
req := request.NewMockRequestor()
ust := testStore(t, ds, scs, req, clock)
@@ -309,9 +309,9 @@ func TestSearchUsersRequestErrors(t *testing.T) {
clock := tsutil.NewTestClock()
ds := docs.NewMem()
- ds.SetTimeNow(clock.Now)
+ ds.SetClock(clock)
scs := keys.NewSigchainStore(ds)
- scs.SetTimeNow(clock.Now)
+ scs.SetClock(clock)
req := request.NewMockRequestor()
ust := testStore(t, ds, scs, req, clock)