Beispiel #1
0
// GetBodyNode returns an BODY node nested within an HTML node.
func getBodyNode() *html.Node {
	ns, err := html.ParseFragment(strings.NewReader("<html><body></body></html>"), nil)
	if err != nil {
		panic("error generating context")
	}
	if len(ns) == 0 {
		panic("no nodes generating context")
	}
	h := ns[0]
	if h.Type != html.ElementNode || h.DataAtom != atom.Html {
		panic("expected an HTML node, got " + pretty.String(h))
	}
	b := h.LastChild
	if b.Type != html.ElementNode || b.DataAtom != atom.Body {
		panic("expected a BODY node, got " + pretty.String(b))
	}
	return b
}
Beispiel #2
0
func TestTypeUnderlying(t *testing.T) {
	tests := []struct {
		t Type
		u Type
	}{
		{t: intType, u: intType},
		{t: byteType, u: byteType},
		{t: t0, u: intType},
		{t: t1, u: intType},
		{t: &Star{Target: t0}, u: &Star{Target: t0}},
		{
			t: &SliceType{Element: intType},
			u: &SliceType{Element: intType},
		},
		{
			t: &ArrayType{Size: intLit("5"), Element: intType},
			u: &ArrayType{Size: intLit("5"), Element: intType},
		},
		{
			t: &MapType{Key: t0, Value: intType},
			u: &MapType{Key: t0, Value: intType},
		},
		{
			t: &ChannelType{Send: true, Element: intType},
			u: &ChannelType{Send: true, Element: intType},
		},
		{t: &FunctionType{}, u: &FunctionType{}},
		{t: &InterfaceType{}, u: &InterfaceType{}},
		{t: &StructType{}, u: &StructType{}},
	}
	for _, test := range tests {
		u := test.t.Underlying()
		if eq.Deep(u, test.u) {
			continue
		}
		t.Errorf("(%s).Underlying()=%s, want %s", pretty.String(test.t), pretty.String(u), pretty.String(test.u))
	}
}
Beispiel #3
0
func TestTypeIdentical(t *testing.T) {
	// We don't care about the contents of these, just that &pkgA != &pkgB.
	var pkgA, pkgB packageDecl

	tests := []struct {
		u, v  Type
		ident bool
	}{
		{intType, intType, true},
		{byteType, byteType, true},
		{byteType, uint8Type, true},
		{runeType, int32Type, true},
		{runeType, intType, false},
		{intType, t0, false},
		{t0, t0, true},
		{t0, t1, false},
		{t1, t1Ident, true},
		{t1, t1Diff, false},
		{t0, &Star{Target: t0}, false},

		{&Star{Target: intType}, &Star{Target: intType}, true},
		{&Star{Target: int32Type}, &Star{Target: runeType}, true},
		{&Star{Target: int32Type}, &Star{Target: intType}, false},
		{
			&Star{Target: &Star{Target: intType}},
			&Star{Target: &Star{Target: intType}},
			true,
		},
		{
			&Star{Target: &Star{Target: intType}},
			&Star{Target: intType},
			false,
		},
		{
			&SliceType{Element: intType},
			&SliceType{Element: intType},
			true,
		},
		{
			&SliceType{Element: int32Type},
			&SliceType{Element: runeType},
			true,
		},
		{
			&SliceType{Element: int32Type},
			&SliceType{Element: intType},
			false,
		},
		{
			&SliceType{Element: &SliceType{Element: intType}},
			&SliceType{Element: &SliceType{Element: intType}},
			true,
		},
		{
			&SliceType{Element: &SliceType{Element: intType}},
			&SliceType{Element: intType},
			false,
		},
		{&SliceType{Element: int32Type}, t0, false},
		{
			&ArrayType{Size: intLit("1"), Element: intType},
			&ArrayType{Size: intLit("1"), Element: intType},
			true,
		},
		{
			&ArrayType{Size: intLit("1"), Element: intType},
			&ArrayType{Size: intLit("2"), Element: intType},
			false,
		},
		{
			&ArrayType{Size: intLit("1"), Element: intType},
			&ArrayType{Size: intLit("1"), Element: t0},
			false,
		},
		{
			&ArrayType{
				Size: intLit("1"),
				Element: &ArrayType{
					Size:    intLit("1"),
					Element: t0,
				},
			},
			&ArrayType{
				Size: intLit("1"),
				Element: &ArrayType{
					Size:    intLit("1"),
					Element: t0,
				},
			},
			true,
		},
		{
			&ArrayType{
				Size: intLit("2"),
				Element: &ArrayType{
					Size:    intLit("1"),
					Element: t0,
				},
			},
			&ArrayType{
				Size: intLit("1"),
				Element: &ArrayType{
					Size:    intLit("2"),
					Element: t0,
				},
			},
			false,
		},
		{
			&ArrayType{Size: intLit("1"), Element: intType},
			&SliceType{Element: intType},
			false,
		},
		{
			&MapType{Key: intType, Value: t1},
			&MapType{Key: intType, Value: t1Ident},
			true,
		},
		{
			&MapType{Key: intType, Value: t1},
			&MapType{Key: intType, Value: t1Diff},
			false,
		},
		{
			&MapType{Key: t0, Value: t1},
			&MapType{Key: intType, Value: t1},
			false,
		},
		{
			&ChannelType{Element: intType},
			&ChannelType{Element: intType},
			true,
		},
		{
			&ChannelType{Receive: true, Element: intType},
			&ChannelType{Receive: true, Element: intType},
			true,
		},
		{
			&ChannelType{Receive: true, Send: true, Element: intType},
			&ChannelType{Receive: true, Send: true, Element: intType},
			true,
		},
		{
			&ChannelType{Element: intType},
			&ChannelType{Send: true, Element: intType},
			false,
		},
		{
			&ChannelType{Receive: true, Element: intType},
			&ChannelType{Element: intType},
			false,
		},
		{
			&ChannelType{Element: t1},
			&ChannelType{Element: t1Diff},
			false,
		},
		{
			&ChannelType{Element: &ChannelType{Element: runeType}},
			&ChannelType{Element: &ChannelType{Element: int32Type}},
			true,
		},
		{
			&ChannelType{Receive: true, Element: &ChannelType{Element: t0}},
			&ChannelType{Element: &ChannelType{Receive: true, Element: t0}},
			false,
		},
		{&ChannelType{Element: t1}, t0, false},
		{&FunctionType{}, &FunctionType{}, true},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{
					{Type: intType, Identifier: id("a")},
				},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{
					{Type: intType, Identifier: id("a")},
				},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{
					{Type: intType, Identifier: id("a")},
				},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{
					{Type: intType, Identifier: id("notA")},
				},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t1}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t1Ident}},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t1}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t1Diff}},
			}},
			false,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}},
			}},
			&FunctionType{Signature: Signature{
				Results: []ParameterDecl{{Type: t0}},
			}},
			false,
		},
		{
			&FunctionType{Signature: Signature{
				Results: []ParameterDecl{{Type: t0}},
			}},
			&FunctionType{Signature: Signature{
				Results: []ParameterDecl{{Type: t0}},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t1}, {Type: t0}},
			}},
			false,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1, DotDotDot: true}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
			}},
			false,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1, DotDotDot: true}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1, DotDotDot: true}},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
				Results:    []ParameterDecl{{Type: intType}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
				Results:    []ParameterDecl{{Type: intType}},
			}},
			true,
		},
		{
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: intType}},
				Results:    []ParameterDecl{{Type: t0}, {Type: t1}},
			}},
			&FunctionType{Signature: Signature{
				Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
				Results:    []ParameterDecl{{Type: intType}},
			}},
			false,
		},
		{
			&FunctionType{Signature: Signature{
				Results: []ParameterDecl{{Type: t0}, {Type: t1}},
			}},
			&FunctionType{Signature: Signature{
				Results: []ParameterDecl{{Type: t1}, {Type: t0}},
			}},
			false,
		},
		{&FunctionType{}, t0, false},

		// The Methods field is not used when checking for interface identity, but
		// the unexported methodSet field won't print on test errors, so we kindly
		// populate both.
		{&InterfaceType{}, &InterfaceType{}, true},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgA},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgA},
				},
			},
			true,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgA},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgB},
				},
			},
			false,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("A")},
				},
				methodSet: []*Method{
					{Identifier: *id("A"), pkg: &pkgA},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("A")},
				},
				methodSet: []*Method{
					{Identifier: *id("A"), pkg: &pkgB},
				},
			},
			true,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgA},
				},
			},
			&InterfaceType{},
			false,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgA},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("b")},
				},
				methodSet: []*Method{
					{Identifier: *id("b"), pkg: &pkgA},
				},
			},
			false,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{
						Identifier: *id("a"),
						Signature: Signature{
							Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
							Results:    []ParameterDecl{{Type: intType}},
						},
					},
				},
				methodSet: []*Method{
					{
						Identifier: *id("a"),
						Signature: Signature{
							Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
							Results:    []ParameterDecl{{Type: intType}},
						},
						pkg: &pkgA,
					},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{
						Identifier: *id("a"),
						Signature: Signature{
							Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
							Results:    []ParameterDecl{{Type: intType}},
						},
					},
				},
				methodSet: []*Method{
					{
						Identifier: *id("a"),
						Signature: Signature{
							Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
							Results:    []ParameterDecl{{Type: intType}},
						},
						pkg: &pkgA,
					},
				},
			},
			true,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{
						Identifier: *id("a"),
						Signature: Signature{
							Results: []ParameterDecl{{Type: intType}},
						},
					},
				},
				methodSet: []*Method{
					{
						Identifier: *id("a"),
						Signature: Signature{
							Results: []ParameterDecl{{Type: intType}},
						},
						pkg: &pkgA,
					},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{
						Identifier: *id("a"),
						Signature: Signature{
							Results: []ParameterDecl{{Type: t0}},
						},
					},
				},
				methodSet: []*Method{
					{
						Identifier: *id("a"),
						Signature: Signature{
							Results: []ParameterDecl{{Type: t0}},
						},
						pkg: &pkgA,
					},
				},
			},
			false,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("a")},
				},
				methodSet: []*Method{
					{Identifier: *id("a"), pkg: &pkgA},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{
						Identifier: *id("a"),
						Signature: Signature{
							Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
							Results:    []ParameterDecl{{Type: intType}},
						},
					},
				},
				methodSet: []*Method{
					{
						Identifier: *id("a"),
						Signature: Signature{
							Parameters: []ParameterDecl{{Type: t0}, {Type: t1}},
							Results:    []ParameterDecl{{Type: intType}},
						},
						pkg: &pkgA,
					},
				},
			},
			false,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("A")},
					&Method{Identifier: *id("B")},
				},
				methodSet: []*Method{
					{Identifier: *id("A")},
					{Identifier: *id("B")},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("A")},
					&Method{Identifier: *id("B")},
				},
				methodSet: []*Method{
					{Identifier: *id("A")},
					{Identifier: *id("B")},
				},
			},
			true,
		},
		{
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("A")},
					&Method{Identifier: *id("B")},
				},
				methodSet: []*Method{
					{Identifier: *id("A")},
					{Identifier: *id("B")},
				},
			},
			&InterfaceType{
				Methods: []Node{
					&Method{Identifier: *id("A")},
					&Method{Identifier: *id("C")},
				},
				methodSet: []*Method{
					{Identifier: *id("A")},
					{Identifier: *id("C")},
				},
			},
			false,
		},
		{&InterfaceType{}, t0, false},
		{&StructType{}, &StructType{}, true},
		{
			&StructType{Fields: []FieldDecl{{Type: intType}}},
			&StructType{Fields: []FieldDecl{{Type: intType}}},
			true,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("a"), Type: intType},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("a"), Type: intType},
			}},
			true,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
				{Identifier: id("y"), Type: &SliceType{Element: t0}},
				{Identifier: id("z"), Type: t1},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
				{Identifier: id("y"), Type: &SliceType{Element: t0}},
				{Identifier: id("z"), Type: t1},
			}},
			true,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
				{Identifier: id("y"), Type: &SliceType{Element: t0}},
				{Identifier: id("z"), Type: t1},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
				{Identifier: id("z"), Type: t1},
			}},
			false,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
				{Identifier: id("y"), Type: &SliceType{Element: t0}},
				{Identifier: id("z"), Type: t1},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
				{Identifier: id("z"), Type: t1},
			}},
			false,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t1},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: intType},
			}},
			false,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t1, Tag: strLit("tag")},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t1, Tag: strLit("tag")},
			}},
			true,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t1, Tag: strLit("tag")},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t1, Tag: strLit("different tag")},
			}},
			false,
		},
		{
			&StructType{Fields: []FieldDecl{{Identifier: id("x")}}},
			&StructType{Fields: []FieldDecl{{Identifier: id("y")}}},
			false,
		},
		{
			&StructType{Fields: []FieldDecl{{Identifier: id("x"), Type: t0}}},
			&StructType{Fields: []FieldDecl{{Type: t0}}},
			false,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t0, pkg: &pkgA},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), Type: t0, pkg: &pkgA},
			}},
			true,
		},
		{
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), pkg: &pkgA},
			}},
			&StructType{Fields: []FieldDecl{
				{Identifier: id("x"), pkg: &pkgB},
			}},
			false,
		},
		{&StructType{}, t0, false},
	}
	for _, test := range tests {
		ident := test.u.Identical(test.v)
		if ident != test.ident {
			t.Errorf("(%s).Identical(%s)=%t, want %t", pretty.String(test.u), pretty.String(test.v), ident, test.ident)
		}
		identReflect := test.v.Identical(test.u)
		if ident == identReflect {
			continue
		}
		u := pretty.String(test.u)
		v := pretty.String(test.v)
		t.Errorf("(%s).Identical(%s)=%t, but (%s).Identical(%s)=%t", u, v, ident, v, u, identReflect)
	}
}
Beispiel #4
0
func TestIsRepresentable(t *testing.T) {
	zero, neg1 := intLit("0"), intLit("-1")
	hello := strLit("Hello, World!")
	tests := []struct {
		x  Expression
		t  Type
		ok bool
	}{
		{&BoolLiteral{}, boolType, true},
		{zero, boolType, false},

		{imgLit("5i"), complex64Type, true},
		{floatLit("5"), complex64Type, true},
		{intLit("5"), complex64Type, true},
		{hello, complex64Type, false},
		{imgLit("5i"), complex128Type, true},
		{floatLit("5"), complex128Type, true},
		{intLit("5"), complex128Type, true},
		{runeLit('a'), complex128Type, true},
		{hello, complex128Type, false},

		{floatLit("5"), float32Type, true},
		{intLit("5"), float32Type, true},
		{runeLit('a'), float32Type, true},
		{hello, float32Type, false},
		{floatLit("5"), float64Type, true},
		{intLit("5"), float64Type, true},
		{hello, float64Type, false},

		{hello, stringType, true},
		{zero, stringType, false},

		{intLit(strconv.Itoa(minInt)), intType, true},
		{intLit(strconv.Itoa(maxInt)), intType, true},
		{intLit(strconv.Itoa(math.MinInt8 - 1)), int8Type, false},
		{intLit(strconv.Itoa(math.MinInt8)), int8Type, true},
		{intLit(strconv.Itoa(math.MinInt8)), int8Type, true},
		{intLit(strconv.Itoa(math.MaxInt8 + 1)), int8Type, false},
		{intLit(strconv.Itoa(math.MinInt16 - 1)), int16Type, false},
		{intLit(strconv.Itoa(math.MinInt16)), int16Type, true},
		{intLit(strconv.Itoa(math.MaxInt16)), int16Type, true},
		{intLit(strconv.Itoa(math.MaxInt16 + 1)), int16Type, false},
		{intLit(strconv.Itoa(math.MinInt32 - 1)), int32Type, false},
		{intLit(strconv.Itoa(math.MinInt32)), int32Type, true},
		{intLit(strconv.Itoa(math.MaxInt32)), int32Type, true},
		{intLit(strconv.Itoa(math.MaxInt32 + 1)), int32Type, false},
		{intLit("-9223372036854775809"), int32Type, false},
		{intLit(strconv.Itoa(math.MinInt64)), int64Type, true},
		{intLit(strconv.Itoa(math.MaxInt64)), int64Type, true},
		{intLit("9223372036854775808"), int32Type, false},
		{neg1, uintType, false},
		{zero, uintType, true},
		{intLit(strconv.FormatUint(maxUint, 10)), uintType, true},
		{neg1, byteType, false},
		{zero, byteType, true},
		{intLit(strconv.Itoa(math.MaxUint8)), byteType, true},
		{intLit(strconv.Itoa(math.MaxUint8 + 1)), byteType, false},
		{neg1, uint8Type, false},
		{zero, uint8Type, true},
		{intLit(strconv.Itoa(math.MaxUint8)), uint8Type, true},
		{intLit(strconv.Itoa(math.MaxUint8 + 1)), uint8Type, false},
		{neg1, uint16Type, false},
		{zero, uint16Type, true},
		{intLit(strconv.Itoa(math.MaxUint16)), uint16Type, true},
		{intLit(strconv.Itoa(math.MaxUint16 + 1)), uint16Type, false},
		{neg1, uint32Type, false},
		{zero, uint32Type, true},
		{intLit(strconv.Itoa(math.MaxUint32)), uint32Type, true},
		{intLit(strconv.Itoa(math.MaxUint32 + 1)), uint32Type, false},
		{neg1, uint64Type, false},
		{zero, uint64Type, true},
		{intLit(strconv.FormatUint(math.MaxUint64, 10)), uint64Type, true},
		{intLit("18446744073709551616"), uint64Type, false},
		{&BoolLiteral{}, intType, false},
		{floatLit("5.0"), intType, true},
		{
			&ComplexLiteral{
				Real:      big.NewRat(5, 1),
				Imaginary: big.NewRat(0, 1),
			},
			intType,
			true,
		},

		{&BoolLiteral{}, &SliceType{Element: intType}, false},

		// Untyped types.
		{intLit("5"), Untyped(IntegerConst), true},
		{runeLit('α'), Untyped(IntegerConst), true},
		{floatLit("5.0"), Untyped(IntegerConst), true},
		{floatLit("5.1"), Untyped(IntegerConst), false},
		{
			&ComplexLiteral{
				Real:      big.NewRat(5, 1),
				Imaginary: big.NewRat(0, 1),
			},
			Untyped(IntegerConst),
			true,
		},

		{intLit("0"), Untyped(FloatConst), true},
		{runeLit('a'), Untyped(FloatConst), true},
		{floatLit("5.1"), Untyped(FloatConst), true},
		{imgLit("5.1"), Untyped(FloatConst), false},

		{intLit("0"), Untyped(ComplexConst), true},
		{runeLit('a'), Untyped(ComplexConst), true},
		{floatLit("5.1"), Untyped(ComplexConst), true},
		{imgLit("5.1"), Untyped(ComplexConst), true},
		{hello, Untyped(ComplexConst), false},

		{hello, Untyped(StringConst), true},
		{intLit("5"), Untyped(StringConst), false},

		{&BoolLiteral{}, Untyped(BoolConst), true},
		{&BoolLiteral{Value: true}, Untyped(BoolConst), true},
		{hello, Untyped(BoolConst), false},
	}
	for _, test := range tests {
		if ok := IsRepresentable(test.x, test.t); ok != test.ok {
			t.Errorf("IsRepresentable(%s, %s)=%t, want %t", pretty.String(test.x), pretty.String(test.t), ok, test.ok)
		}
	}
}
Beispiel #5
0
func TestCheckTypes(t *testing.T) {
	// The source must contain an identifier α.
	// The test calls Check and compares the type of α to the given Type.
	tests := []struct {
		src string
		t   Type
	}{
		// Literals
		{`package a; const α = 1`, Untyped(IntegerConst)},
		{`package a; const α = 1.0`, Untyped(FloatConst)},
		{`package a; const α = 1.0i`, Untyped(ComplexConst)},
		{`package a; const α = 'a'`, Untyped(RuneConst)},
		{`package a; const α = "Hello, World!"`, Untyped(StringConst)},

		// Identifiers
		{`package a; const α = true`, Untyped(BoolConst)},
		{`package a; const α = false`, Untyped(BoolConst)},
		{`package a; const α = iota`, Untyped(IntegerConst)},
		{`package a; const ( a = iota; α )`, Untyped(IntegerConst)},
		{`package a; const α int = 1`, intType},
		{`package a; const α float64 = 'a'`, float64Type},
		{`package a; const a, b, c, α int = 1, 2, 3, 4`, intType},
		{`package a; const ( a int = iota; α )`, intType},

		// UnaryOps
		{`package a; const α = -1`, Untyped(IntegerConst)},
		{`package a; const α = -1.0`, Untyped(FloatConst)},
		{`package a; const α = -1.0i`, Untyped(ComplexConst)},
		{`package a; const α = -'a'`, Untyped(RuneConst)},
		{`package a; const α = !true`, Untyped(BoolConst)},
		{`package a; const α = -iota`, Untyped(IntegerConst)},
		{`package a; const α = ^1`, Untyped(IntegerConst)},
		{`package a; const α = +1.189`, Untyped(FloatConst)},
		{`package a; const α int = -1`, intType},
		{`package a; const α int = +1.0`, intType},
		{`package a; const α int = ^1`, intType},
		{`package a; const α int = ^1`, intType},
	}
	for _, test := range tests {
		l := token.NewLexer("", test.src)
		p := NewParser(l)
		f := parseFile(p)
		if err := Check([]*File{f}); err != nil {
			t.Errorf("Check(%v), unexpected error: %v", test.src, err)
			continue
		}
		d := f.syms.Find("α")
		if d == nil {
			t.Errorf("Check(%v): failed to find symbol α", test.src)
			continue
		}
		var typ Type
		switch d := d.(type) {
		case *constSpecView:
			typ = d.Type
		case *varSpecView:
			typ = d.Type
		default:
			panic("declaration type not supported")
		}
		if !eq.Deep(typ, test.t) {
			t.Errorf("Check(%v)=%v: α's type is %v, want %v", test.src,
				pretty.String(f), pretty.String(typ), pretty.String(test.t))
		}
	}
}
Beispiel #6
0
func TestIsAssignable(t *testing.T) {
	anInt32 := intLit("42")
	anInt32.typ = int32Type
	aUint8 := intLit("42")
	aUint8.typ = uint8Type
	t0Ident := id("t0")
	t0Ident.decl = &VarSpec{Type: t0}
	nilLit := &NilLiteral{typ: Untyped(NilConst)}

	namedT0Slice0 := typ("T0Slice")
	namedT0Slice0.Identifier.decl = &TypeSpec{
		Identifier: *id("T0Slice"),
		Type:       &SliceType{Element: t0},
	}
	// Just like namedT0Slice0, but via a different declaration.
	namedT0Slice1 := typ("T0Slice")
	namedT0Slice1.Identifier.decl = &TypeSpec{
		Identifier: *id("T0Slice"),
		Type:       &SliceType{Element: t0},
	}
	t0SliceIdent := id("t0slice")
	t0SliceIdent.decl = &VarSpec{Type: namedT0Slice0}

	bidirIntChan := id("ch")
	bidirIntChan.decl = &VarSpec{Type: &ChannelType{Send: true, Receive: true, Element: intType}}
	sendIntChan := id("ch")
	sendIntChan.decl = &VarSpec{Type: &ChannelType{Send: true, Element: intType}}
	recvIntChan := id("ch")
	recvIntChan.decl = &VarSpec{Type: &ChannelType{Receive: true, Element: intType}}

	tests := []struct {
		x  Expression
		t  Type
		ok bool
	}{
		{intLit("42"), intType, true},
		{intLit("42"), int8Type, true},
		{intLit("42"), int16Type, true},
		{intLit("42"), int32Type, true},
		{intLit("42"), int64Type, true},
		{intLit("42"), uintType, true},
		{intLit("42"), uint8Type, true},
		{intLit("42"), uint16Type, true},
		{intLit("42"), uint32Type, true},
		{intLit("42"), uint64Type, true},
		{intLit("42"), float32Type, true},
		{intLit("42"), float64Type, true},
		{intLit("42"), complex64Type, true},
		{intLit("42"), complex128Type, true},
		{strLit("Hello, World!"), intType, false},
		{anInt32, int32Type, true},
		{anInt32, runeType, true},
		{anInt32, intType, false},
		{aUint8, uint8Type, true},
		{aUint8, byteType, true},
		{aUint8, intType, false},
		{strLit("Hello, World!"), stringType, true},
		{intLit("42"), stringType, false},
		{t0Ident, t0, true},
		{t0Ident, intType, false},
		{t0Ident, &SliceType{Element: t0}, false},
		{t0SliceIdent, &SliceType{Element: t0}, true},
		{t0SliceIdent, namedT0Slice0, true},
		{t0SliceIdent, namedT0Slice1, false},
		{nilLit, intType, false},
		{nilLit, &StructType{}, false},
		{nilLit, &Star{Target: t0}, true},
		{nilLit, &SliceType{Element: t0}, true},
		{nilLit, &MapType{Key: t0, Value: intType}, true},
		{nilLit, &ChannelType{Element: t0}, true},
		{nilLit, &InterfaceType{}, true},
		{bidirIntChan, &ChannelType{Send: true, Element: intType}, true},
		{bidirIntChan, &ChannelType{Receive: true, Element: intType}, true},
		{bidirIntChan, &ChannelType{Send: true, Receive: true, Element: intType}, true},
		{bidirIntChan, &ChannelType{Send: true, Element: t0}, false},
		{sendIntChan, &ChannelType{Send: true, Element: intType}, true},
		{sendIntChan, &ChannelType{Receive: true, Element: intType}, false},
		{sendIntChan, &ChannelType{Send: true, Receive: true, Element: intType}, false},
		{sendIntChan, &ChannelType{Send: true, Element: t0}, false},
		{recvIntChan, &ChannelType{Send: true, Element: intType}, false},
		{recvIntChan, &ChannelType{Receive: true, Element: intType}, true},
		{recvIntChan, &ChannelType{Send: true, Receive: true, Element: intType}, false},
		{recvIntChan, &ChannelType{Receive: true, Element: t0}, false},
	}
	for _, test := range tests {
		if ok := IsAssignable(test.x, test.t); ok != test.ok {
			t.Errorf("IsAssignable(%s, %s)=%t, want %t", pretty.String(test.x), pretty.String(test.t), ok, test.ok)
		}
	}
}
Beispiel #7
0
func TestConstFolding(t *testing.T) {
	runeNeg97 := intLit("-97")
	runeNeg97.Rune = true

	// The source must contain a const α. The test calls Check on the source and
	// compares the resulting value of α to the given Expression.
	tests := []struct {
		src string
		v   Expression
	}{
		{`package a; const α = 1`, intLit("1")},
		{`package a; const α = 1.0`, floatLit("1.0")},
		{`package a; const α = 1.0i`, imgLit("1.0")},
		{`package a; const α = 'a'`, runeLit('a')},
		{`package a; const α = "Hello, World!"`, strLit("Hello, World!")},
		{`package a; const α = true`, &BoolLiteral{Value: true}},
		{`package a; const α = false`, &BoolLiteral{Value: false}},
		{`package a; const α, b = b, 5`, intLit("5")},
		{`package a; const α = iota`, intLit("0")},
		{`package a; const ( zero = iota; α )`, intLit("1")},
		{`package a; const ( zero = iota; one; α )`, intLit("2")},
		{`package a; const α = +1`, intLit("1")},
		{`package a; const α = -1`, intLit("-1")},
		{`package a; const α = - -1`, intLit("1")},
		{`package a; const α = +'a'`, runeLit('a')},
		{`package a; const α = -'a'`, runeNeg97},
		{`package a; const α = +1.0`, floatLit("1.0")},
		{`package a; const α = - - -1.0`, floatLit("-1.0")},
		{`package a; const α = +1.0i`, imgLit("1.0")},
		{`package a; const α = - - -1.0i`, imgLit("-1.0")},
		{`package a; const α = ^0`, intLit("-1")},
		{`package a; const α = ^1`, intLit("-2")},
		{`package a; const α float64 = ^256`, intLit("-257")},
		{`package a; const α = !true`, &BoolLiteral{Value: false}},
		{`package a; const α = !!true`, &BoolLiteral{Value: true}},
		{`package a; const α = !false`, &BoolLiteral{Value: true}},
		{`package a; const α = !!false`, &BoolLiteral{Value: false}},
		{`package a; const f, α = false, !f`, &BoolLiteral{Value: true}},
	}
	for _, test := range tests {
		l := token.NewLexer("", test.src)
		p := NewParser(l)
		f := parseFile(p)
		if err := Check([]*File{f}); err != nil {
			t.Errorf("Check(%v), unexpected error: %v", test.src, err)
			continue
		}
		d := f.syms.Find("α")
		if d == nil {
			t.Errorf("Check(%v): failed to find symbol α", test.src)
			continue
		}
		a, ok := d.(*constSpecView)
		if !ok {
			t.Errorf("Check(%v): α is not a const", test.src)
			continue
		}
		if !eq.Deep(a.Value, test.v) {
			t.Errorf("Check(%v)=%v: α folded to %v, want %v", test.src,
				pretty.String(f), pretty.String(a.Value), pretty.String(test.v))
		}
	}
}
Beispiel #8
0
func TestPkgDecls(t *testing.T) {
	tests := []struct {
		src []string
		// The top-level identifiers.
		ids []string
		// An expected error, if non-empty.
		err string
	}{
		{
			src: []string{
				`package a; const a = 1`,
				`package a; const B = 1`,
			},
			ids: []string{"a", "B"},
		},
		{
			src: []string{`package a; const a, B = B, 1`},
			ids: []string{"a", "B"},
		},
		{
			src: []string{
				`package a
			const (
				a, B = B, 1
				c, d
			)`,
			},
			ids: []string{"a", "B", "c", "d"},
		},
		{
			src: []string{
				`package a; var a = 1`,
				`package a; var B = 1`,
			},
			ids: []string{"a", "B"},
		},
		{
			src: []string{`package a; var a, B = 1, 2`},
			ids: []string{"a", "B"},
		},
		{
			src: []string{
				`package a
			var (
				a, B = 0, 1
				c, d = 3.0, 4.0
			)`,
			},
			ids: []string{"a", "B", "c", "d"},
		},
		{
			src: []string{
				`package a
			type (
				a struct{}
				B struct { C }
			)`,
			},
			ids: []string{"a", "B"},
		},
		{
			src: []string{
				`package a
			func a(){}
			func B() int { return 0 }`,
			},
			ids: []string{"a", "B"},
		},
		{
			src: []string{
				`package a
			func a(){}
			func B() int { return 0 }`,
				`package a
			func c(e int){}
			func d() (f int) { return 0 }`,
			},
			ids: []string{"a", "B", "c", "d"},
		},
		{
			src: []string{
				`package a
			func (z int) a(){}
			func (z float64) B() int { return 0 }`,
			},
			ids: []string{"a", "B"},
		},
		{
			src: []string{
				`package a
			func (z T0) a(){}
			func (z T1) B() int { return 0 }`,
				`package a
			func (z T2) c(e int){}
			func (z T3) d() (f int) { return 0 }`,
			},
			ids: []string{"a", "B", "c", "d"},
		},

		// Redeclaration errors.
		{
			src: []string{`package a; const a = 1; const a = 2`},
			err: "a redeclared",
		},
		{
			src: []string{`package a; const a = 1; var a = 2`},
			err: "a redeclared",
		},
		{
			src: []string{`package a; const a = 1; func a(){}`},
			err: "a redeclared",
		},
		{
			src: []string{
				`package a; const a = 1`,
				`package a; const a = 2`,
			},
			err: "a redeclared",
		},
		{
			src: []string{`
				package a
				import (
					"fmt"
					"fmt"
				)
			`},
			err: "fmt redeclared",
		},
		{
			src: []string{`
				package a
				import (
					"fmt"
					"foo/bar/fmt"
				)
			`},
			err: "fmt redeclared",
		},
		{
			src: []string{`
				package a
				import fmt "foo"
				import "fmt"
			`},
			err: "fmt redeclared",
		},
		{
			src: []string{`
				package a
				import (
					"fmt"
					fmt "foo/bar"
				)
			`},
			err: "fmt redeclared",
		},
		{
			// Not an error to redeclare the same import in different files.
			src: []string{
				`package a; import "fmt"`,
				`package a; import "fmt"`,
			},
		},

		// The blank identifier is not redeclared.
		{
			src: []string{`package a; const _ = 1; const _ = 2`},
		},
	}

	for _, test := range tests {
		files := parseSrcFiles(t, test.src)
		if files == nil {
			continue
		}
		var ids []string
		seen := make(map[Declaration]bool)
		s, err := pkgDecls(files)
		if test.err != "" {
			if err == nil {
				t.Errorf("pkgDecls(%v), err=nil, want matching %s", test.src, test.err)
			} else if !regexp.MustCompile(test.err).MatchString(err.Error()) {
				t.Errorf("pkgDecls(%v), err=[%v], want matching [%s]", test.src, err, test.err)
			}
			continue
		}
		if err != nil {
			t.Errorf("pkgDecls(%v), unexpected err=[%v]", test.src, err)
			continue
		}
		for id, d := range s.Decls {
			ids = append(ids, id)
			if seen[d] {
				t.Errorf("pkgDecls(%v), multiple idents map to declaration %s", test.src, pretty.String(d))
			}
			seen[d] = true
		}
		sort.Strings(ids)
		sort.Strings(test.ids)
		if reflect.DeepEqual(ids, test.ids) {
			continue
		}
		t.Errorf("pkgDecls(%v)=%v, want %v", test.src, ids, test.ids)
	}
}
Beispiel #9
0
// BUG(eaburns): Test NilLiteral, BoolLiteral, and ComplexLiteral.
func TestExpressionSource(t *testing.T) {
	tests := []struct{ expr, want string }{
		{`"Hello, World!"`, `"Hello, World!"`},
		{`"αβξ"`, `"αβξ"`},
		{"\x60\\n\x0a\\n\x60", `"\\n\n\\n"`},
		{`'a'`, `'a'`},
		{`'☺'`, `'☺'`},
		{`0`, `0`},
		{`5`, `5`},
		{`0.0`, `0.0`},
		{`5.0`, `5.0`},
		{`3.1415926535`, `3.1415926535`},
		{`1e4`, `10000.0`},
		{`1e-4`, `0.0001`},
		// BUG(eaburns): ComplexLiteral tests don't test ComplexLiterals with a
		// real component, since they are never returned by the parser.
		{`0i`, `0.0i`},
		{`5i`, `5.0i`},
		{`3.1415926535i`, `3.1415926535i`},
		{`a`, `a`},
		{`abc_xyz`, `abc_xyz`},
		{`-1`, `-1`},
		{`+-1`, `+-1`},
		{`<-abc_xyz`, `<-abc_xyz`},
		{`**a`, `**a`},
		{`1 + 1`, `1 + 1`},
		{`1 * abc`, `1 * abc`},
		{`-x / *b`, `-x / *b`},
		{`a + b / c + d`, `a + b / c + d`},
		{`(a + b) / (c + d)`, `(a + b) / (c + d)`},
		{`a()`, `a()`},
		{`a(b, c)`, `a(b, c)`},
		{`a(b, c...)`, `a(b, c...)`},
		{`*a(b, (c + d) / e)`, `*a(b, (c + d) / e)`},
		{`(*int32)(4)`, `(*int32)(4)`},
		{`a.b.c`, `a.b.c`},
		{`a(b, c).d`, `a(b, c).d`},
		{`-a(b, c).d + 12`, `-a(b, c).d + 12`},
		{`a.(b)`, `a.(b)`},
		{`a().(b.c).(e)`, `a().(b.c).(e)`},
		{`a[:]`, `a[:]`},
		{`a[1:]`, `a[1:]`},
		{`a[:2]`, `a[:2]`},
		{`a[1:2]`, `a[1:2]`},
		{`a[1:2:3]`, `a[1:2:3]`},
		{`a[:len(a) - 1]`, `a[:len(a) - 1]`},
		{`a[0]`, `a[0]`},
		{`a[len(a) - 1]`, `a[len(a) - 1]`},
		{`point{a, b}`, `point{a, b}`},
		{`point{x: a, y: b}`, `point{x: a, y: b}`},
		{`(*point){x: a, y: b}`, `(*point){x: a, y: b}`},
		{`[]int`, `[]int`},
		{`[][]int32{}`, `[][]int32{}`},
		{`[2]float64`, `[2]float64`},
		{`[...]float64{0, 0}`, `[...]float64{0, 0}`},
		{`map[string]int`, `map[string]int`},
		{`map[string]*[]float64`, `map[string]*[]float64`},
		{`chan int`, `chan int`},
		{`<-chan int`, `<-chan int`},
		{`chan<- int`, `chan<- int`},
		{`chan<- <-chan int`, `chan<- <-chan int`},
		{`func(){}`, `func(){…}`},
		{`func(int){}`, `func(int){…}`},
		{`func(int)bool{}`, `func(int)bool{…}`},
		{`func(int, float64){}`, `func(int, float64){…}`},
		{`func()(int, int){}`, `func()(int, int){…}`},
		{`func(int, ...float64)(int, int){}`, `func(int, ...float64)(int, int){…}`},
		{`func(x, y int)(z int){}`, `func(x int, y int)(z int){…}`},
		{`func(x, y ...int)(z int, err error){}`, `func(x int, y ...int)(z int, err error){…}`},
		{`struct{ x, y int }{}`, `struct{…}{}`},
		{`interface{ x(); y(int)bool }{}`, `interface{…}{}`},
	}
	for _, test := range tests {
		l := token.NewLexer("", test.expr)
		p := NewParser(l)
		e := parseExpr(p)
		got := e.Source()
		if test.want != got {
			t.Errorf("(%s).Source()=[%s], want [%s]", test.expr, got, test.want)
		}
	}

	// These can't be tested above, because the parser never returns them.
	var zero big.Rat
	nodeTests := []struct {
		expr Expression
		want string
	}{
		{&NilLiteral{}, "nil"},
		{&BoolLiteral{}, "false"},
		{&BoolLiteral{Value: true}, "true"},
		{&ComplexLiteral{Real: &zero, Imaginary: &zero}, "0.0i"},
		{&ComplexLiteral{Real: &zero, Imaginary: big.NewRat(5, 1)}, "5.0i"},
		{&ComplexLiteral{Real: big.NewRat(5, 1), Imaginary: &zero}, "5.0+0.0i"},
		{&ComplexLiteral{Real: big.NewRat(5, 1), Imaginary: big.NewRat(5, 1)}, "5.0+5.0i"},
		{&ComplexLiteral{Real: big.NewRat(5, 1), Imaginary: big.NewRat(-5, 1)}, "5.0-5.0i"},
		{&ComplexLiteral{Real: big.NewRat(-5, 1), Imaginary: big.NewRat(-5, 1)}, "-5.0-5.0i"},
	}
	for _, test := range nodeTests {
		got := test.expr.Source()
		if got != test.want {
			t.Errorf("(%s).Source()=[%s], want [%s]", pretty.String(test.expr), got, test.want)
		}
	}
}