github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/goid/goid_test.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package goid 16 17 import ( 18 "runtime" 19 "sync" 20 "testing" 21 "time" 22 ) 23 24 func TestUniquenessAndConsistency(t *testing.T) { 25 const ( 26 numGoroutines = 5000 27 28 // maxID is not an intrinsic property of goroutine IDs; it is only a 29 // property of how the Go runtime currently assigns them. Future 30 // changes to the Go runtime may require that maxID be raised, or that 31 // assertions regarding it be removed entirely. 32 maxID = numGoroutines + 1000 33 ) 34 35 var ( 36 goidsMu sync.Mutex 37 goids = make(map[int64]struct{}) 38 checkedWG sync.WaitGroup 39 exitCh = make(chan struct{}) 40 ) 41 for i := 0; i < numGoroutines; i++ { 42 checkedWG.Add(1) 43 go func() { 44 id := Get() 45 if id > maxID { 46 t.Errorf("observed unexpectedly large goroutine ID %d", id) 47 } 48 goidsMu.Lock() 49 if _, dup := goids[id]; dup { 50 t.Errorf("observed duplicate goroutine ID %d", id) 51 } 52 goids[id] = struct{}{} 53 goidsMu.Unlock() 54 checkedWG.Done() 55 for { 56 if curID := Get(); curID != id { 57 t.Errorf("goroutine ID changed from %d to %d", id, curID) 58 // Don't spam logs by repeating the check; wait quietly for 59 // the test to finish. 60 <-exitCh 61 return 62 } 63 // Check if the test is over. 64 select { 65 case <-exitCh: 66 return 67 default: 68 } 69 // Yield to other goroutines, and possibly migrate to another P. 70 runtime.Gosched() 71 } 72 }() 73 } 74 // Wait for all goroutines to perform uniqueness checks. 75 checkedWG.Wait() 76 // Wait for an additional second to allow goroutines to spin checking for 77 // ID consistency. 78 time.Sleep(time.Second) 79 // Request that all goroutines exit. 80 close(exitCh) 81 }