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