| // Copyright 2014 Google Inc. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package uuid |
| |
| import ( |
| "flag" |
| "runtime" |
| "testing" |
| "time" |
| ) |
| |
| // This test is only run when --regressions is passed on the go test line. |
| var regressions = flag.Bool("regressions", false, "run uuid regression tests") |
| |
| // TestClockSeqRace tests for a particular race condition of returning two |
| // identical Version1 UUIDs. The duration of 1 minute was chosen as the race |
| // condition, before being fixed, nearly always occured in under 30 seconds. |
| func TestClockSeqRace(t *testing.T) { |
| if !*regressions { |
| t.Skip("skipping regression tests") |
| } |
| duration := time.Minute |
| |
| done := make(chan struct{}) |
| defer close(done) |
| |
| ch := make(chan UUID, 10000) |
| ncpu := runtime.NumCPU() |
| switch ncpu { |
| case 0, 1: |
| // We can't run the test effectively. |
| t.Skip("skipping race test, only one CPU detected") |
| return |
| default: |
| runtime.GOMAXPROCS(ncpu) |
| } |
| for i := 0; i < ncpu; i++ { |
| go func() { |
| for { |
| select { |
| case <-done: |
| return |
| case ch <- NewUUID(): |
| } |
| } |
| }() |
| } |
| |
| uuids := make(map[string]bool) |
| cnt := 0 |
| start := time.Now() |
| for u := range ch { |
| s := u.String() |
| if uuids[s] { |
| t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s) |
| return |
| } |
| uuids[s] = true |
| if time.Since(start) > duration { |
| return |
| } |
| cnt++ |
| } |
| } |