1package wrappers
2
3import (
4	"testing"
5	"time"
6)
7
8func TestNow(t *testing.T) {
9	cases := []struct {
10		title               string
11		options             []TimeOption
12		expectedTimeWrapper TimeWrapper
13	}{
14		{
15			title: "without options",
16			expectedTimeWrapper: TimeWrapper{
17				Formatted: true,
18				Time:      time.Now().In(time.UTC),
19			},
20		},
21		{
22			title:   "with formatting false",
23			options: []TimeOption{WithFormatted(false)},
24			expectedTimeWrapper: TimeWrapper{
25				Formatted: false,
26				Time:      time.Now().In(time.UTC),
27			},
28		},
29		{
30			title:   "with kdbx4 formatting",
31			options: []TimeOption{WithKDBX4Formatting},
32			expectedTimeWrapper: TimeWrapper{
33				Formatted: false,
34				Time:      time.Now().In(time.UTC),
35			},
36		},
37		{
38			title: "with time overwrite",
39			options: []TimeOption{
40				func(t *TimeWrapper) {
41					t.Time = time.Date(2015, 11, 12, 23, 34, 34, 0, time.UTC)
42				},
43			},
44			expectedTimeWrapper: TimeWrapper{
45				Formatted: true,
46				Time:      time.Date(2015, 11, 12, 23, 34, 34, 0, time.UTC),
47			},
48		},
49	}
50
51	for _, c := range cases {
52		t.Run(c.title, func(t *testing.T) {
53			timeWrapper := Now(c.options...)
54
55			if timeWrapper.Formatted != c.expectedTimeWrapper.Formatted {
56				t.Errorf(
57					"Received formatted %+v, expected %+v",
58					timeWrapper.Formatted,
59					c.expectedTimeWrapper.Formatted,
60				)
61			}
62
63			duration, _ := time.ParseDuration("100ms")
64
65			if timeWrapper.Time.Sub(c.expectedTimeWrapper.Time) > duration {
66				t.Errorf(
67					"Received time not within %+v: received %+v, expected %+v",
68					duration,
69					timeWrapper.Time,
70					c.expectedTimeWrapper.Time,
71				)
72			}
73		})
74	}
75}
76
77func TestTimeWrapperMarshalText(t *testing.T) {
78	cases := []struct {
79		title     string
80		valueFn   func() time.Time
81		formatted bool
82		expValue  string
83		expErr    error
84	}{
85		{
86			title: "negative year",
87			valueFn: func() time.Time {
88				return time.Date(-1, time.June, 10, 6, 34, 12, 123123, time.UTC)
89			},
90			formatted: true,
91			expErr:    ErrYearOutsideOfRange,
92		},
93		{
94			title: "year above 10000",
95			valueFn: func() time.Time {
96				return time.Date(10001, time.June, 10, 6, 34, 12, 123123, time.UTC)
97			},
98			formatted: true,
99			expErr:    ErrYearOutsideOfRange,
100		},
101		{
102			title: "realistic year (2018)",
103			valueFn: func() time.Time {
104				ref, _ := time.Parse(time.RFC3339, "2018-06-10T06:20:23+02:00")
105				return ref
106			},
107			formatted: true,
108			expValue:  "2018-06-10T04:20:23Z",
109		},
110		{
111			title: "kdbx4 timestamp 1",
112			valueFn: func() time.Time {
113				ref, _ := time.Parse(time.RFC3339, "2019-08-03T08:35:06+02:00")
114				return ref
115			},
116			formatted: false,
117			expValue:  "GiLX1A4AAAA=",
118		},
119		{
120			title: "kdbx4 timestamp 2",
121			valueFn: func() time.Time {
122				ref, _ := time.Parse(time.RFC3339, "2019-08-03T08:35:00+02:00")
123				return ref
124			},
125			formatted: false,
126			expValue:  "FCLX1A4AAAA=",
127		},
128		{
129			title: "kdbx4 timestamp 3",
130			valueFn: func() time.Time {
131				ref, _ := time.Parse(time.RFC3339, "2019-08-03T06:34:25Z")
132				return ref
133			},
134			formatted: false,
135			expValue:  "8SHX1A4AAAA=",
136		},
137	}
138
139	for _, c := range cases {
140		t.Run(c.title, func(t *testing.T) {
141			value := c.valueFn()
142
143			timeWrap := TimeWrapper{
144				Formatted: c.formatted,
145				Time:      value,
146			}
147			data, err := timeWrap.MarshalText()
148			if err != c.expErr {
149				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
150			}
151
152			if string(data) != c.expValue {
153				t.Errorf(
154					"Did not marshal into expected string '%s', received: '%s'",
155					c.expValue,
156					string(data),
157				)
158			}
159		})
160	}
161}
162
163func TestTimeWrapperUnmarshalText(t *testing.T) {
164	cases := []struct {
165		title    string
166		value    string
167		expValue time.Time
168		expErr   error
169	}{
170		{
171			title:    "Non UTC RFC3339 compatible value",
172			value:    "2018-06-10T06:20:23+02:00",
173			expValue: time.Date(2018, time.June, 10, 4, 20, 23, 0, time.UTC),
174		},
175		{
176			title:    "UTC RFC3339 compatible value",
177			value:    "2018-06-10T04:20:23Z",
178			expValue: time.Date(2018, time.June, 10, 4, 20, 23, 0, time.UTC),
179		},
180		{
181			title:    "kdbx4 timestamp 1",
182			value:    "GiLX1A4AAAA=",
183			expValue: time.Date(2019, time.August, 3, 6, 35, 6, 0, time.UTC),
184		},
185		{
186			title:    "kdbx4 timestamp 2",
187			value:    "FCLX1A4AAAA=",
188			expValue: time.Date(2019, time.August, 3, 6, 35, 0, 0, time.UTC),
189		},
190		{
191			title:    "kdbx4 timestamp 3",
192			value:    "8SHX1A4AAAA=",
193			expValue: time.Date(2019, time.August, 3, 6, 34, 25, 0, time.UTC),
194		},
195	}
196
197	for _, c := range cases {
198		t.Run(c.title, func(t *testing.T) {
199
200			timeWrap := &TimeWrapper{
201				Formatted: true,
202			}
203			err := timeWrap.UnmarshalText([]byte(c.value))
204			if err != c.expErr {
205				t.Fatalf("Did not receive expected error %+v, received %+v", c.expErr, err)
206			}
207
208			if !timeWrap.Time.Equal(c.expValue) {
209				t.Errorf("Did not receive expected value '%+v', received: '%+v'", c.expValue, *timeWrap)
210			}
211		})
212	}
213}
214