Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
Added new Chrono structure to keep track of virtual time
Browse files Browse the repository at this point in the history
  • Loading branch information
nqn committed Nov 16, 2015
1 parent 7447698 commit 9dab28c
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
71 changes: 71 additions & 0 deletions core/chrono.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
http://www.apache.org/licenses/LICENSE-2.0.txt
Copyright 2015 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package core

import (
"time"
)

// The chrono structure provides an artificial notion of time that can be
// stopped, forwarded to make testing of timed code deterministic.
type chrono struct {
skew time.Duration
paused bool
pausedAt time.Time
}

// Now() should replace usage of time.Now(). If chrono has been paused, Now()
// returns the time when it was paused. If there is any skew (due to forwarding
// or reversing), this is always added to the end time.
func (c *chrono) Now() time.Time {
var now time.Time
if c.paused {
now = c.pausedAt
} else {
now = time.Now()
}
return now.Add(c.skew)
}

// Forwards time of chrono with skew time. This can be used in both running and
// paused mode.
func (c *chrono) Forward(skew time.Duration) {
c.skew = skew
}

// Resets any previous set clock skew.
func (c *chrono) Reset() {
c.skew = 0
}

// "Stops" time by recording current time and shortcircuit Now() to return this
// time instead of the actual time (plus skew).
func (c *chrono) Pause() {
c.pausedAt = c.Now()
c.paused = true
}

// Continues time after having been paused. This has no effect if clock is
// already running.
func (c *chrono) Continue() {
c.paused = false
}

var Chrono chrono
86 changes: 86 additions & 0 deletions core/chrono_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
http://www.apache.org/licenses/LICENSE-2.0.txt
Copyright 2015 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package core

import (
"testing"
"time"

. "github.com/smartystreets/goconvey/convey"
)

func TestChrono(t *testing.T) {
Convey("Given a new chrono", t, func() {
var Chrono chrono
Convey("Forward time should be 0", func() {
So(Chrono.skew, ShouldEqual, 0)
})

Convey("When forwarded for 30 seconds", func() {
Chrono.Forward(30 * time.Second)
Convey("Forward time should be 30 seconds", func() {
So(Chrono.skew, ShouldEqual, 30*time.Second)
})
})

Convey("After pausing time", func() {
Chrono.Pause()
before := Chrono.Now()
Convey("And waiting 10 milliseconds", func() {
time.Sleep(10 * time.Millisecond)

Convey("Time should stand still", func() {
So(Chrono.Now().Equal(before), ShouldBeTrue)
})
})

Convey("When forwarding another hour", func() {
Chrono.Forward(1 * time.Hour)

Convey("Time should be exactly when we stopped plus one hour", func() {
So(Chrono.Now().Equal(before.Add(1*time.Hour)), ShouldBeTrue)
})
})

Convey("When resetting time", func() {
Chrono.Reset()
Convey("Forward time should be 0", func() {
So(Chrono.skew, ShouldEqual, 0)
})

Convey("And time should be the same as when we paused", func() {
So(Chrono.Now().Equal(before), ShouldBeTrue)
})
})
})

Convey("Continuing time", func() {
Chrono.Continue()
before := Chrono.Now()
Convey("And waiting 10 milliseconds", func() {
time.Sleep(10 * time.Millisecond)

Convey("Time should progress", func() {
So(Chrono.Now().After(before), ShouldBeTrue)
})
})
})
})
}

0 comments on commit 9dab28c

Please sign in to comment.