go zerodivide 源码

  • 2022-07-15
  • 浏览 (1214)

golang zerodivide 代码

文件路径:/test/zerodivide.go

// run

// 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 that zero division causes a panic.

package main

import (
	"fmt"
	"math"
	"runtime"
	"strings"
)

type ErrorTest struct {
	name string
	fn   func()
	err  string
}

var (
	i, j, k       int   = 0, 0, 1
	i8, j8, k8    int8  = 0, 0, 1
	i16, j16, k16 int16 = 0, 0, 1
	i32, j32, k32 int32 = 0, 0, 1
	i64, j64, k64 int64 = 0, 0, 1

	bb = []int16{2, 0}

	u, v, w       uint    = 0, 0, 1
	u8, v8, w8    uint8   = 0, 0, 1
	u16, v16, w16 uint16  = 0, 0, 1
	u32, v32, w32 uint32  = 0, 0, 1
	u64, v64, w64 uint64  = 0, 0, 1
	up, vp, wp    uintptr = 0, 0, 1

	f, g, h                         float64 = 0, 0, 1
	f32, g32, h32                   float32 = 0, 0, 1
	f64, g64, h64, inf, negInf, nan float64 = 0, 0, 1, math.Inf(1), math.Inf(-1), math.NaN()

	c, d, e          complex128 = 0 + 0i, 0 + 0i, 1 + 1i
	c64, d64, e64    complex64  = 0 + 0i, 0 + 0i, 1 + 1i
	c128, d128, e128 complex128 = 0 + 0i, 0 + 0i, 1 + 1i
)

// Fool gccgo into thinking that these variables can change.
func NotCalled() {
	i++
	j++
	k++
	i8++
	j8++
	k8++
	i16++
	j16++
	k16++
	i32++
	j32++
	k32++
	i64++
	j64++
	k64++

	u++
	v++
	w++
	u8++
	v8++
	w8++
	u16++
	v16++
	w16++
	u32++
	v32++
	w32++
	u64++
	v64++
	w64++
	up++
	vp++
	wp++

	f += 1
	g += 1
	h += 1
	f32 += 1
	g32 += 1
	h32 += 1
	f64 += 1
	g64 += 1
	h64 += 1

	c += 1 + 1i
	d += 1 + 1i
	e += 1 + 1i
	c64 += 1 + 1i
	d64 += 1 + 1i
	e64 += 1 + 1i
	c128 += 1 + 1i
	d128 += 1 + 1i
	e128 += 1 + 1i
}

var tmp interface{}

// We could assign to _ but the compiler optimizes it too easily.
func use(v interface{}) {
	tmp = v
}

// Verify error/no error for all types.
var errorTests = []ErrorTest{
	// All integer divide by zero should error.
	ErrorTest{"int 0/0", func() { use(i / j) }, "divide"},
	ErrorTest{"int8 0/0", func() { use(i8 / j8) }, "divide"},
	ErrorTest{"int16 0/0", func() { use(i16 / j16) }, "divide"},
	ErrorTest{"int32 0/0", func() { use(i32 / j32) }, "divide"},
	ErrorTest{"int64 0/0", func() { use(i64 / j64) }, "divide"},

	ErrorTest{"int 1/0", func() { use(k / j) }, "divide"},
	ErrorTest{"int8 1/0", func() { use(k8 / j8) }, "divide"},
	ErrorTest{"int16 1/0", func() { use(k16 / j16) }, "divide"},
	ErrorTest{"int32 1/0", func() { use(k32 / j32) }, "divide"},
	ErrorTest{"int64 1/0", func() { use(k64 / j64) }, "divide"},

	// From issue 5790, we should ensure that _ assignments
	// still evaluate and generate zerodivide panics.
	ErrorTest{"int16 _ = bb[0]/bb[1]", func() { _ = bb[0] / bb[1] }, "divide"},

	ErrorTest{"uint 0/0", func() { use(u / v) }, "divide"},
	ErrorTest{"uint8 0/0", func() { use(u8 / v8) }, "divide"},
	ErrorTest{"uint16 0/0", func() { use(u16 / v16) }, "divide"},
	ErrorTest{"uint32 0/0", func() { use(u32 / v32) }, "divide"},
	ErrorTest{"uint64 0/0", func() { use(u64 / v64) }, "divide"},
	ErrorTest{"uintptr 0/0", func() { use(up / vp) }, "divide"},

	ErrorTest{"uint 1/0", func() { use(w / v) }, "divide"},
	ErrorTest{"uint8 1/0", func() { use(w8 / v8) }, "divide"},
	ErrorTest{"uint16 1/0", func() { use(w16 / v16) }, "divide"},
	ErrorTest{"uint32 1/0", func() { use(w32 / v32) }, "divide"},
	ErrorTest{"uint64 1/0", func() { use(w64 / v64) }, "divide"},
	ErrorTest{"uintptr 1/0", func() { use(wp / vp) }, "divide"},

	// All float64ing divide by zero should not error.
	ErrorTest{"float64 0/0", func() { use(f / g) }, ""},
	ErrorTest{"float32 0/0", func() { use(f32 / g32) }, ""},
	ErrorTest{"float64 0/0", func() { use(f64 / g64) }, ""},

	ErrorTest{"float64 1/0", func() { use(h / g) }, ""},
	ErrorTest{"float32 1/0", func() { use(h32 / g32) }, ""},
	ErrorTest{"float64 1/0", func() { use(h64 / g64) }, ""},
	ErrorTest{"float64 inf/0", func() { use(inf / g64) }, ""},
	ErrorTest{"float64 -inf/0", func() { use(negInf / g64) }, ""},
	ErrorTest{"float64 nan/0", func() { use(nan / g64) }, ""},

	// All complex divide by zero should not error.
	ErrorTest{"complex 0/0", func() { use(c / d) }, ""},
	ErrorTest{"complex64 0/0", func() { use(c64 / d64) }, ""},
	ErrorTest{"complex128 0/0", func() { use(c128 / d128) }, ""},

	ErrorTest{"complex 1/0", func() { use(e / d) }, ""},
	ErrorTest{"complex64 1/0", func() { use(e64 / d64) }, ""},
	ErrorTest{"complex128 1/0", func() { use(e128 / d128) }, ""},
}

func error_(fn func()) (error string) {
	defer func() {
		if e := recover(); e != nil {
			error = e.(runtime.Error).Error()
		}
	}()
	fn()
	return ""
}

type FloatTest struct {
	f, g float64
	out  float64
}

var float64Tests = []FloatTest{
	FloatTest{0, 0, nan},
	FloatTest{nan, 0, nan},
	FloatTest{inf, 0, inf},
	FloatTest{negInf, 0, negInf},
}

func alike(a, b float64) bool {
	switch {
	case math.IsNaN(a) && math.IsNaN(b):
		return true
	case a == b:
		return math.Signbit(a) == math.Signbit(b)
	}
	return false
}

func main() {
	bad := false
	for _, t := range errorTests {
		err := error_(t.fn)
		switch {
		case t.err == "" && err == "":
			// fine
		case t.err != "" && err == "":
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%s: expected %q; got no error\n", t.name, t.err)
		case t.err == "" && err != "":
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%s: expected no error; got %q\n", t.name, err)
		case t.err != "" && err != "":
			if !strings.Contains(err, t.err) {
				if !bad {
					bad = true
					fmt.Printf("BUG\n")
				}
				fmt.Printf("%s: expected %q; got %q\n", t.name, t.err, err)
				continue
			}
		}
	}

	// At this point we know we don't error on the values we're testing
	for _, t := range float64Tests {
		x := t.f / t.g
		if !alike(x, t.out) {
			if !bad {
				bad = true
				fmt.Printf("BUG\n")
			}
			fmt.Printf("%v/%v: expected %g error; got %g\n", t.f, t.g, t.out, x)
		}
	}
	if bad {
		panic("zerodivide")
	}
}

相关信息

go 源码目录

相关文章

go 235 源码

go 64bit 源码

go alg 源码

go alias 源码

go alias1 源码

go alias2 源码

go alias3 源码

go align 源码

go append 源码

go append1 源码

0  赞