This module wraps the parts of the time module of Go that do access
the OS time directly, as it stands at Go 1.2 and 1.3 (which are both the
same.) Unfortunately, due to the fact I can not re-export types, you'll
still need to import "time" for its types.

This module declares an interface for time functions AbstractTime,
provides an implementation that simply backs to the "real" time functions
"RealTime", and provides an implementation that allows you to fully control
the time "ManualTime", including setting "now", and requiring you to
manually trigger all time-based events, such as alerts and alarms.

Since there is no way to distinguish between different calls to the
standard time functions, each of the methods in the AbstractTime interface
adds an "id". The RealTime implementation simply ignores them. The
ManualTime implementations uses these to trigger specific time events.
Be sure to see the example for usage of the ManualTime implementation.

Avoid re-using IDs on the Tick functions; it becomes confusing which
.Trigger is affecting which Tick.

Be sure to see the Example below.

Quality: At the moment I would call this beta code. Go lint clean, go vet
clean, 100% coverage in the tests. You and I both know that doesn't prove
this is bug-free, but at least it shows I care. And bear in mind what
this really provides is a structure, rather than a whackload of code; should
the code prove not quite correct for your project, it will be easy for you
to fix it.

package main
import (
"time"
)
// It's best to allocate IDs like this for your time usages.
const (
timeoutID = iota
)
func main() {
// Suppose you have a goroutine feeding you something from a socket,
// and you want to do something if that times out. You can test this
// with:
manualTime := NewManual()
timedOut := make(chan struct{})
go ReadSocket(manualTime, timedOut)
manualTime.Trigger(timeoutID)
// This will read the struct{}{} from above. Getting here asserts
// that we did what we wanted when we timed out.
<-timedOut
}
// In production code, at would be a RealTime, and thus use the "real"
// time.After function, ignoring the ID.
func ReadSocket(at AbstractTime, timedOut chan struct{}) {
timeout := at.After(time.Second, timeoutID)
// in this example, this will never be filled
fromSocket := make(chan []byte)
select {
case <-fromSocket:
// handle socketData
case <-timeout:
timedOut <- struct{}{}
}
}

Trigger takes the given ids for time events, and causes them to "occur":
triggering messages on channels, ending sleeps, etc.

Note this is the ONLY way to "trigger" such events. While this package
allows you to manipulate "Now" in a couple of different ways, advancing
"now" past a Trigger's set time will NOT trigger it. First, this keeps
it simple to understand when things are triggered, and second, reality
isn't so deterministic anyhow....