1// Copyright 2023 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 runtime_test
6
7import (
8	"reflect"
9	"runtime"
10	"runtime/metrics"
11	"testing"
12)
13
14func TestPanicNil(t *testing.T) {
15	t.Run("default", func(t *testing.T) {
16		checkPanicNil(t, new(runtime.PanicNilError))
17	})
18	t.Run("GODEBUG=panicnil=0", func(t *testing.T) {
19		t.Setenv("GODEBUG", "panicnil=0")
20		checkPanicNil(t, new(runtime.PanicNilError))
21	})
22	t.Run("GODEBUG=panicnil=1", func(t *testing.T) {
23		t.Setenv("GODEBUG", "panicnil=1")
24		checkPanicNil(t, nil)
25	})
26}
27
28func checkPanicNil(t *testing.T, want any) {
29	name := "/godebug/non-default-behavior/panicnil:events"
30	s := []metrics.Sample{{Name: name}}
31	metrics.Read(s)
32	v1 := s[0].Value.Uint64()
33
34	defer func() {
35		e := recover()
36		if reflect.TypeOf(e) != reflect.TypeOf(want) {
37			println(e, want)
38			t.Errorf("recover() = %v, want %v", e, want)
39			panic(e)
40		}
41		metrics.Read(s)
42		v2 := s[0].Value.Uint64()
43		if want == nil {
44			if v2 != v1+1 {
45				t.Errorf("recover() with panicnil=1 did not increment metric %s", name)
46			}
47		} else {
48			if v2 != v1 {
49				t.Errorf("recover() with panicnil=0 incremented metric %s: %d -> %d", name, v1, v2)
50			}
51		}
52	}()
53	panic(nil)
54}
55