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

Subversion Repositories openrisc

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

Compare with Previous | Blame | View Log

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

// Copyright 2009 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 close(c), receive of closed channel.
//
// TODO(rsc): Doesn't check behavior of close(c) when there
// are blocked senders/receivers.

package main

import "os"

var failed bool

type Chan interface {
        Send(int)
        Nbsend(int) bool
        Recv() (int)
        Nbrecv() (int, bool)
        Recv2() (int, bool)
        Nbrecv2() (int, bool, bool)
        Close()
        Impl() string
}

// direct channel operations when possible
type XChan chan int

func (c XChan) Send(x int) {
        c <- x
}

func (c XChan) Nbsend(x int) bool {
        select {
        case c <- x:
                return true
        default:
                return false
        }
        panic("nbsend")
}

func (c XChan) Recv() int {
        return <-c
}

func (c XChan) Nbrecv() (int, bool) {
        select {
        case x := <-c:
                return x, true
        default:
                return 0, false
        }
        panic("nbrecv")
}

func (c XChan) Recv2() (int, bool) {
        x, ok := <-c
        return x, ok
}

func (c XChan) Nbrecv2() (int, bool, bool) {
        select {
        case x, ok := <-c:
                return x, ok, true
        default:
                return 0, false, false
        }
        panic("nbrecv2")
}

func (c XChan) Close() {
        close(c)
}

func (c XChan) Impl() string {
        return "(<- operator)"
}

// indirect operations via select
type SChan chan int

func (c SChan) Send(x int) {
        select {
        case c <- x:
        }
}

func (c SChan) Nbsend(x int) bool {
        select {
        default:
                return false
        case c <- x:
                return true
        }
        panic("nbsend")
}

func (c SChan) Recv() int {
        select {
        case x := <-c:
                return x
        }
        panic("recv")
}

func (c SChan) Nbrecv() (int, bool) {
        select {
        default:
                return 0, false
        case x := <-c:
                return x, true
        }
        panic("nbrecv")
}

func (c SChan) Recv2() (int, bool) {
        select {
        case x, ok := <-c:
                return x, ok
        }
        panic("recv")
}

func (c SChan) Nbrecv2() (int, bool, bool) {
        select {
        default:
                return 0, false, false
        case x, ok := <-c:
                return x, ok, true
        }
        panic("nbrecv")
}

func (c SChan) Close() {
        close(c)
}

func (c SChan) Impl() string {
        return "(select)"
}

// indirect operations via larger selects
var dummy = make(chan bool)

type SSChan chan int

func (c SSChan) Send(x int) {
        select {
        case c <- x:
        case <-dummy:
        }
}

func (c SSChan) Nbsend(x int) bool {
        select {
        default:
                return false
        case <-dummy:
        case c <- x:
                return true
        }
        panic("nbsend")
}

func (c SSChan) Recv() int {
        select {
        case <-dummy:
        case x := <-c:
                return x
        }
        panic("recv")
}

func (c SSChan) Nbrecv() (int, bool) {
        select {
        case <-dummy:
        default:
                return 0, false
        case x := <-c:
                return x, true
        }
        panic("nbrecv")
}

func (c SSChan) Recv2() (int, bool) {
        select {
        case <-dummy:
        case x, ok := <-c:
                return x, ok
        }
        panic("recv")
}

func (c SSChan) Nbrecv2() (int, bool, bool) {
        select {
        case <-dummy:
        default:
                return 0, false, false
        case x, ok := <-c:
                return x, ok, true
        }
        panic("nbrecv")
}

func (c SSChan) Close() {
        close(c)
}

func (c SSChan) Impl() string {
        return "(select)"
}


func shouldPanic(f func()) {
        defer func() {
                if recover() == nil {
                        panic("did not panic")
                }
        }()
        f()
}

func test1(c Chan) {
        for i := 0; i < 3; i++ {
                // recv a close signal (a zero value)
                if x := c.Recv(); x != 0 {
                        println("test1: recv on closed:", x, c.Impl())
                        failed = true
                }
                if x, ok := c.Recv2(); x != 0 || ok {
                        println("test1: recv2 on closed:", x, ok, c.Impl())
                        failed = true
                }

                // should work with select: received a value without blocking, so selected == true.
                x, selected := c.Nbrecv()
                if x != 0 || !selected {
                        println("test1: recv on closed nb:", x, selected, c.Impl())
                        failed = true
                }
                x, ok, selected := c.Nbrecv2()
                if x != 0 || ok || !selected {
                        println("test1: recv2 on closed nb:", x, ok, selected, c.Impl())
                        failed = true
                }
        }

        // send should work with ,ok too: sent a value without blocking, so ok == true.
        shouldPanic(func() { c.Nbsend(1) })

        // the value should have been discarded.
        if x := c.Recv(); x != 0 {
                println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
                failed = true
        }

        // similarly Send.
        shouldPanic(func() { c.Send(2) })
        if x := c.Recv(); x != 0 {
                println("test1: recv on closed got non-zero after send on closed:", x, c.Impl())
                failed = true
        }
}

func testasync1(c Chan) {
        // should be able to get the last value via Recv
        if x := c.Recv(); x != 1 {
                println("testasync1: Recv did not get 1:", x, c.Impl())
                failed = true
        }

        test1(c)
}

func testasync2(c Chan) {
        // should be able to get the last value via Recv2
        if x, ok := c.Recv2(); x != 1 || !ok {
                println("testasync1: Recv did not get 1, true:", x, ok, c.Impl())
                failed = true
        }

        test1(c)
}

func testasync3(c Chan) {
        // should be able to get the last value via Nbrecv
        if x, selected := c.Nbrecv(); x != 1 || !selected {
                println("testasync2: Nbrecv did not get 1, true:", x, selected, c.Impl())
                failed = true
        }

        test1(c)
}

func testasync4(c Chan) {
        // should be able to get the last value via Nbrecv2
        if x, ok, selected := c.Nbrecv2(); x != 1 || !ok || !selected {
                println("testasync2: Nbrecv did not get 1, true, true:", x, ok, selected, c.Impl())
                failed = true
        }
        test1(c)
}

func closedsync() chan int {
        c := make(chan int)
        close(c)
        return c
}

func closedasync() chan int {
        c := make(chan int, 2)
        c <- 1
        close(c)
        return c
}

var mks = []func(chan int) Chan {
        func(c chan int) Chan { return XChan(c) },
        func(c chan int) Chan { return SChan(c) },
        func(c chan int) Chan { return SSChan(c) },
}

var testcloseds = []func(Chan) {
        testasync1,
        testasync2,
        testasync3,
        testasync4,
}

func main() {
        for _, mk := range mks {
                test1(mk(closedsync()))
        }
        
        for _, testclosed := range testcloseds {
                for _, mk := range mks {
                        testclosed(mk(closedasync()))
                }
        }
        
        var ch chan int 
        shouldPanic(func() {
                close(ch)
        })
        
        ch = make(chan int)
        close(ch)
        shouldPanic(func() {
                close(ch)
        })

        if failed {
                os.Exit(1)
        }
}

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.