github.com/muyo/sno@v1.2.1/id_test.go (about) 1 package sno 2 3 import ( 4 "bytes" 5 "fmt" 6 "reflect" 7 "sync/atomic" 8 "testing" 9 "time" 10 ) 11 12 func TestID_Time(t *testing.T) { 13 tn := time.Now() 14 id := New(255) 15 16 // As we prune the fraction, actual cmp needs to be adjusted. This *may* also fail 17 // in the rare condition that a new timeframe started between time.Now() and New() 18 // since we're not using a deterministic time source currently. 19 expected := tn.UnixNano() / TimeUnit 20 actual := id.Time().UnixNano() / TimeUnit 21 22 if actual != expected { 23 t.Errorf("expected [%v], got [%v]", expected, actual) 24 } 25 26 id = NewWithTime(255, tn) 27 actual = id.Time().UnixNano() / TimeUnit 28 29 if actual != expected { 30 t.Errorf("expected [%v], got [%v]", expected, actual) 31 } 32 } 33 34 func TestID_Timestamp(t *testing.T) { 35 tn := time.Now() 36 id := New(255) 37 38 expected := tn.UnixNano() / TimeUnit * TimeUnit // Drop precision for the comparison. 39 actual := id.Timestamp() 40 41 if actual != expected { 42 t.Errorf("expected [%v], got [%v]", expected, actual) 43 } 44 45 id = NewWithTime(255, tn) 46 actual = id.Timestamp() 47 48 if actual != expected { 49 t.Errorf("expected [%v], got [%v]", expected, actual) 50 } 51 } 52 53 func TestID_Meta(t *testing.T) { 54 var expected byte = 255 55 id := New(expected) 56 actual := id.Meta() 57 58 if actual != expected { 59 t.Errorf("expected [%v], got [%v]", expected, actual) 60 } 61 } 62 63 func TestID_Partition(t *testing.T) { 64 expected := generator.Partition() 65 actual := generator.New(255).Partition() 66 67 if actual != expected { 68 t.Errorf("expected [%v], got [%v]", expected, actual) 69 } 70 } 71 72 func TestID_Sequence(t *testing.T) { 73 expected := atomic.LoadUint32(&generator.seq) + 1 74 actual := generator.New(255).Sequence() 75 76 if actual != uint16(expected) { 77 t.Errorf("expected [%v], got [%v]", expected, actual) 78 } 79 } 80 81 func TestID_String(t *testing.T) { 82 src := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 83 expected := "brpk4q72xwf2m63l" 84 actual := src.String() 85 86 if actual != expected { 87 t.Errorf("expected [%s], got [%s]", expected, actual) 88 } 89 } 90 91 func TestID_Bytes(t *testing.T) { 92 src := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 93 expected := make([]byte, SizeBinary) 94 copy(expected, src[:]) 95 96 actual := src.Bytes() 97 if !bytes.Equal(actual, expected) { 98 t.Errorf("expected [%s], got [%s]", expected, actual) 99 } 100 101 actual[SizeBinary-1]++ 102 if bytes.Equal(expected, actual) { 103 t.Error("returned a reference to underlying array") 104 } 105 } 106 107 func TestID_MarshalText(t *testing.T) { 108 src := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 109 expected := []byte("brpk4q72xwf2m63l") 110 111 actual, err := src.MarshalText() 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 if !bytes.Equal(actual, expected) { 117 t.Errorf("expected [%s], got [%s]", expected, actual) 118 } 119 } 120 121 func TestID_UnmarshalText_Valid(t *testing.T) { 122 actual := ID{} 123 expected := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 124 125 if err := actual.UnmarshalText([]byte("brpk4q72xwf2m63l")); err != nil { 126 t.Fatal(err) 127 } 128 129 if actual != expected { 130 t.Errorf("expected [%s], got [%s]", expected, actual) 131 } 132 } 133 134 func TestID_UnmarshalText_Invalid(t *testing.T) { 135 id := ID{} 136 err := id.UnmarshalText([]byte("012brpk4q72xwf2m63l1245453gfdgxz")) 137 138 if _, ok := err.(*InvalidDataSizeError); !ok { 139 t.Errorf("expected error with type [%T], got [%T]", &InvalidDataSizeError{}, err) 140 } 141 } 142 143 func TestID_MarshalJSON_Valid(t *testing.T) { 144 src := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 145 expected := []byte("\"brpk4q72xwf2m63l\"") 146 147 actual, err := src.MarshalJSON() 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 if !bytes.Equal(actual, expected) { 153 t.Errorf("expected [%s], got [%s]", expected, actual) 154 } 155 } 156 157 func TestID_MarshalJSON_Null(t *testing.T) { 158 src := ID{} 159 expected := []byte("null") 160 actual, err := src.MarshalJSON() 161 if err != nil { 162 t.Fatal(err) 163 } 164 165 if !bytes.Equal(actual, expected) { 166 t.Errorf("expected [%s], got [%s]", expected, actual) 167 } 168 } 169 170 func TestID_UnmarshalJSON_Valid(t *testing.T) { 171 actual := ID{} 172 expected := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 173 174 if err := actual.UnmarshalJSON([]byte("\"brpk4q72xwf2m63l\"")); err != nil { 175 t.Fatal(err) 176 } 177 178 if actual != expected { 179 t.Errorf("expected [%s], got [%s]", expected, actual) 180 } 181 } 182 183 func TestID_UnmarshalJSON_Invalid(t *testing.T) { 184 id := ID{} 185 err := id.UnmarshalJSON([]byte("\"012brpk4q72xwf2m63l1245453gfdgxz\"")) 186 187 if _, ok := err.(*InvalidDataSizeError); !ok { 188 t.Errorf("expected error with type [%T], got [%T]", &InvalidDataSizeError{}, err) 189 } 190 191 if err != nil && err.Error() != errInvalidDataSizeMsg { 192 t.Errorf("expected error [%s], got [%s]", errInvalidDataSizeMsg, err.Error()) 193 } 194 } 195 196 func TestID_UnmarshalJSON_Null(t *testing.T) { 197 actual := ID{} 198 expected := ID{} 199 200 if err := actual.UnmarshalJSON([]byte("null")); err != nil { 201 t.Fatal(err) 202 } 203 204 if actual != expected { 205 t.Errorf("expected [%s], got [%s]", expected, actual) 206 } 207 } 208 209 func TestID_IsZero(t *testing.T) { 210 for _, c := range []struct { 211 id ID 212 want bool 213 }{ 214 { 215 id: New(255), 216 want: false, 217 }, 218 { 219 id: ID{}, 220 want: true, 221 }, 222 } { 223 if actual, expected := c.id.IsZero(), c.want; actual != expected { 224 t.Errorf("expected [%v], got [%v]", expected, actual) 225 } 226 } 227 } 228 229 func TestID_Compare(t *testing.T) { 230 a := New(100) 231 l := a 232 l[5]++ 233 e := a 234 b := a 235 b[5]-- 236 237 if actual := a.Compare(l); actual != -1 { 238 t.Errorf("expected [-1], got [%d]", actual) 239 } 240 241 if actual := a.Compare(e); actual != 0 { 242 t.Errorf("expected [0], got [%d]", actual) 243 } 244 245 if actual := a.Compare(b); actual != 1 { 246 t.Errorf("expected [1], got [%d]", actual) 247 } 248 } 249 250 func TestID_Value(t *testing.T) { 251 src := ID{78, 111, 33, 96, 160, 255, 154, 10, 16, 51} 252 expected := make([]byte, SizeBinary) 253 copy(expected, src[:]) 254 255 v, err := src.Value() 256 if err != nil { 257 t.Errorf("got unexpected error: %s", err) 258 } 259 260 actual, ok := v.([]byte) 261 if !ok { 262 t.Errorf("expected type [%T], got [%T]", expected, actual) 263 } 264 265 if !bytes.Equal(actual, expected) { 266 t.Errorf("expected [%s], got [%s]", expected, actual) 267 } 268 269 actual[SizeBinary-1]++ 270 if bytes.Equal(expected, actual) { 271 t.Error("returned a reference to underlying array") 272 } 273 } 274 275 func TestID_Scan(t *testing.T) { 276 id := New(255) 277 278 for _, c := range []struct { 279 name string 280 in interface{} 281 out ID 282 err error 283 errMsg string 284 }{ 285 {"nil", nil, ID{}, nil, ""}, 286 {"bytes-valid", id[:], id, nil, ""}, 287 {"bytes-invalid", make([]byte, 3), zero, &InvalidDataSizeError{Size: 3}, errInvalidDataSizeMsg}, 288 {"bytes-zero", []byte{}, zero, nil, ""}, 289 {"string-valid", id.String(), id, nil, ""}, 290 {"string-invalid", "123", zero, &InvalidDataSizeError{Size: 3}, errInvalidDataSizeMsg}, 291 {"string-zero", "", zero, nil, ""}, 292 {"invalid", 69, ID{}, &InvalidTypeError{Value: 69}, fmt.Sprintf(errInvalidTypeFmt, 69)}, 293 } { 294 c := c 295 t.Run(c.name, func(t *testing.T) { 296 t.Parallel() 297 298 var out ID 299 err := out.Scan(c.in) 300 301 if actual, expected := out, c.out; actual != expected { 302 t.Errorf("expected [%s], got [%s]", expected, actual) 303 } 304 305 if err != nil && c.err == nil { 306 t.Errorf("got unexpected error: %s", err) 307 } else if actual, expected := reflect.TypeOf(err), reflect.TypeOf(c.err); actual != expected { 308 t.Errorf("expected error type [%s], got [%s]", expected, actual) 309 } else if err != nil && c.errMsg != "" && err.Error() != c.errMsg { 310 t.Errorf("expected error message [%s], got [%s]", c.errMsg, err.Error()) 311 } 312 }) 313 } 314 }