Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ on:
pull_request:

env:
GO_VERSION: "1.21.x"
GO_VERSION: "1.25.x"

jobs:
lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}

Expand All @@ -25,7 +25,7 @@ jobs:
make $GITHUB_OUTPUT

- name: lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v8
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: ${{ steps.vars.outputs.GOLANGCI_LINT_VERSION }}
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, macos-latest ]
go-version: [ 1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x ]
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 ]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Go cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
# In order:
# * Module download cache
Expand Down
88 changes: 45 additions & 43 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,57 +1,59 @@
# See https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
version: "2"
run:
tests: true

linters-settings:
errcheck:
check-type-assertions: true
check-blank: true
gocyclo:
min-complexity: 20
dupl:
threshold: 100
misspell:
locale: US
unused:
check-exported: false
unparam:
check-exported: true

linters:
enable-all: true
default: all
disable:
- deadcode
- exhaustivestruct
- copyloopvar
- depguard
- exhaustruct
- forbidigo
- forcetypeassert
- gci
- gochecknoglobals
- golint
- gomnd
- ifshort
- interfacer
- intrange
- ireturn
- lll
- maligned
- nosnakecase
- nolintlint # https://github.com/golangci/golangci-lint/issues/3063
- mnd
- nolintlint
- paralleltest
- scopelint
- structcheck
- testpackage
- varcheck
- varnamelen
- wrapcheck

issues:
exclude-use-default: false
exclude-rules:
- linters:
- dupl
- funlen
- goconst
- goerr113
- gomnd
- noctx
path: "_test.go"
- wsl
settings:
dupl:
threshold: 100
errcheck:
check-type-assertions: true
check-blank: true
gocyclo:
min-complexity: 20
misspell:
locale: US
exclusions:
generated: lax
rules:
- linters:
- dupl
- err113
- funlen
- goconst
- mnd
- noctx
- predeclared
path: _test.go
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gofmt
- gofumpt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ MODULE_NAME=clocksteps

VENDOR_DIR = vendor

GOLANGCI_LINT_VERSION ?= v1.52.2
GOLANGCI_LINT_VERSION ?= v2.4.0

GO ?= go
GOLANGCI_LINT ?= $(shell go env GOPATH)/bin/golangci-lint-$(GOLANGCI_LINT_VERSION)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ makes it easy to run tests with `time`.

## Prerequisites

- `Go >= 1.16`
- `Go >= 1.17`

## Usage

Expand Down
40 changes: 25 additions & 15 deletions clock.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,54 @@ var _ clock.Clock = (*Clock)(nil)

// Clock is a clock.Clock.
type Clock struct {
timestamp *time.Time
mu sync.Mutex
timestamps []time.Time
mu sync.Mutex
}

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

if c.timestamp == nil {
if len(c.timestamps) == 0 {
return time.Now()
}

return *c.timestamp
result := c.timestamps[0]

if len(c.timestamps) > 1 {
c.timestamps = c.timestamps[1:]
}

return result
}

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

c.timestamp = timestamp(t)
c.timestamps = []time.Time{t}
}

// Next sets the next timestamps to be returned by Now().
func (c *Clock) Next(t ...time.Time) {
c.mu.Lock()
defer c.mu.Unlock()

c.timestamps = append(c.timestamps, t...)
}

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

if c.timestamp == nil {
if len(c.timestamps) == 0 {
return ErrClockIsNotSet
}

c.timestamp = timestamp(c.timestamp.Add(d))
c.timestamps[0] = c.timestamps[0].Add(d)

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

if c.timestamp == nil {
if len(c.timestamps) == 0 {
return ErrClockIsNotSet
}

c.timestamp = timestamp(c.timestamp.AddDate(years, months, days))
c.timestamps[0] = c.timestamps[0].AddDate(years, months, days)

return nil
}
Expand All @@ -73,15 +87,15 @@ func (c *Clock) Freeze() {
c.mu.Lock()
defer c.mu.Unlock()

c.timestamp = timestamp(time.Now())
c.timestamps = []time.Time{time.Now()}
}

// Unfreeze unfreezes the clock.
func (c *Clock) Unfreeze() {
c.mu.Lock()
defer c.mu.Unlock()

c.timestamp = nil
c.timestamps = nil
}

// Clock provides clock.Clock.
Expand All @@ -93,7 +107,3 @@ func (c *Clock) Clock() clock.Clock {
func New() *Clock {
return &Clock{}
}

func timestamp(t time.Time) *time.Time {
return &t
}
23 changes: 18 additions & 5 deletions clock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"testing"
"time"

"github.com/godogx/clocksteps"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/godogx/clocksteps"
)

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

// Errors while adding time to a live clock.
assert.Equal(t, clocksteps.ErrClockIsNotSet, c.Add(time.Hour))
assert.Equal(t, clocksteps.ErrClockIsNotSet, c.AddDate(0, 0, 1))
require.ErrorIs(t, c.Add(time.Hour), clocksteps.ErrClockIsNotSet)
require.ErrorIs(t, c.AddDate(0, 0, 1), clocksteps.ErrClockIsNotSet)

// Freeze the clock.
c.Freeze()
Expand All @@ -42,7 +44,7 @@ func TestClock(t *testing.T) {
// Change the time.
ts = ts.Add(2 * time.Hour)
err := c.Add(2 * time.Hour)
assert.NoError(t, err)
require.NoError(t, err)

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

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

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

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

// Add more timestamps.
ts2 := time.Date(2021, 2, 3, 4, 5, 6, 0, time.UTC)
c.Next(ts2)

oldTs := c.Now()

assert.Equal(t, ts, oldTs)
assert.NotEqual(t, ts2, oldTs)
assert.Equal(t, ts2, c.Now())
assert.Equal(t, ts2, c.Now())

// Unfreeze the clock.
c.Unfreeze()

Expand Down
10 changes: 9 additions & 1 deletion features/Clock.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Feature: Without Background

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

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

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

Then the time is "2020-04-05T06:07:08Z"
And the time is "2021-01-02T03:04:05Z"
And the time is "2023-02-03T04:05:06Z"
And the time is "2022-12-31T23:59:59Z"
And the time is "2022-12-31T23:59:59Z"
And the time is "2022-12-31T23:59:59Z"

Scenario: Add time
Given the clock is at "2020-01-02T03:04:05Z"
Expand Down
6 changes: 4 additions & 2 deletions features/bootstrap/godog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bootstrap

import (
"bytes"
"errors"
"flag"
"fmt"
"math/rand"
Expand All @@ -13,6 +14,7 @@ import (

"github.com/cucumber/godog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.nhat.io/timeparser"

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

files, err := os.ReadDir(filepath.Clean(path))
assert.NoError(t, err)
require.NoError(t, err)

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

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

if ts.After(min) && ts.Before(max) {
return fmt.Errorf("the time is now")
return errors.New("the time is now")
}

return nil
Expand Down
Loading
Loading