timestamp_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ptypes
  5. import (
  6. "math"
  7. "testing"
  8. "time"
  9. "github.com/golang/protobuf/proto"
  10. tspb "github.com/golang/protobuf/ptypes/timestamp"
  11. )
  12. var tests = []struct {
  13. ts *tspb.Timestamp
  14. valid bool
  15. t time.Time
  16. }{
  17. // The timestamp representing the Unix epoch date.
  18. {&tspb.Timestamp{Seconds: 0, Nanos: 0}, true, utcDate(1970, 1, 1)},
  19. // The smallest representable timestamp.
  20. {&tspb.Timestamp{Seconds: math.MinInt64, Nanos: math.MinInt32}, false,
  21. time.Unix(math.MinInt64, math.MinInt32).UTC()},
  22. // The smallest representable timestamp with non-negative nanos.
  23. {&tspb.Timestamp{Seconds: math.MinInt64, Nanos: 0}, false, time.Unix(math.MinInt64, 0).UTC()},
  24. // The earliest valid timestamp.
  25. {&tspb.Timestamp{Seconds: minValidSeconds, Nanos: 0}, true, utcDate(1, 1, 1)},
  26. //"0001-01-01T00:00:00Z"},
  27. // The largest representable timestamp.
  28. {&tspb.Timestamp{Seconds: math.MaxInt64, Nanos: math.MaxInt32}, false,
  29. time.Unix(math.MaxInt64, math.MaxInt32).UTC()},
  30. // The largest representable timestamp with nanos in range.
  31. {&tspb.Timestamp{Seconds: math.MaxInt64, Nanos: 1e9 - 1}, false,
  32. time.Unix(math.MaxInt64, 1e9-1).UTC()},
  33. // The largest valid timestamp.
  34. {&tspb.Timestamp{Seconds: maxValidSeconds - 1, Nanos: 1e9 - 1}, true,
  35. time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC)},
  36. // The smallest invalid timestamp that is larger than the valid range.
  37. {&tspb.Timestamp{Seconds: maxValidSeconds, Nanos: 0}, false, time.Unix(maxValidSeconds, 0).UTC()},
  38. // A date before the epoch.
  39. {&tspb.Timestamp{Seconds: -281836800, Nanos: 0}, true, utcDate(1961, 1, 26)},
  40. // A date after the epoch.
  41. {&tspb.Timestamp{Seconds: 1296000000, Nanos: 0}, true, utcDate(2011, 1, 26)},
  42. // A date after the epoch, in the middle of the day.
  43. {&tspb.Timestamp{Seconds: 1296012345, Nanos: 940483}, true,
  44. time.Date(2011, 1, 26, 3, 25, 45, 940483, time.UTC)},
  45. }
  46. func TestValidateTimestamp(t *testing.T) {
  47. for _, s := range tests {
  48. got := validateTimestamp(s.ts)
  49. if (got == nil) != s.valid {
  50. t.Errorf("validateTimestamp(%v) = %v, want %v", s.ts, got, s.valid)
  51. }
  52. }
  53. }
  54. func TestTimestamp(t *testing.T) {
  55. for _, s := range tests {
  56. got, err := Timestamp(s.ts)
  57. if (err == nil) != s.valid {
  58. t.Errorf("Timestamp(%v) error = %v, but valid = %t", s.ts, err, s.valid)
  59. } else if s.valid && got != s.t {
  60. t.Errorf("Timestamp(%v) = %v, want %v", s.ts, got, s.t)
  61. }
  62. }
  63. // Special case: a nil Timestamp is an error, but returns the 0 Unix time.
  64. got, err := Timestamp(nil)
  65. want := time.Unix(0, 0).UTC()
  66. if got != want {
  67. t.Errorf("Timestamp(nil) = %v, want %v", got, want)
  68. }
  69. if err == nil {
  70. t.Errorf("Timestamp(nil) error = nil, expected error")
  71. }
  72. }
  73. func TestTimestampProto(t *testing.T) {
  74. for _, s := range tests {
  75. got, err := TimestampProto(s.t)
  76. if (err == nil) != s.valid {
  77. t.Errorf("TimestampProto(%v) error = %v, but valid = %t", s.t, err, s.valid)
  78. } else if s.valid && !proto.Equal(got, s.ts) {
  79. t.Errorf("TimestampProto(%v) = %v, want %v", s.t, got, s.ts)
  80. }
  81. }
  82. // No corresponding special case here: no time.Time results in a nil Timestamp.
  83. }
  84. func TestTimestampString(t *testing.T) {
  85. for _, test := range []struct {
  86. ts *tspb.Timestamp
  87. want string
  88. }{
  89. // Not much testing needed because presumably time.Format is
  90. // well-tested.
  91. {&tspb.Timestamp{Seconds: 0, Nanos: 0}, "1970-01-01T00:00:00Z"},
  92. {&tspb.Timestamp{Seconds: minValidSeconds - 1, Nanos: 0}, "(timestamp: seconds:-62135596801 before 0001-01-01)"},
  93. } {
  94. got := TimestampString(test.ts)
  95. if got != test.want {
  96. t.Errorf("TimestampString(%v) = %q, want %q", test.ts, got, test.want)
  97. }
  98. }
  99. }
  100. func utcDate(year, month, day int) time.Time {
  101. return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
  102. }
  103. func TestTimestampNow(t *testing.T) {
  104. // Bracket the expected time.
  105. before := time.Now()
  106. ts := TimestampNow()
  107. after := time.Now()
  108. tm, err := Timestamp(ts)
  109. if err != nil {
  110. t.Errorf("between %v and %v\nTimestampNow() = %v\nwhich is invalid (%v)", before, after, ts, err)
  111. }
  112. if tm.Before(before) || tm.After(after) {
  113. t.Errorf("between %v and %v\nTimestamp(TimestampNow()) = %v", before, after, tm)
  114. }
  115. }