1// Copyright 2013 The go-github AUTHORS. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style 4// license that can be found in the LICENSE file. 5 6package github 7 8import ( 9 "encoding/json" 10 "fmt" 11 "testing" 12 "time" 13) 14 15const ( 16 emptyTimeStr = `"0001-01-01T00:00:00Z"` 17 referenceTimeStr = `"2006-01-02T15:04:05Z"` 18 referenceTimeStrFractional = `"2006-01-02T15:04:05.000Z"` // This format was returned by the Projects API before October 1, 2017. 19 referenceUnixTimeStr = `1136214245` 20) 21 22var ( 23 referenceTime = time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC) 24 unixOrigin = time.Unix(0, 0).In(time.UTC) 25) 26 27func TestTimestamp_Marshal(t *testing.T) { 28 testCases := []struct { 29 desc string 30 data Timestamp 31 want string 32 wantErr bool 33 equal bool 34 }{ 35 {"Reference", Timestamp{referenceTime}, referenceTimeStr, false, true}, 36 {"Empty", Timestamp{}, emptyTimeStr, false, true}, 37 {"Mismatch", Timestamp{}, referenceTimeStr, false, false}, 38 } 39 for _, tc := range testCases { 40 out, err := json.Marshal(tc.data) 41 if gotErr := err != nil; gotErr != tc.wantErr { 42 t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) 43 } 44 got := string(out) 45 equal := got == tc.want 46 if (got == tc.want) != tc.equal { 47 t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) 48 } 49 } 50} 51 52func TestTimestamp_Unmarshal(t *testing.T) { 53 testCases := []struct { 54 desc string 55 data string 56 want Timestamp 57 wantErr bool 58 equal bool 59 }{ 60 {"Reference", referenceTimeStr, Timestamp{referenceTime}, false, true}, 61 {"ReferenceUnix", referenceUnixTimeStr, Timestamp{referenceTime}, false, true}, 62 {"ReferenceFractional", referenceTimeStrFractional, Timestamp{referenceTime}, false, true}, 63 {"Empty", emptyTimeStr, Timestamp{}, false, true}, 64 {"UnixStart", `0`, Timestamp{unixOrigin}, false, true}, 65 {"Mismatch", referenceTimeStr, Timestamp{}, false, false}, 66 {"MismatchUnix", `0`, Timestamp{}, false, false}, 67 {"Invalid", `"asdf"`, Timestamp{referenceTime}, true, false}, 68 } 69 for _, tc := range testCases { 70 var got Timestamp 71 err := json.Unmarshal([]byte(tc.data), &got) 72 if gotErr := err != nil; gotErr != tc.wantErr { 73 t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) 74 continue 75 } 76 equal := got.Equal(tc.want) 77 if equal != tc.equal { 78 t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) 79 } 80 } 81} 82 83func TestTimstamp_MarshalReflexivity(t *testing.T) { 84 testCases := []struct { 85 desc string 86 data Timestamp 87 }{ 88 {"Reference", Timestamp{referenceTime}}, 89 {"Empty", Timestamp{}}, 90 } 91 for _, tc := range testCases { 92 data, err := json.Marshal(tc.data) 93 if err != nil { 94 t.Errorf("%s: Marshal err=%v", tc.desc, err) 95 } 96 var got Timestamp 97 err = json.Unmarshal(data, &got) 98 if err != nil { 99 t.Errorf("%s: Unmarshal err=%v", tc.desc, err) 100 } 101 if !got.Equal(tc.data) { 102 t.Errorf("%s: %+v != %+v", tc.desc, got, data) 103 } 104 } 105} 106 107type WrappedTimestamp struct { 108 A int 109 Time Timestamp 110} 111 112func TestWrappedTimstamp_Marshal(t *testing.T) { 113 testCases := []struct { 114 desc string 115 data WrappedTimestamp 116 want string 117 wantErr bool 118 equal bool 119 }{ 120 {"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, true}, 121 {"Empty", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, emptyTimeStr), false, true}, 122 {"Mismatch", WrappedTimestamp{}, fmt.Sprintf(`{"A":0,"Time":%s}`, referenceTimeStr), false, false}, 123 } 124 for _, tc := range testCases { 125 out, err := json.Marshal(tc.data) 126 if gotErr := err != nil; gotErr != tc.wantErr { 127 t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) 128 } 129 got := string(out) 130 equal := got == tc.want 131 if equal != tc.equal { 132 t.Errorf("%s: got=%s, want=%s, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) 133 } 134 } 135} 136 137func TestWrappedTimstamp_Unmarshal(t *testing.T) { 138 testCases := []struct { 139 desc string 140 data string 141 want WrappedTimestamp 142 wantErr bool 143 equal bool 144 }{ 145 {"Reference", referenceTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true}, 146 {"ReferenceUnix", referenceUnixTimeStr, WrappedTimestamp{0, Timestamp{referenceTime}}, false, true}, 147 {"Empty", emptyTimeStr, WrappedTimestamp{0, Timestamp{}}, false, true}, 148 {"UnixStart", `0`, WrappedTimestamp{0, Timestamp{unixOrigin}}, false, true}, 149 {"Mismatch", referenceTimeStr, WrappedTimestamp{0, Timestamp{}}, false, false}, 150 {"MismatchUnix", `0`, WrappedTimestamp{0, Timestamp{}}, false, false}, 151 {"Invalid", `"asdf"`, WrappedTimestamp{0, Timestamp{referenceTime}}, true, false}, 152 } 153 for _, tc := range testCases { 154 var got Timestamp 155 err := json.Unmarshal([]byte(tc.data), &got) 156 if gotErr := err != nil; gotErr != tc.wantErr { 157 t.Errorf("%s: gotErr=%v, wantErr=%v, err=%v", tc.desc, gotErr, tc.wantErr, err) 158 continue 159 } 160 equal := got.Time.Equal(tc.want.Time.Time) 161 if equal != tc.equal { 162 t.Errorf("%s: got=%#v, want=%#v, equal=%v, want=%v", tc.desc, got, tc.want, equal, tc.equal) 163 } 164 } 165} 166 167func TestWrappedTimstamp_MarshalReflexivity(t *testing.T) { 168 testCases := []struct { 169 desc string 170 data WrappedTimestamp 171 }{ 172 {"Reference", WrappedTimestamp{0, Timestamp{referenceTime}}}, 173 {"Empty", WrappedTimestamp{0, Timestamp{}}}, 174 } 175 for _, tc := range testCases { 176 bytes, err := json.Marshal(tc.data) 177 if err != nil { 178 t.Errorf("%s: Marshal err=%v", tc.desc, err) 179 } 180 var got WrappedTimestamp 181 err = json.Unmarshal(bytes, &got) 182 if err != nil { 183 t.Errorf("%s: Unmarshal err=%v", tc.desc, err) 184 } 185 if !got.Time.Equal(tc.data.Time) { 186 t.Errorf("%s: %+v != %+v", tc.desc, got, tc.data) 187 } 188 } 189} 190