Yuxuan 'fishy' Wang | 19c13b4 | 2022-10-12 14:13:15 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
| 19 | |
| 20 | package thrift |
| 21 | |
| 22 | import ( |
| 23 | "fmt" |
| 24 | "testing" |
| 25 | "testing/quick" |
| 26 | ) |
| 27 | |
| 28 | func TestHexToByte(t *testing.T) { |
| 29 | for _, c := range []struct { |
| 30 | s string |
| 31 | b byte |
| 32 | fail bool |
| 33 | }{ |
| 34 | { |
| 35 | s: "ff", |
| 36 | b: 0xff, |
| 37 | }, |
| 38 | { |
| 39 | s: "FF", |
| 40 | b: 0xff, |
| 41 | }, |
| 42 | { |
| 43 | s: "00", |
| 44 | b: 0, |
| 45 | }, |
| 46 | { |
| 47 | s: "77", |
| 48 | b: 0x77, |
| 49 | }, |
| 50 | { |
| 51 | s: "aC", |
| 52 | b: 0xac, |
| 53 | }, |
| 54 | { |
| 55 | s: "xx", |
| 56 | fail: true, |
| 57 | }, |
| 58 | { |
| 59 | s: "x0", |
| 60 | fail: true, |
| 61 | }, |
| 62 | { |
| 63 | s: "fx", |
| 64 | fail: true, |
| 65 | }, |
| 66 | } { |
| 67 | t.Run(c.s, func(t *testing.T) { |
| 68 | b, ok := hexToByte(c.s[0], c.s[1]) |
| 69 | if ok != !c.fail { |
| 70 | t.Errorf("Want failure, got %x, %v", b, ok) |
| 71 | } |
| 72 | if !c.fail && b != c.b { |
| 73 | t.Errorf("Want %x, got %x", c.b, b) |
| 74 | } |
| 75 | }) |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | func TestUUIDString(t *testing.T) { |
| 80 | for _, c := range []struct { |
| 81 | uuid Tuuid |
| 82 | want string |
| 83 | }{ |
| 84 | { |
| 85 | uuid: Tuuid{}, |
| 86 | want: "00000000-0000-0000-0000-000000000000", |
| 87 | }, |
| 88 | { |
| 89 | uuid: Tuuid{ |
| 90 | 0x6b, 0xa7, 0xb8, 0x10, |
| 91 | 0x9d, 0xad, |
| 92 | 0x11, 0xd1, |
| 93 | 0x80, 0xb4, |
| 94 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 95 | }, |
| 96 | want: "6ba7b810-9dad-11d1-80b4-00c04fd430c8", |
| 97 | }, |
| 98 | { |
| 99 | uuid: Tuuid{ |
| 100 | 0x6b, 0xa7, 0xB8, 0x11, |
| 101 | 0x9d, 0xAd, |
| 102 | 0x11, 0xd1, |
| 103 | 0x80, 0xb4, |
| 104 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 105 | }, |
| 106 | want: "6ba7b811-9dad-11d1-80b4-00c04fd430c8", |
| 107 | }, |
| 108 | { |
| 109 | uuid: Tuuid{ |
| 110 | 0x6b, 0xa7, 0xb8, 0x12, |
| 111 | 0x9d, 0xad, |
| 112 | 0x11, 0xd1, |
| 113 | 0x80, 0xb4, |
| 114 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 115 | }, |
| 116 | want: "6ba7b812-9dad-11d1-80b4-00c04fd430c8", |
| 117 | }, |
| 118 | { |
| 119 | uuid: Tuuid{ |
| 120 | 0x6b, 0xa7, 0xb8, 0x14, |
| 121 | 0x9d, 0xad, |
| 122 | 0x11, 0xd1, |
| 123 | 0x80, 0xb4, |
| 124 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 125 | }, |
| 126 | want: "6ba7b814-9dad-11d1-80b4-00c04fd430c8", |
| 127 | }, |
| 128 | } { |
| 129 | t.Run(fmt.Sprintf("% 02x", c.uuid[:]), func(t *testing.T) { |
| 130 | got := c.uuid.String() |
| 131 | if got != c.want { |
| 132 | t.Errorf("got %q, want %q", got, c.want) |
| 133 | } |
| 134 | }) |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | func TestUUIDParse(t *testing.T) { |
| 139 | for _, c := range []struct { |
| 140 | uuid string |
| 141 | want Tuuid |
| 142 | err bool |
| 143 | }{ |
| 144 | { |
| 145 | uuid: "00000000-0000-0000-0000-000000000000", |
| 146 | want: Tuuid{ |
| 147 | 0x00, 0x00, 0x00, 0x00, |
| 148 | 0x00, 0x00, |
| 149 | 0x00, 0x00, |
| 150 | 0x00, 0x00, |
| 151 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 152 | }, |
| 153 | }, |
| 154 | { |
| 155 | uuid: "6BA7B810-9DAD-11D1-80B4-00C04FD430C8", |
| 156 | want: Tuuid{ |
| 157 | 0x6B, 0xA7, 0xB8, 0x10, |
| 158 | 0x9D, 0xAD, |
| 159 | 0x11, 0xD1, |
| 160 | 0x80, 0xB4, |
| 161 | 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8, |
| 162 | }, |
| 163 | }, |
| 164 | { |
| 165 | uuid: "6ba7B811-9dAd-11d1-80b4-00c04fd430c8", |
| 166 | want: Tuuid{ |
| 167 | 0x6b, 0xa7, 0xB8, 0x11, |
| 168 | 0x9d, 0xAd, |
| 169 | 0x11, 0xd1, |
| 170 | 0x80, 0xb4, |
| 171 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 172 | }, |
| 173 | }, |
| 174 | { |
| 175 | uuid: "6ba7b812-9dad-11d1-80b4-00c04fd430c8", |
| 176 | want: Tuuid{ |
| 177 | 0x6b, 0xa7, 0xb8, 0x12, |
| 178 | 0x9d, 0xad, |
| 179 | 0x11, 0xd1, |
| 180 | 0x80, 0xb4, |
| 181 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 182 | }, |
| 183 | }, |
| 184 | { |
| 185 | uuid: "6ba7b814-9dad-11d1-80b4-00c04fd430c8", |
| 186 | want: Tuuid{ |
| 187 | 0x6b, 0xa7, 0xb8, 0x14, |
| 188 | 0x9d, 0xad, |
| 189 | 0x11, 0xd1, |
| 190 | 0x80, 0xb4, |
| 191 | 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, |
| 192 | }, |
| 193 | }, |
| 194 | { |
| 195 | uuid: "00000000000000000000000000000000", |
| 196 | err: true, // not in canonical form |
| 197 | }, |
| 198 | { |
| 199 | uuid: "6ba7b810-9d-ad11d1-80b4-00c04fd430c8", |
| 200 | err: true, // wrong position of hyphens |
| 201 | }, |
| 202 | { |
| 203 | uuid: "urn:uuid:6ba7b811-9dad-11d1-80b4-00c04fd430c8", |
| 204 | err: true, // urn form is not supported |
| 205 | }, |
| 206 | { |
| 207 | uuid: "{6ba7b812-9dad-11d1-80b4-00c04fd430c8}", |
| 208 | err: true, // guid with braces form is not supported |
| 209 | }, |
| 210 | { |
| 211 | uuid: "6xa7b814-9dad-11d1-80b4-00c04fd430c8", |
| 212 | err: true, // non-hex numbers |
| 213 | }, |
| 214 | } { |
| 215 | t.Run(c.uuid, func(t *testing.T) { |
| 216 | uuid, err := ParseTuuid(c.uuid) |
| 217 | if c.err { |
| 218 | if err == nil { |
| 219 | t.Errorf("Got %v, want error", uuid) |
| 220 | } |
| 221 | } else { |
| 222 | if err != nil { |
| 223 | t.Errorf("Failed to parse: %v", err) |
| 224 | } |
| 225 | if uuid != c.want { |
| 226 | t.Errorf("Got %v, want %v", uuid, c.want) |
| 227 | } |
| 228 | } |
| 229 | }) |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | func TestUUIDQuick(t *testing.T) { |
| 234 | f := func(u Tuuid) bool { |
| 235 | s := u.String() |
| 236 | parsed, err := ParseTuuid(s) |
| 237 | if err != nil { |
| 238 | t.Error(err) |
| 239 | } |
| 240 | if parsed != u { |
| 241 | t.Errorf("Parsed %v want %v", parsed, u) |
| 242 | } |
| 243 | return !t.Failed() |
| 244 | } |
| 245 | if err := quick.Check(f, nil); err != nil { |
| 246 | t.Error(err) |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | func BenchmarkUUIDParse(b *testing.B) { |
| 251 | for _, s := range []string{ |
| 252 | "00000000-0000-0000-0000-000000000000", |
| 253 | "6ba7b810-9dad-11d1-80b4-00c04fd430c8", |
| 254 | "6ba7b811-9dad-11d1-80b4-00c04fd430c8", |
| 255 | "6ba7b812-9dad-11d1-80b4-00c04fd430c8", |
| 256 | "6ba7b814-9dad-11d1-80b4-00c04fd430c8", |
| 257 | } { |
| 258 | b.Run(s, func(b *testing.B) { |
| 259 | b.ReportAllocs() |
| 260 | if _, err := ParseTuuid(s); err != nil { |
| 261 | b.Fatalf("Unable to parse %q: %v", s, err) |
| 262 | } |
| 263 | b.ResetTimer() |
| 264 | b.RunParallel(func(pb *testing.PB) { |
| 265 | for pb.Next() { |
| 266 | ParseTuuid(s) |
| 267 | } |
| 268 | }) |
| 269 | }) |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | func BenchmarkUUIDString(b *testing.B) { |
| 274 | for _, u := range []Tuuid{ |
| 275 | {}, |
| 276 | Must(ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8")), |
| 277 | Must(ParseTuuid("6ba7b811-9dad-11d1-80b4-00c04fd430c8")), |
| 278 | Must(ParseTuuid("6ba7b812-9dad-11d1-80b4-00c04fd430c8")), |
| 279 | Must(ParseTuuid("6ba7b814-9dad-11d1-80b4-00c04fd430c8")), |
| 280 | } { |
| 281 | b.Run(u.String(), func(b *testing.B) { |
| 282 | b.ReportAllocs() |
| 283 | b.RunParallel(func(pb *testing.PB) { |
| 284 | for pb.Next() { |
| 285 | _ = u.String() |
| 286 | } |
| 287 | }) |
| 288 | }) |
| 289 | } |
| 290 | } |