| // Copyright 2023 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package main | |
| import ( | |
| "fmt" | |
| "log" | |
| "net" | |
| "os" | |
| "runtime" | |
| "runtime/trace" | |
| "sync" | |
| "syscall" | |
| "time" | |
| ) | |
| func main() { | |
| if err := trace.Start(os.Stdout); err != nil { | |
| log.Fatal(err) | |
| } | |
| // checkExecutionTimes relies on this. | |
| var wg sync.WaitGroup | |
| wg.Add(2) | |
| go cpu10(&wg) | |
| go cpu20(&wg) | |
| wg.Wait() | |
| // checkHeapMetrics relies on this. | |
| allocHog(25 * time.Millisecond) | |
| // checkProcStartStop relies on this. | |
| var wg2 sync.WaitGroup | |
| for i := 0; i < runtime.GOMAXPROCS(0); i++ { | |
| wg2.Add(1) | |
| go func() { | |
| defer wg2.Done() | |
| cpuHog(50 * time.Millisecond) | |
| }() | |
| } | |
| wg2.Wait() | |
| // checkSyscalls relies on this. | |
| done := make(chan error) | |
| go blockingSyscall(50*time.Millisecond, done) | |
| if err := <-done; err != nil { | |
| log.Fatal(err) | |
| } | |
| // checkNetworkUnblock relies on this. | |
| ln, err := net.Listen("tcp", "127.0.0.1:0") | |
| if err != nil { | |
| log.Fatalf("listen failed: %v", err) | |
| } | |
| defer ln.Close() | |
| go func() { | |
| c, err := ln.Accept() | |
| if err != nil { | |
| return | |
| } | |
| time.Sleep(time.Millisecond) | |
| var buf [1]byte | |
| c.Write(buf[:]) | |
| c.Close() | |
| }() | |
| c, err := net.Dial("tcp", ln.Addr().String()) | |
| if err != nil { | |
| log.Fatalf("dial failed: %v", err) | |
| } | |
| var tmp [1]byte | |
| c.Read(tmp[:]) | |
| c.Close() | |
| trace.Stop() | |
| } | |
| // blockingSyscall blocks the current goroutine for duration d in a syscall and | |
| // sends a message to done when it is done or if the syscall failed. | |
| func blockingSyscall(d time.Duration, done chan<- error) { | |
| r, w, err := os.Pipe() | |
| if err != nil { | |
| done <- err | |
| return | |
| } | |
| start := time.Now() | |
| msg := []byte("hello") | |
| time.AfterFunc(d, func() { w.Write(msg) }) | |
| _, err = syscall.Read(int(r.Fd()), make([]byte, len(msg))) | |
| if err == nil && time.Since(start) < d { | |
| err = fmt.Errorf("syscall returned too early: want=%s got=%s", d, time.Since(start)) | |
| } | |
| done <- err | |
| } | |
| func cpu10(wg *sync.WaitGroup) { | |
| defer wg.Done() | |
| cpuHog(10 * time.Millisecond) | |
| } | |
| func cpu20(wg *sync.WaitGroup) { | |
| defer wg.Done() | |
| cpuHog(20 * time.Millisecond) | |
| } | |
| func cpuHog(dt time.Duration) { | |
| start := time.Now() | |
| for i := 0; ; i++ { | |
| if i%1000 == 0 && time.Since(start) > dt { | |
| return | |
| } | |
| } | |
| } | |
| func allocHog(dt time.Duration) { | |
| start := time.Now() | |
| var s [][]byte | |
| for i := 0; ; i++ { | |
| if i%1000 == 0 { | |
| if time.Since(start) > dt { | |
| return | |
| } | |
| // Take a break... this will generate a ton of events otherwise. | |
| time.Sleep(50 * time.Microsecond) | |
| } | |
| s = append(s, make([]byte, 1024)) | |
| } | |
| } |