Skip to content

Commit

Permalink
Prepare for clockwork v0.5.0 (#51292)
Browse files Browse the repository at this point in the history
* Introduce the clocki package

* Do root module fixes so e/ can be built

* Use clocki in lib/backend tests

* Genericfy test.Constructor and related methods
  • Loading branch information
codingllama authored Jan 23, 2025
1 parent e04b9fb commit 1f7b09f
Show file tree
Hide file tree
Showing 20 changed files with 145 additions and 49 deletions.
10 changes: 4 additions & 6 deletions lib/auth/helpers_mfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/auth/mocku2f"
wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes"
"github.com/gravitational/teleport/lib/utils/clocki"
)

// TestDevice is a test MFA device.
Expand Down Expand Up @@ -190,9 +191,8 @@ func (d *TestDevice) solveAuthnTOTP(c *proto.MFAAuthenticateChallenge) (*proto.M
if d.clock == nil {
return nil, trace.BadParameter("clock not set")
}
if c, ok := d.clock.(clockwork.FakeClock); ok {
c.Advance(30 * time.Second)
}
clocki.Advance(d.clock, 30*time.Second)

code, err := totp.GenerateCode(d.TOTPSecret, d.clock.Now())
if err != nil {
return nil, trace.Wrap(err)
Expand Down Expand Up @@ -244,9 +244,7 @@ func (d *TestDevice) solveRegisterTOTP(c *proto.MFARegisterChallenge) (*proto.MF
if d.clock == nil {
return nil, trace.BadParameter("clock not set")
}
if c, ok := d.clock.(clockwork.FakeClock); ok {
c.Advance(30 * time.Second)
}
clocki.Advance(d.clock, 30*time.Second)

if c.GetTOTP().Algorithm != otp.AlgorithmSHA1.String() {
return nil, trace.BadParameter("unexpected TOTP challenge algorithm: %s", c.GetTOTP().Algorithm)
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/dynamo/atomicwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ import (

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func newAtomicWriteBackend(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func newAtomicWriteBackend(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
dynamoCfg := map[string]interface{}{
"table_name": dynamoDBTestTable(),
"poll_stream_period": 300 * time.Millisecond,
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/dynamo/dynamodbbk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func TestMain(m *testing.M) {
Expand Down Expand Up @@ -74,7 +75,7 @@ func TestDynamoDB(t *testing.T) {
"poll_stream_period": 300 * time.Millisecond,
}

newBackend := func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
testCfg, err := test.ApplyOptions(options)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
4 changes: 2 additions & 2 deletions lib/backend/etcdbk/atomicwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ import (
"testing"

"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils/clocki"
)

// newAtomicWriteTestBackend builds a backend suitable for the atomic write test suite. Once all backends implement AtomicWrite,
// it will be integrated into the main backend interface and we can get rid of this separate helper.
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
opts, err := test.ApplyOptions(options)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
4 changes: 2 additions & 2 deletions lib/backend/etcdbk/etcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ import (
"time"

"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/clocki"
)

const (
Expand Down Expand Up @@ -65,7 +65,7 @@ func TestEtcd(t *testing.T) {
t.Skip("This test requires etcd, run `make run-etcd` and set TELEPORT_ETCD_TEST=yes in your environment")
}

newBackend := func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
opts, err := test.ApplyOptions(options)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/firestore/atomicwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ import (

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
cfg := firestoreParams()

testCfg, err := test.ApplyOptions(options)
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/firestore/firestorebk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import (
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func TestMain(m *testing.M) {
Expand Down Expand Up @@ -126,7 +127,7 @@ func TestFirestoreDB(t *testing.T) {
ensureTestsEnabled(t)
ensureEmulatorRunning(t, cfg)

newBackend := func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
testCfg, err := test.ApplyOptions(options)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
5 changes: 3 additions & 2 deletions lib/backend/lite/atomicwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ import (

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils/clocki"
)

// newAtomicWriteTestBackendBuilder builds a backend suitable for the atomic write test suite. Once all backends implement AtomicWrite,
// it will be integrated into the main backend interface and we can get rid of this separate helper.
func newAtomicWriteTestBackendBuilder(t *testing.T) func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
return func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func newAtomicWriteTestBackendBuilder(t *testing.T) test.Constructor[clocki.FakeClock] {
return func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
clock := clockwork.NewFakeClock()

cfg, err := test.ApplyOptions(options)
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/lite/lite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func TestMain(m *testing.M) {
Expand All @@ -39,7 +40,7 @@ func TestMain(m *testing.M) {
}

func TestLite(t *testing.T) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
clock := clockwork.NewFakeClock()

cfg, err := test.ApplyOptions(options)
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/memory/atomicwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ import (

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils/clocki"
)

// newAtomicWriteTestBackend builds a backend suitable for the atomic write test suite. Once all backends implement AtomicWrite,
// it will be integrated into the main backend interface and we can get rid of this separate helper.
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
cfg, err := test.ApplyOptions(options)

if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/memory/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func TestMain(m *testing.M) {
Expand All @@ -40,7 +41,7 @@ func TestMain(m *testing.M) {
}

func TestMemory(t *testing.T) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
cfg, err := test.ApplyOptions(options)

if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/pgbk/atomicwrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils/clocki"
)

// Testing requires a local psql backend to be set up, and for params to be passed via env. Ex:
Expand All @@ -37,7 +38,7 @@ import (

// newAtomicWriteTestBackend builds a backend suitable for the atomic write test suite. Once all backends implement AtomicWrite,
// it will be integrated into the main backend interface and we can get rid of this separate helper.
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func newAtomicWriteTestBackend(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
testCfg, err := test.ApplyOptions(options)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
3 changes: 2 additions & 1 deletion lib/backend/pgbk/pgbk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/backend/test"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func TestMain(m *testing.M) {
Expand All @@ -47,7 +48,7 @@ func TestPostgresBackend(t *testing.T) {
t.Skip("Postgres backend tests are disabled. Enable them by setting the TELEPORT_PGBK_TEST_PARAMS_JSON variable.")
}

newBackend := func(options ...test.ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
newBackend := func(options ...test.ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
testCfg, err := test.ApplyOptions(options)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
15 changes: 8 additions & 7 deletions lib/backend/test/atomicwrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ import (
"golang.org/x/sync/errgroup"

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/utils/clocki"
)

func RunAtomicWriteComplianceSuite(t *testing.T, newBackend Constructor) {
func RunAtomicWriteComplianceSuite[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
t.Run("Move", func(t *testing.T) {
testAtomicWriteMove(t, newBackend)
})
Expand All @@ -59,7 +60,7 @@ func RunAtomicWriteComplianceSuite(t *testing.T, newBackend Constructor) {
}

// testAtomicWriteMove verifies the correct behavior of "move" operations.
func testAtomicWriteMove(t *testing.T, newBackend Constructor) {
func testAtomicWriteMove[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
bk, _, err := newBackend()
require.NoError(t, err)

Expand Down Expand Up @@ -121,7 +122,7 @@ func testAtomicWriteMove(t *testing.T, newBackend Constructor) {

// testAtomicWriteLock verifies correct behavior of various "lock" patterns (i.e. where some update on key X is conditional on
// the state of key Y).
func testAtomicWriteLock(t *testing.T, newBackend Constructor) {
func testAtomicWriteLock[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
bk, _, err := newBackend()
require.NoError(t, err)

Expand Down Expand Up @@ -275,7 +276,7 @@ func testAtomicWriteLock(t *testing.T, newBackend Constructor) {
}

// testAtomicWriteMax verifies correct behavior of very large atomic writes.
func testAtomicWriteMax(t *testing.T, newBackend Constructor) {
func testAtomicWriteMax[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
bk, _, err := newBackend()
require.NoError(t, err)

Expand Down Expand Up @@ -361,7 +362,7 @@ func testAtomicWriteMax(t *testing.T, newBackend Constructor) {
}

// testAtomicWriteConcurrent is a sanity-check intended to verify the correctness of AtomicWrite under high concurrency.
func testAtomicWriteConcurrent(t *testing.T, newBackend Constructor) {
func testAtomicWriteConcurrent[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
const (
increments = 200
workers = 20
Expand Down Expand Up @@ -454,7 +455,7 @@ func testAtomicWriteConcurrent(t *testing.T, newBackend Constructor) {
// testAtomicWriteNonConflicting verifies that non-conflicting but overlapping transactions all succeed
// on the first attempt when running concurrently, meaning that backends that treat overlap as conflict (e.g. dynamo)
// handle such conflicts internally.
func testAtomicWriteNonConflicting(t *testing.T, newBackend Constructor) {
func testAtomicWriteNonConflicting[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
const workers = 60

bk, _, err := newBackend()
Expand Down Expand Up @@ -521,7 +522,7 @@ func testAtomicWriteNonConflicting(t *testing.T, newBackend Constructor) {
// testAtomicWriteOther verifies some minor edge-cases that may not be covered by other tests. Specifically,
// it verifies that Item.Key has no effect on writes or subsequent reads, and that ineffectual writes still
// update the value of revision.
func testAtomicWriteOther(t *testing.T, newBackend Constructor) {
func testAtomicWriteOther[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
bk, _, err := newBackend()
require.NoError(t, err)

Expand Down
6 changes: 3 additions & 3 deletions lib/backend/test/atomicwrite_shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ import (

"github.com/google/uuid"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"

"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/utils/clocki"
)

// RunBackendComplianceSuiteWithAtomicWriteShim runs the old backend compliance suite against the provided backend
// with a shim that converts all calls to single-write methods (all write methods but DeleteRange) into calls to
// AtomicWrite. This is done to ensure that the relationship between the conditional actions of AtomicWrite and the
// single-write methods is well defined, and to improve overall coverage of AtomicWrite implementations via reuse.
func RunBackendComplianceSuiteWithAtomicWriteShim(t *testing.T, newBackend Constructor) {
RunBackendComplianceSuite(t, func(options ...ConstructionOption) (backend.Backend, clockwork.FakeClock, error) {
func RunBackendComplianceSuiteWithAtomicWriteShim[FakeClock clocki.FakeClock](t *testing.T, newBackend Constructor[FakeClock]) {
RunBackendComplianceSuite(t, func(options ...ConstructionOption) (backend.Backend, clocki.FakeClock, error) {
bk, clock, err := newBackend(options...)
if err != nil {
return nil, nil, trace.Wrap(err)
Expand Down
Loading

0 comments on commit 1f7b09f

Please sign in to comment.