Skip to content

Commit 3d6b4a5

Browse files
authored
Add step to set the next timestamp for the clock (#30)
* Add step to set the next timestamp for the clock * Add more go versions * Fix lint issues
1 parent 5dabf09 commit 3d6b4a5

13 files changed

Lines changed: 149 additions & 92 deletions

File tree

.github/workflows/lint.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ on:
77
pull_request:
88

99
env:
10-
GO_VERSION: "1.21.x"
10+
GO_VERSION: "1.25.x"
1111

1212
jobs:
1313
lint:
1414
name: lint
1515
runs-on: ubuntu-latest
1616
steps:
17-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@v5
1818

19-
- uses: actions/setup-go@v5
19+
- uses: actions/setup-go@v6
2020
with:
2121
go-version: ${{ env.GO_VERSION }}
2222

@@ -25,7 +25,7 @@ jobs:
2525
make $GITHUB_OUTPUT
2626
2727
- name: lint
28-
uses: golangci/golangci-lint-action@v3
28+
uses: golangci/golangci-lint-action@v8
2929
with:
3030
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
3131
version: ${{ steps.vars.outputs.GOLANGCI_LINT_VERSION }}

.github/workflows/test.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
os: [ ubuntu-latest, macos-latest ]
19-
go-version: [ 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x ]
19+
go-version: [ 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x, 1.24.x, 1.25.x ]
2020
runs-on: ${{ matrix.os }}
2121
steps:
2222
- name: Install Go
23-
uses: actions/setup-go@v5
23+
uses: actions/setup-go@v6
2424
with:
2525
go-version: ${{ matrix.go-version }}
2626

2727
- name: Checkout code
28-
uses: actions/checkout@v4
28+
uses: actions/checkout@v5
2929

3030
- name: Go cache
31-
uses: actions/cache@v3
31+
uses: actions/cache@v4
3232
with:
3333
# In order:
3434
# * Module download cache

.golangci.yaml

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,59 @@
1-
# See https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
1+
version: "2"
22
run:
33
tests: true
4-
5-
linters-settings:
6-
errcheck:
7-
check-type-assertions: true
8-
check-blank: true
9-
gocyclo:
10-
min-complexity: 20
11-
dupl:
12-
threshold: 100
13-
misspell:
14-
locale: US
15-
unused:
16-
check-exported: false
17-
unparam:
18-
check-exported: true
19-
204
linters:
21-
enable-all: true
5+
default: all
226
disable:
23-
- deadcode
24-
- exhaustivestruct
7+
- copyloopvar
8+
- depguard
259
- exhaustruct
2610
- forbidigo
2711
- forcetypeassert
28-
- gci
2912
- gochecknoglobals
30-
- golint
31-
- gomnd
32-
- ifshort
33-
- interfacer
13+
- intrange
3414
- ireturn
3515
- lll
36-
- maligned
37-
- nosnakecase
38-
- nolintlint # https://github.com/golangci/golangci-lint/issues/3063
16+
- mnd
17+
- nolintlint
3918
- paralleltest
40-
- scopelint
41-
- structcheck
4219
- testpackage
43-
- varcheck
4420
- varnamelen
4521
- wrapcheck
46-
47-
issues:
48-
exclude-use-default: false
49-
exclude-rules:
50-
- linters:
51-
- dupl
52-
- funlen
53-
- goconst
54-
- goerr113
55-
- gomnd
56-
- noctx
57-
path: "_test.go"
22+
- wsl
23+
settings:
24+
dupl:
25+
threshold: 100
26+
errcheck:
27+
check-type-assertions: true
28+
check-blank: true
29+
gocyclo:
30+
min-complexity: 20
31+
misspell:
32+
locale: US
33+
exclusions:
34+
generated: lax
35+
rules:
36+
- linters:
37+
- dupl
38+
- err113
39+
- funlen
40+
- goconst
41+
- mnd
42+
- noctx
43+
- predeclared
44+
path: _test.go
45+
paths:
46+
- third_party$
47+
- builtin$
48+
- examples$
49+
formatters:
50+
enable:
51+
- gofmt
52+
- gofumpt
53+
- goimports
54+
exclusions:
55+
generated: lax
56+
paths:
57+
- third_party$
58+
- builtin$
59+
- examples$

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ MODULE_NAME=clocksteps
22

33
VENDOR_DIR = vendor
44

5-
GOLANGCI_LINT_VERSION ?= v1.52.2
5+
GOLANGCI_LINT_VERSION ?= v2.4.0
66

77
GO ?= go
88
GOLANGCI_LINT ?= $(shell go env GOPATH)/bin/golangci-lint-$(GOLANGCI_LINT_VERSION)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ makes it easy to run tests with `time`.
1111

1212
## Prerequisites
1313

14-
- `Go >= 1.16`
14+
- `Go >= 1.17`
1515

1616
## Usage
1717

clock.go

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,54 @@ var _ clock.Clock = (*Clock)(nil)
1616

1717
// Clock is a clock.Clock.
1818
type Clock struct {
19-
timestamp *time.Time
20-
mu sync.Mutex
19+
timestamps []time.Time
20+
mu sync.Mutex
2121
}
2222

2323
// Now returns a fixed timestamp or time.Now().
2424
func (c *Clock) Now() time.Time {
2525
c.mu.Lock()
2626
defer c.mu.Unlock()
2727

28-
if c.timestamp == nil {
28+
if len(c.timestamps) == 0 {
2929
return time.Now()
3030
}
3131

32-
return *c.timestamp
32+
result := c.timestamps[0]
33+
34+
if len(c.timestamps) > 1 {
35+
c.timestamps = c.timestamps[1:]
36+
}
37+
38+
return result
3339
}
3440

3541
// Set fixes the clock at a time.
3642
func (c *Clock) Set(t time.Time) {
3743
c.mu.Lock()
3844
defer c.mu.Unlock()
3945

40-
c.timestamp = timestamp(t)
46+
c.timestamps = []time.Time{t}
47+
}
48+
49+
// Next sets the next timestamps to be returned by Now().
50+
func (c *Clock) Next(t ...time.Time) {
51+
c.mu.Lock()
52+
defer c.mu.Unlock()
53+
54+
c.timestamps = append(c.timestamps, t...)
4155
}
4256

4357
// Add adds time to the clock.
4458
func (c *Clock) Add(d time.Duration) error {
4559
c.mu.Lock()
4660
defer c.mu.Unlock()
4761

48-
if c.timestamp == nil {
62+
if len(c.timestamps) == 0 {
4963
return ErrClockIsNotSet
5064
}
5165

52-
c.timestamp = timestamp(c.timestamp.Add(d))
66+
c.timestamps[0] = c.timestamps[0].Add(d)
5367

5468
return nil
5569
}
@@ -59,11 +73,11 @@ func (c *Clock) AddDate(years, months, days int) error {
5973
c.mu.Lock()
6074
defer c.mu.Unlock()
6175

62-
if c.timestamp == nil {
76+
if len(c.timestamps) == 0 {
6377
return ErrClockIsNotSet
6478
}
6579

66-
c.timestamp = timestamp(c.timestamp.AddDate(years, months, days))
80+
c.timestamps[0] = c.timestamps[0].AddDate(years, months, days)
6781

6882
return nil
6983
}
@@ -73,15 +87,15 @@ func (c *Clock) Freeze() {
7387
c.mu.Lock()
7488
defer c.mu.Unlock()
7589

76-
c.timestamp = timestamp(time.Now())
90+
c.timestamps = []time.Time{time.Now()}
7791
}
7892

7993
// Unfreeze unfreezes the clock.
8094
func (c *Clock) Unfreeze() {
8195
c.mu.Lock()
8296
defer c.mu.Unlock()
8397

84-
c.timestamp = nil
98+
c.timestamps = nil
8599
}
86100

87101
// Clock provides clock.Clock.
@@ -93,7 +107,3 @@ func (c *Clock) Clock() clock.Clock {
93107
func New() *Clock {
94108
return &Clock{}
95109
}
96-
97-
func timestamp(t time.Time) *time.Time {
98-
return &t
99-
}

clock_test.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import (
44
"testing"
55
"time"
66

7-
"github.com/godogx/clocksteps"
87
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/godogx/clocksteps"
911
)
1012

1113
func TestClock(t *testing.T) {
@@ -18,8 +20,8 @@ func TestClock(t *testing.T) {
1820
assert.True(t, now.Before(c.Now()))
1921

2022
// Errors while adding time to a live clock.
21-
assert.Equal(t, clocksteps.ErrClockIsNotSet, c.Add(time.Hour))
22-
assert.Equal(t, clocksteps.ErrClockIsNotSet, c.AddDate(0, 0, 1))
23+
require.ErrorIs(t, c.Add(time.Hour), clocksteps.ErrClockIsNotSet)
24+
require.ErrorIs(t, c.AddDate(0, 0, 1), clocksteps.ErrClockIsNotSet)
2325

2426
// Freeze the clock.
2527
c.Freeze()
@@ -42,7 +44,7 @@ func TestClock(t *testing.T) {
4244
// Change the time.
4345
ts = ts.Add(2 * time.Hour)
4446
err := c.Add(2 * time.Hour)
45-
assert.NoError(t, err)
47+
require.NoError(t, err)
4648

4749
<-time.After(50 * time.Millisecond)
4850

@@ -51,12 +53,23 @@ func TestClock(t *testing.T) {
5153
// Change the date.
5254
ts = ts.AddDate(2, 1, 3)
5355
err = c.AddDate(2, 1, 3)
54-
assert.NoError(t, err)
56+
require.NoError(t, err)
5557

5658
<-time.After(50 * time.Millisecond)
5759

5860
assert.Equal(t, ts, c.Now())
5961

62+
// Add more timestamps.
63+
ts2 := time.Date(2021, 2, 3, 4, 5, 6, 0, time.UTC)
64+
c.Next(ts2)
65+
66+
oldTs := c.Now()
67+
68+
assert.Equal(t, ts, oldTs)
69+
assert.NotEqual(t, ts2, oldTs)
70+
assert.Equal(t, ts2, c.Now())
71+
assert.Equal(t, ts2, c.Now())
72+
6073
// Unfreeze the clock.
6174
c.Unfreeze()
6275

features/Clock.feature

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Feature: Without Background
22

3-
Scenario: Set time
3+
Scenario: Set and Next time
44
Given the clock is at "2020-01-02T03:04:05Z"
55

66
Then the time is "2020-01-02T03:04:05Z"
@@ -14,8 +14,16 @@ Feature: Without Background
1414
Then the time is "2020-03-04T05:06:07Z"
1515

1616
Given now is "2020-04-05T06:07:08Z"
17+
And the clock advances to "2021-01-02T03:04:05Z"
18+
And the clock changes to "2023-02-03T04:05:06Z"
19+
And the clock moves forward to "2022-12-31T23:59:59Z"
1720

1821
Then the time is "2020-04-05T06:07:08Z"
22+
And the time is "2021-01-02T03:04:05Z"
23+
And the time is "2023-02-03T04:05:06Z"
24+
And the time is "2022-12-31T23:59:59Z"
25+
And the time is "2022-12-31T23:59:59Z"
26+
And the time is "2022-12-31T23:59:59Z"
1927

2028
Scenario: Add time
2129
Given the clock is at "2020-01-02T03:04:05Z"

features/bootstrap/godog_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package bootstrap
22

33
import (
44
"bytes"
5+
"errors"
56
"flag"
67
"fmt"
78
"math/rand"
@@ -13,6 +14,7 @@ import (
1314

1415
"github.com/cucumber/godog"
1516
"github.com/stretchr/testify/assert"
17+
"github.com/stretchr/testify/require"
1618
"go.nhat.io/timeparser"
1719

1820
"github.com/godogx/clocksteps"
@@ -64,7 +66,7 @@ func RunSuite(t *testing.T, path string, featureContext func(t *testing.T, ctx *
6466
var paths []string
6567

6668
files, err := os.ReadDir(filepath.Clean(path))
67-
assert.NoError(t, err)
69+
require.NoError(t, err)
6870

6971
paths = make([]string, 0, len(files))
7072

@@ -133,7 +135,7 @@ func isNotNow(c *clocksteps.Clock) error {
133135
max := now.Add(10 * time.Millisecond)
134136

135137
if ts.After(min) && ts.Before(max) {
136-
return fmt.Errorf("the time is now")
138+
return errors.New("the time is now")
137139
}
138140

139141
return nil

0 commit comments

Comments
 (0)