github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/runtime/abi_test.go (about) 1 // Copyright 2021 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 5 //go:build goexperiment.regabireflect 6 // +build goexperiment.regabireflect 7 8 // This file contains tests specific to making sure the register ABI 9 // works in a bunch of contexts in the runtime. 10 11 package runtime_test 12 13 import ( 14 "github.com/comwrg/go/src/internal/abi" 15 "github.com/comwrg/go/src/internal/testenv" 16 "os" 17 "os/exec" 18 "runtime" 19 "strings" 20 "testing" 21 "time" 22 ) 23 24 var regConfirmRun chan int 25 26 //go:registerparams 27 func regFinalizerPointer(v *Tint) (int, float32, [10]byte) { 28 regConfirmRun <- *(*int)(v) 29 return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 30 } 31 32 //go:registerparams 33 func regFinalizerIface(v Tinter) (int, float32, [10]byte) { 34 regConfirmRun <- *(*int)(v.(*Tint)) 35 return 5151, 4.0, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 36 } 37 38 func TestFinalizerRegisterABI(t *testing.T) { 39 testenv.MustHaveExec(t) 40 41 // Actually run the test in a subprocess because we don't want 42 // finalizers from other tests interfering. 43 if os.Getenv("TEST_FINALIZER_REGABI") != "1" { 44 cmd := testenv.CleanCmdEnv(exec.Command(os.Args[0], "-test.run=TestFinalizerRegisterABI", "-test.v")) 45 cmd.Env = append(cmd.Env, "TEST_FINALIZER_REGABI=1") 46 out, err := cmd.CombinedOutput() 47 if !strings.Contains(string(out), "PASS\n") || err != nil { 48 t.Fatalf("%s\n(exit status %v)", string(out), err) 49 } 50 return 51 } 52 53 // Optimistically clear any latent finalizers from e.g. the testing 54 // package before continuing. 55 // 56 // It's possible that a finalizer only becomes available to run 57 // after this point, which would interfere with the test and could 58 // cause a crash, but because we're running in a separate process 59 // it's extremely unlikely. 60 runtime.GC() 61 runtime.GC() 62 63 // fing will only pick the new IntRegArgs up if it's currently 64 // sleeping and wakes up, so wait for it to go to sleep. 65 success := false 66 for i := 0; i < 100; i++ { 67 if runtime.FinalizerGAsleep() { 68 success = true 69 break 70 } 71 time.Sleep(20 * time.Millisecond) 72 } 73 if !success { 74 t.Fatal("finalizer not asleep?") 75 } 76 77 argRegsBefore := runtime.SetIntArgRegs(abi.IntArgRegs) 78 defer runtime.SetIntArgRegs(argRegsBefore) 79 80 tests := []struct { 81 name string 82 fin interface{} 83 confirmValue int 84 }{ 85 {"Pointer", regFinalizerPointer, -1}, 86 {"Interface", regFinalizerIface, -2}, 87 } 88 for i := range tests { 89 test := &tests[i] 90 t.Run(test.name, func(t *testing.T) { 91 regConfirmRun = make(chan int) 92 93 x := new(Tint) 94 *x = (Tint)(test.confirmValue) 95 runtime.SetFinalizer(x, test.fin) 96 97 runtime.KeepAlive(x) 98 99 // Queue the finalizer. 100 runtime.GC() 101 runtime.GC() 102 103 select { 104 case <-time.After(time.Second): 105 t.Fatal("finalizer failed to execute") 106 case gotVal := <-regConfirmRun: 107 if gotVal != test.confirmValue { 108 t.Fatalf("wrong finalizer executed? got %d, want %d", gotVal, test.confirmValue) 109 } 110 } 111 }) 112 } 113 }