OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [testsuite/] [go.test/] [test/] [recover.go] - Rev 700

Compare with Previous | Blame | View Log

// $G $D/$F.go && $L $F.$A && ./$A.out

// Copyright 2010 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.

// Test of basic recover functionality.

package main

import "runtime"

func main() {
        test1()
        test1WithClosures()
        test2()
        test3()
        test4()
        test5()
        test6()
        test6WithClosures()
        test7()
}

func die() {
        runtime.Breakpoint() // can't depend on panic
}

func mustRecover(x interface{}) {
        mustNotRecover() // because it's not a defer call
        v := recover()
        if v == nil {
                println("missing recover")
                die() // panic is useless here
        }
        if v != x {
                println("wrong value", v, x)
                die()
        }

        // the value should be gone now regardless
        v = recover()
        if v != nil {
                println("recover didn't recover")
                die()
        }
}

func mustNotRecover() {
        v := recover()
        if v != nil {
                println("spurious recover", v)
                die()
        }
}

func withoutRecover() {
        mustNotRecover() // because it's a sub-call
}

func test1() {
        defer mustNotRecover() // because mustRecover will squelch it
        defer mustRecover(1)   // because of panic below
        defer withoutRecover() // should be no-op, leaving for mustRecover to find
        panic(1)
}

// Repeat test1 with closures instead of standard function.
// Interesting because recover bases its decision
// on the frame pointer of its caller, and a closure's
// frame pointer is in the middle of its actual arguments
// (after the hidden ones for the closed-over variables).
func test1WithClosures() {
        defer func() {
                v := recover()
                if v != nil {
                        println("spurious recover in closure")
                        die()
                }
        }()
        defer func(x interface{}) {
                mustNotRecover()
                v := recover()
                if v == nil {
                        println("missing recover")
                        die()
                }
                if v != x {
                        println("wrong value", v, x)
                        die()
                }
        }(1)
        defer func() {
                mustNotRecover()
        }()
        panic(1)
}

func test2() {
        // Recover only sees the panic argument
        // if it is called from a deferred call.
        // It does not see the panic when called from a call within a deferred call (too late)
        // nor does it see the panic when it *is* the deferred call (too early).
        defer mustRecover(2)
        defer recover() // should be no-op
        panic(2)
}

func test3() {
        defer mustNotRecover()
        defer func() {
                recover() // should squelch
        }()
        panic(3)
}

func test4() {
        // Equivalent to test3 but using defer to make the call.
        defer mustNotRecover()
        defer func() {
                defer recover() // should squelch
        }()
        panic(4)
}

// Check that closures can set output arguments.
// Run g().  If it panics, return x; else return deflt.
func try(g func(), deflt interface{}) (x interface{}) {
        defer func() {
                if v := recover(); v != nil {
                        x = v
                }
        }()
        defer g()
        return deflt
}

// Check that closures can set output arguments.
// Run g().  If it panics, return x; else return deflt.
func try1(g func(), deflt interface{}) (x interface{}) {
        defer func() {
                if v := recover(); v != nil {
                        x = v
                }
        }()
        defer g()
        x = deflt
        return
}

func test5() {
        v := try(func() { panic(5) }, 55).(int)
        if v != 5 {
                println("wrong value", v, 5)
                die()
        }

        s := try(func() {}, "hi").(string)
        if s != "hi" {
                println("wrong value", s, "hi")
                die()
        }

        v = try1(func() { panic(5) }, 55).(int)
        if v != 5 {
                println("try1 wrong value", v, 5)
                die()
        }

        s = try1(func() {}, "hi").(string)
        if s != "hi" {
                println("try1 wrong value", s, "hi")
                die()
        }
}

// When a deferred big call starts, it must first
// create yet another stack segment to hold the
// giant frame for x.  Make sure that doesn't
// confuse recover.
func big(mustRecover bool) {
        var x [100000]int
        x[0] = 1
        x[99999] = 1
        _ = x

        v := recover()
        if mustRecover {
                if v == nil {
                        println("missing big recover")
                        die()
                }
        } else {
                if v != nil {
                        println("spurious big recover")
                        die()
                }
        }
}

func test6() {
        defer big(false)
        defer big(true)
        panic(6)
}

func test6WithClosures() {
        defer func() {
                var x [100000]int
                x[0] = 1
                x[99999] = 1
                _ = x
                if recover() != nil {
                        println("spurious big closure recover")
                        die()
                }
        }()
        defer func() {
                var x [100000]int
                x[0] = 1
                x[99999] = 1
                _ = x
                if recover() == nil {
                        println("missing big closure recover")
                        die()
                }
        }()
        panic("6WithClosures")
}

func test7() {
        ok := false
        func() {
                // should panic, then call mustRecover 7, which stops the panic.
                // then should keep processing ordinary defers earlier than that one
                // before returning.
                // this test checks that the defer func on the next line actually runs.
                defer func() { ok = true }()
                defer mustRecover(7)
                panic(7)
        }()
        if !ok {
                println("did not run ok func")
                die()
        }
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.