github.com/tenntenn/testtime@v0.2.3-0.20221118081726-55bcd1f05226/README.md (about) 1 # testtime 2 3 [![pkg.go.dev][gopkg-badge]][gopkg] 4 5 ## How to use 6 7 `testtime` package provides `testtime.Now()` and `testtime.SetTime()`. 8 `testtime.SetTime()` stores a fixed time to a map with goroutine ID of `testtime.SetTime()` as a key. 9 When goroutine ID of `testtime.Now()` is related to a fixed time by `testtime.SetTime()`, it returns the fixed time otherwise it returns current time which is returned by `time.Now()`. 10 11 ```go 12 package main 13 14 import ( 15 "fmt" 16 "time" 17 "testing" 18 19 "github.com/tenntenn/testtime" 20 ) 21 22 func Test(t *testing.T) { 23 24 t.Run("A", func(t *testing.T) { 25 // set zero value 26 testtime.SetTime(t, time.Time{}) 27 // true 28 if time.Now().IsZero { 29 t.Error("error") 30 } 31 }) 32 33 t.Run("B", func(t *testing.T) { 34 // set func which return zero value 35 f := func() time.Time { 36 return time.Time{} 37 } 38 testtime.SetFunc(t, f) 39 // true 40 if time.Now().IsZero { 41 t.Error("error") 42 } 43 }) 44 45 // false 46 if !time.Now().IsZero { 47 t.Error("error") 48 } 49 } 50 ``` 51 52 The `testtime` command replace `time.Now` to `testtime.Now`. 53 It prints a file path of overlay JSON which can be given to `-overlay` flag of `go test` command. 54 55 ```sh 56 $ go install github.com/tenntenn/testtime/cmd/testtime@latest 57 $ go test -overlay=`testtime` 58 PASS 59 ok main 0.156s 60 ``` 61 62 The `testtime` command creates an overlay JSON file and `time.go` which is replaced `time.Now` in `$GOPATH/pkg/testtime` directory. The `testtime` command does not update these files without `-u` flag. 63 64 ```sh 65 $ cat `testtime` | jq 66 { 67 "Replace": { 68 "/usr/local/go/src/time/time.go": "/Users/tenntenn/go/pkg/testtime/time_go1.19.go" 69 } 70 } 71 $ diff /usr/local/go/src/time/time.go /Users/tenntenn/go/pkg/testtime/time_go1.19.go 72 82a83,84 73 > "runtime" 74 > "sync" 75 1089c1091 76 < func Now() Time { 77 --- 78 > func _Now() Time { 79 1619a1622,1649 80 > 81 > // It will be added to GOROOT/src/time/time.go. 82 > 83 > var timeMap sync.Map 84 > 85 > // Now returns a fixed time which is related with the goroutine by SetTime or SetFunc. 86 > // If the current goroutine is not related with any fixed time or function, Now calls time.Now and returns its returned value. 87 > func Now() Time { 88 > v, ok := timeMap.Load(goroutineID()) 89 > if ok { 90 > return v.(func() Time)() 91 > } 92 > return _Now() 93 > } 94 > 95 > func goroutineID() string { 96 > var buf [64]byte 97 > n := runtime.Stack(buf[:], false) 98 > // 10: len("goroutine ") 99 > for i := 10; i < n; i++ { 100 > if buf[i] == ' ' { 101 > return string(buf[10:i]) 102 > } 103 > } 104 > return "" 105 > } 106 > 107 > // End of testtime's code 108 ``` 109 110 ## Examples 111 112 See [_examples](./_examples) directory. 113 114 <!-- links --> 115 [gopkg]: https://pkg.go.dev/github.com/tenntenn/testtime 116 [gopkg-badge]: https://pkg.go.dev/badge/github.com/tenntenn/testtime?status.svg