mirror of
https://github.com/restic/restic.git
synced 2024-09-05 19:09:24 +02:00
284 lines
7.1 KiB
Go
284 lines
7.1 KiB
Go
// +build go1.7
|
|
|
|
package date
|
|
|
|
// Copyright 2017 Microsoft 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.
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func ExampleUnixTime_MarshalJSON() {
|
|
epoch := UnixTime(UnixEpoch())
|
|
text, _ := json.Marshal(epoch)
|
|
fmt.Print(string(text))
|
|
// Output: 0
|
|
}
|
|
|
|
func ExampleUnixTime_UnmarshalJSON() {
|
|
var myTime UnixTime
|
|
json.Unmarshal([]byte("1.3e2"), &myTime)
|
|
fmt.Printf("%v", time.Time(myTime))
|
|
// Output: 1970-01-01 00:02:10 +0000 UTC
|
|
}
|
|
|
|
func TestUnixTime_MarshalJSON(t *testing.T) {
|
|
testCases := []time.Time{
|
|
UnixEpoch().Add(-1 * time.Second), // One second befote the Unix Epoch
|
|
time.Date(2017, time.April, 14, 20, 27, 47, 0, time.UTC), // The time this test was written
|
|
UnixEpoch(),
|
|
time.Date(1800, 01, 01, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2200, 12, 29, 00, 01, 37, 82, time.UTC),
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.String(), func(subT *testing.T) {
|
|
var actual, expected float64
|
|
var marshaled []byte
|
|
|
|
target := UnixTime(tc)
|
|
expected = float64(target.Duration().Nanoseconds()) / 1e9
|
|
|
|
if temp, err := json.Marshal(target); err == nil {
|
|
marshaled = temp
|
|
} else {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
dec := json.NewDecoder(bytes.NewReader(marshaled))
|
|
if err := dec.Decode(&actual); err != nil {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
diff := math.Abs(actual - expected)
|
|
subT.Logf("\ngot :\t%g\nwant:\t%g\ndiff:\t%g", actual, expected, diff)
|
|
if diff > 1e-9 { //Must be within 1 nanosecond of one another
|
|
subT.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnixTime_UnmarshalJSON(t *testing.T) {
|
|
testCases := []struct {
|
|
text string
|
|
expected time.Time
|
|
}{
|
|
{"1", UnixEpoch().Add(time.Second)},
|
|
{"0", UnixEpoch()},
|
|
{"1492203742", time.Date(2017, time.April, 14, 21, 02, 22, 0, time.UTC)}, // The time this test was written
|
|
{"-1", time.Date(1969, time.December, 31, 23, 59, 59, 0, time.UTC)},
|
|
{"1.5", UnixEpoch().Add(1500 * time.Millisecond)},
|
|
{"0e1", UnixEpoch()}, // See http://json.org for 'number' format definition.
|
|
{"1.3e+2", UnixEpoch().Add(130 * time.Second)},
|
|
{"1.6E-10", UnixEpoch()}, // This is so small, it should get truncated into the UnixEpoch
|
|
{"2E-6", UnixEpoch().Add(2 * time.Microsecond)},
|
|
{"1.289345e9", UnixEpoch().Add(1289345000 * time.Second)},
|
|
{"1e-9", UnixEpoch().Add(time.Nanosecond)},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.text, func(subT *testing.T) {
|
|
var rehydrated UnixTime
|
|
if err := json.Unmarshal([]byte(tc.text), &rehydrated); err != nil {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
if time.Time(rehydrated) != tc.expected {
|
|
subT.Logf("\ngot: \t%v\nwant:\t%v\ndiff:\t%v", time.Time(rehydrated), tc.expected, time.Time(rehydrated).Sub(tc.expected))
|
|
subT.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnixTime_JSONRoundTrip(t *testing.T) {
|
|
testCases := []time.Time{
|
|
UnixEpoch(),
|
|
time.Date(2005, time.November, 5, 0, 0, 0, 0, time.UTC), // The day V for Vendetta (film) was released.
|
|
UnixEpoch().Add(-6 * time.Second),
|
|
UnixEpoch().Add(800 * time.Hour),
|
|
UnixEpoch().Add(time.Nanosecond),
|
|
time.Date(2015, time.September, 05, 4, 30, 12, 9992, time.UTC),
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.String(), func(subT *testing.T) {
|
|
subject := UnixTime(tc)
|
|
var marshaled []byte
|
|
if temp, err := json.Marshal(subject); err == nil {
|
|
marshaled = temp
|
|
} else {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
var unmarshaled UnixTime
|
|
if err := json.Unmarshal(marshaled, &unmarshaled); err != nil {
|
|
subT.Error(err)
|
|
}
|
|
|
|
actual := time.Time(unmarshaled)
|
|
diff := actual.Sub(tc)
|
|
subT.Logf("\ngot :\t%s\nwant:\t%s\ndiff:\t%s", actual.String(), tc.String(), diff.String())
|
|
|
|
if diff > time.Duration(100) { // We lose some precision be working in floats. We shouldn't lose more than 100 nanoseconds.
|
|
subT.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnixTime_MarshalBinary(t *testing.T) {
|
|
testCases := []struct {
|
|
expected int64
|
|
subject time.Time
|
|
}{
|
|
{0, UnixEpoch()},
|
|
{-15 * int64(time.Second), UnixEpoch().Add(-15 * time.Second)},
|
|
{54, UnixEpoch().Add(54 * time.Nanosecond)},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run("", func(subT *testing.T) {
|
|
var marshaled []byte
|
|
|
|
if temp, err := UnixTime(tc.subject).MarshalBinary(); err == nil {
|
|
marshaled = temp
|
|
} else {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
var unmarshaled int64
|
|
if err := binary.Read(bytes.NewReader(marshaled), binary.LittleEndian, &unmarshaled); err != nil {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
if unmarshaled != tc.expected {
|
|
subT.Logf("\ngot: \t%d\nwant:\t%d", unmarshaled, tc.expected)
|
|
subT.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnixTime_BinaryRoundTrip(t *testing.T) {
|
|
testCases := []time.Time{
|
|
UnixEpoch(),
|
|
UnixEpoch().Add(800 * time.Minute),
|
|
UnixEpoch().Add(7 * time.Hour),
|
|
UnixEpoch().Add(-1 * time.Nanosecond),
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.String(), func(subT *testing.T) {
|
|
original := UnixTime(tc)
|
|
var marshaled []byte
|
|
|
|
if temp, err := original.MarshalBinary(); err == nil {
|
|
marshaled = temp
|
|
} else {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
var traveled UnixTime
|
|
if err := traveled.UnmarshalBinary(marshaled); err != nil {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
if traveled != original {
|
|
subT.Logf("\ngot: \t%s\nwant:\t%s", time.Time(original).String(), time.Time(traveled).String())
|
|
subT.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnixTime_MarshalText(t *testing.T) {
|
|
testCases := []time.Time{
|
|
UnixEpoch(),
|
|
UnixEpoch().Add(45 * time.Second),
|
|
UnixEpoch().Add(time.Nanosecond),
|
|
UnixEpoch().Add(-100000 * time.Second),
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
expected, _ := tc.MarshalText()
|
|
t.Run("", func(subT *testing.T) {
|
|
var marshaled []byte
|
|
|
|
if temp, err := UnixTime(tc).MarshalText(); err == nil {
|
|
marshaled = temp
|
|
} else {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
if string(marshaled) != string(expected) {
|
|
subT.Logf("\ngot: \t%s\nwant:\t%s", string(marshaled), string(expected))
|
|
subT.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnixTime_TextRoundTrip(t *testing.T) {
|
|
testCases := []time.Time{
|
|
UnixEpoch(),
|
|
UnixEpoch().Add(-1 * time.Nanosecond),
|
|
UnixEpoch().Add(1 * time.Nanosecond),
|
|
time.Date(2017, time.April, 17, 21, 00, 00, 00, time.UTC),
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.String(), func(subT *testing.T) {
|
|
unixTC := UnixTime(tc)
|
|
|
|
var marshaled []byte
|
|
|
|
if temp, err := unixTC.MarshalText(); err == nil {
|
|
marshaled = temp
|
|
} else {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
var unmarshaled UnixTime
|
|
if err := unmarshaled.UnmarshalText(marshaled); err != nil {
|
|
subT.Error(err)
|
|
return
|
|
}
|
|
|
|
if unmarshaled != unixTC {
|
|
t.Logf("\ngot: \t%s\nwant:\t%s", time.Time(unmarshaled).String(), tc.String())
|
|
t.Fail()
|
|
}
|
|
})
|
|
}
|
|
}
|