github.com/GoogleCloudPlatform/testgrid@v0.0.174/resultstore/resultstore_test.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package resultstore 18 19 import ( 20 "fmt" 21 "reflect" 22 "testing" 23 "time" 24 25 durationpb "github.com/golang/protobuf/ptypes/duration" 26 timestamppb "github.com/golang/protobuf/ptypes/timestamp" 27 "google.golang.org/genproto/googleapis/devtools/resultstore/v2" 28 ) 29 30 func deepEqual(have, want interface{}) bool { 31 return reflect.DeepEqual(have, want) 32 } 33 34 func diff(have, want interface{}) string { 35 // TODO(fejta): something fancier 36 return fmt.Sprintf("got %v, want %v", have, want) 37 } 38 39 func TestDur(t *testing.T) { 40 cases := []struct { 41 name string 42 dur time.Duration 43 expected *durationpb.Duration 44 }{ 45 { 46 name: "basically works", 47 expected: &durationpb.Duration{}, 48 }, 49 { 50 name: "correct seconds", 51 dur: time.Minute, 52 expected: &durationpb.Duration{ 53 Seconds: 60, 54 }, 55 }, 56 { 57 name: "correct nanos", 58 dur: 300 * time.Nanosecond, 59 expected: &durationpb.Duration{ 60 Nanos: 300, 61 }, 62 }, 63 } 64 65 for _, tc := range cases { 66 t.Run(tc.name, func(t *testing.T) { 67 if actual := dur(tc.dur); !deepEqual(actual, tc.expected) { 68 t.Errorf(diff(actual, tc.expected)) 69 } 70 }) 71 } 72 } 73 74 func TestStamp(t *testing.T) { 75 cases := []struct { 76 name string 77 when time.Time 78 expected *timestamppb.Timestamp 79 }{ 80 { 81 name: "basically works", 82 }, 83 { 84 name: "correct when only seconds", 85 when: time.Unix(15, 0), 86 expected: ×tamppb.Timestamp{ 87 Seconds: 15, 88 }, 89 }, 90 { 91 name: "correct when only nanos", 92 when: time.Unix(0, 22), 93 expected: ×tamppb.Timestamp{ 94 Nanos: 22, 95 }, 96 }, 97 { 98 name: "normal", 99 when: time.Unix(33, 4444), 100 expected: ×tamppb.Timestamp{ 101 Seconds: 33, 102 Nanos: 4444, 103 }, 104 }, 105 } 106 107 for _, tc := range cases { 108 t.Run(tc.name, func(t *testing.T) { 109 if actual := stamp(tc.when); !deepEqual(actual, tc.expected) { 110 t.Errorf(diff(actual, tc.expected)) 111 } 112 }) 113 } 114 } 115 116 func TestTiming(t *testing.T) { 117 now := time.Now() 118 cases := []struct { 119 name string 120 when time.Time 121 d time.Duration 122 expected *resultstore.Timing 123 }{ 124 { 125 name: "basically works", 126 }, 127 { 128 name: "only when", 129 when: now, 130 expected: &resultstore.Timing{ 131 StartTime: stamp(now), 132 }, 133 }, 134 { 135 name: "only duration", 136 d: time.Second, 137 expected: &resultstore.Timing{ 138 Duration: dur(time.Second), 139 }, 140 }, 141 } 142 143 for _, tc := range cases { 144 t.Run(tc.name, func(t *testing.T) { 145 actual := timing(tc.when, tc.d) 146 if !deepEqual(actual, tc.expected) { 147 t.Errorf(diff(actual, tc.expected)) 148 } 149 }) 150 } 151 } 152 153 func TestFromTiming(t *testing.T) { 154 cases := []struct { 155 name string 156 t *resultstore.Timing 157 when time.Time 158 dur time.Duration 159 }{ 160 { 161 name: "basically works", 162 }, 163 { 164 name: "only StartTime works", 165 t: &resultstore.Timing{ 166 StartTime: ×tamppb.Timestamp{ 167 Seconds: 15, 168 Nanos: 7, 169 }, 170 }, 171 when: time.Unix(15, 7), 172 }, 173 { 174 name: "only Duration works", 175 t: &resultstore.Timing{ 176 Duration: &durationpb.Duration{ 177 Seconds: 3, 178 Nanos: 4, 179 }, 180 }, 181 dur: 3*time.Second + 4*time.Nanosecond, 182 }, 183 } 184 185 for _, tc := range cases { 186 t.Run(tc.name, func(t *testing.T) { 187 when, dur := fromTiming(tc.t) 188 if !when.Equal(tc.when) { 189 t.Errorf("when: %v != expected %v", when, tc.when) 190 } 191 if dur != tc.dur { 192 t.Errorf("dur: %v != expected %v", dur, tc.dur) 193 } 194 }) 195 } 196 } 197 198 func TestProperties(t *testing.T) { 199 cases := []struct { 200 name string 201 shock bool 202 input []string 203 expected []Property 204 }{ 205 { 206 name: "basically works", 207 }, 208 { 209 name: "one pair works", 210 input: []string{"hello", "world"}, 211 expected: []Property{ 212 { 213 Key: "hello", 214 Value: "world", 215 }, 216 }, 217 }, 218 { 219 name: "two pairs work", 220 input: []string{"key1", "value1", "key2", "value2"}, 221 expected: []Property{ 222 { 223 Key: "key1", 224 Value: "value1", 225 }, 226 { 227 Key: "key2", 228 Value: "value2", 229 }, 230 }, 231 }, 232 { 233 name: "unbalanced pairs panic", 234 input: []string{"key1", "value1", "panic"}, 235 shock: true, 236 }, 237 } 238 239 for _, tc := range cases { 240 t.Run(tc.name, func(t *testing.T) { 241 var shocked bool 242 func() { 243 defer func() { 244 if r := recover(); r != nil { 245 shocked = true 246 } 247 }() 248 actual := Properties(tc.input...) 249 if !deepEqual(actual, tc.expected) { 250 t.Errorf(diff(actual, tc.expected)) 251 } 252 }() 253 if shocked != tc.shock { 254 t.Errorf("shock %t != expected %t", shocked, tc.shock) 255 } 256 }) 257 } 258 } 259 260 func TestFromTarget(t *testing.T) { 261 now := time.Now() 262 cases := []struct { 263 name string 264 t *resultstore.Target 265 expected Target 266 }{ 267 { 268 name: "empty fromTarget works", 269 t: &resultstore.Target{ 270 Name: "Empty Target", 271 }, 272 expected: Target{ 273 Name: "Empty Target", 274 }, 275 }, 276 { 277 name: "fromTarget with empty properties", 278 t: &resultstore.Target{ 279 Name: "Empty Properties", 280 TargetAttributes: &resultstore.TargetAttributes{ 281 Tags: []string{ 282 "attr1", 283 }, 284 }, 285 }, 286 expected: Target{ 287 Name: "Empty Properties", 288 Tags: []string{ 289 "attr1", 290 }, 291 }, 292 }, 293 { 294 name: "fromTarget with properties", 295 t: &resultstore.Target{ 296 Name: "Contain Properties", 297 TargetAttributes: &resultstore.TargetAttributes{ 298 Tags: []string{ 299 "attr1", 300 "attr2", 301 }, 302 }, 303 Properties: []*resultstore.Property{ 304 { 305 Key: "key1", 306 Value: "val1", 307 }, 308 { 309 Key: "key2", 310 Value: "val2", 311 }, 312 }, 313 }, 314 expected: Target{ 315 Name: "Contain Properties", 316 Tags: []string{ 317 "attr1", 318 "attr2", 319 }, 320 Properties: []Property{ 321 { 322 Key: "key1", 323 Value: "val1", 324 }, 325 { 326 Key: "key2", 327 Value: "val2", 328 }, 329 }, 330 }, 331 }, 332 { 333 name: "test all attributes of target", 334 t: &resultstore.Target{ 335 Name: "All Attributes", 336 TargetAttributes: &resultstore.TargetAttributes{ 337 Tags: []string{ 338 "attr1", 339 }, 340 }, 341 Properties: []*resultstore.Property{ 342 { 343 Key: "key1", 344 Value: "val1", 345 }, 346 }, 347 Timing: &resultstore.Timing{ 348 StartTime: stamp(now), 349 Duration: dur(time.Second), 350 }, 351 StatusAttributes: &resultstore.StatusAttributes{ 352 Status: resultstore.Status_STATUS_UNSPECIFIED, 353 Description: "description1", 354 }, 355 }, 356 expected: Target{ 357 Name: "All Attributes", 358 Tags: []string{ 359 "attr1", 360 }, 361 Properties: []Property{ 362 { 363 Key: "key1", 364 Value: "val1", 365 }, 366 }, 367 Start: now, 368 Duration: time.Second, 369 Status: resultstore.Status_STATUS_UNSPECIFIED, 370 Description: "description1", 371 }, 372 }, 373 } 374 375 for _, tc := range cases { 376 t.Run(tc.name, func(t *testing.T) { 377 tgt := fromTarget(tc.t) 378 if !deepEqual(tgt.Name, tc.expected.Name) { 379 t.Errorf(diff(tgt.Name, tc.expected.Name)) 380 } 381 if !deepEqual(tgt.Tags, tc.expected.Tags) { 382 t.Errorf(diff(tgt.Tags, tc.expected.Tags)) 383 } 384 if !deepEqual(tgt.Properties, tc.expected.Properties) { 385 t.Errorf(diff(tgt.Properties, tc.expected.Properties)) 386 } 387 if !deepEqual(tgt.Duration, tc.expected.Duration) { 388 t.Errorf(diff(tgt.Duration, tc.expected.Duration)) 389 } 390 if !deepEqual(tgt.Status, tc.expected.Status) { 391 t.Errorf(diff(tgt.Status, tc.expected.Status)) 392 } 393 if !deepEqual(tgt.Description, tc.expected.Description) { 394 t.Errorf(diff(tgt.Description, tc.expected.Description)) 395 } 396 }) 397 } 398 }