1// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8	"flag"
9	"internal/runtime/exithook"
10	"os"
11	"time"
12	_ "unsafe"
13)
14
15var modeflag = flag.String("mode", "", "mode to run in")
16
17func main() {
18	flag.Parse()
19	switch *modeflag {
20	case "simple":
21		testSimple()
22	case "goodexit":
23		testGoodExit()
24	case "badexit":
25		testBadExit()
26	case "panics":
27		testPanics()
28	case "callsexit":
29		testHookCallsExit()
30	case "exit2":
31		testExit2()
32	default:
33		panic("unknown mode")
34	}
35}
36
37func testSimple() {
38	f1 := func() { println("foo") }
39	f2 := func() { println("bar") }
40	exithook.Add(exithook.Hook{F: f1})
41	exithook.Add(exithook.Hook{F: f2})
42	// no explicit call to os.Exit
43}
44
45func testGoodExit() {
46	f1 := func() { println("apple") }
47	f2 := func() { println("orange") }
48	exithook.Add(exithook.Hook{F: f1})
49	exithook.Add(exithook.Hook{F: f2})
50	// explicit call to os.Exit
51	os.Exit(0)
52}
53
54func testBadExit() {
55	f1 := func() { println("blog") }
56	f2 := func() { println("blix") }
57	f3 := func() { println("blek") }
58	f4 := func() { println("blub") }
59	f5 := func() { println("blat") }
60	exithook.Add(exithook.Hook{F: f1})
61	exithook.Add(exithook.Hook{F: f2, RunOnFailure: true})
62	exithook.Add(exithook.Hook{F: f3})
63	exithook.Add(exithook.Hook{F: f4, RunOnFailure: true})
64	exithook.Add(exithook.Hook{F: f5})
65	os.Exit(1)
66}
67
68func testPanics() {
69	f1 := func() { println("ok") }
70	f2 := func() { panic("BADBADBAD") }
71	f3 := func() { println("good") }
72	exithook.Add(exithook.Hook{F: f1, RunOnFailure: true})
73	exithook.Add(exithook.Hook{F: f2, RunOnFailure: true})
74	exithook.Add(exithook.Hook{F: f3, RunOnFailure: true})
75	os.Exit(0)
76}
77
78func testHookCallsExit() {
79	f1 := func() { println("ok") }
80	f2 := func() { os.Exit(1) }
81	f3 := func() { println("good") }
82	exithook.Add(exithook.Hook{F: f1, RunOnFailure: true})
83	exithook.Add(exithook.Hook{F: f2, RunOnFailure: true})
84	exithook.Add(exithook.Hook{F: f3, RunOnFailure: true})
85	os.Exit(1)
86}
87
88func testExit2() {
89	f1 := func() { time.Sleep(100 * time.Millisecond) }
90	exithook.Add(exithook.Hook{F: f1})
91	for range 10 {
92		go os.Exit(0)
93	}
94	os.Exit(0)
95}
96