Home | History | Annotate | Download | only in types
      1 // Copyright 2016 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 // This file contains tests for sizes.
      6 
      7 package types_test
      8 
      9 import (
     10 	"go/ast"
     11 	"go/importer"
     12 	"go/parser"
     13 	"go/token"
     14 	"go/types"
     15 	"testing"
     16 )
     17 
     18 // findStructType typechecks src and returns the first struct type encountered.
     19 func findStructType(t *testing.T, src string) *types.Struct {
     20 	fset := token.NewFileSet()
     21 	f, err := parser.ParseFile(fset, "x.go", src, 0)
     22 	if err != nil {
     23 		t.Fatal(err)
     24 	}
     25 	info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
     26 	var conf types.Config
     27 	_, err = conf.Check("x", fset, []*ast.File{f}, &info)
     28 	if err != nil {
     29 		t.Fatal(err)
     30 	}
     31 	for _, tv := range info.Types {
     32 		if ts, ok := tv.Type.(*types.Struct); ok {
     33 			return ts
     34 		}
     35 	}
     36 	t.Fatalf("failed to find a struct type in src:\n%s\n", src)
     37 	return nil
     38 }
     39 
     40 // Issue 16316
     41 func TestMultipleSizeUse(t *testing.T) {
     42 	const src = `
     43 package main
     44 
     45 type S struct {
     46     i int
     47     b bool
     48     s string
     49     n int
     50 }
     51 `
     52 	ts := findStructType(t, src)
     53 	sizes := types.StdSizes{WordSize: 4, MaxAlign: 4}
     54 	if got := sizes.Sizeof(ts); got != 20 {
     55 		t.Errorf("Sizeof(%v) with WordSize 4 = %d want 20", ts, got)
     56 	}
     57 	sizes = types.StdSizes{WordSize: 8, MaxAlign: 8}
     58 	if got := sizes.Sizeof(ts); got != 40 {
     59 		t.Errorf("Sizeof(%v) with WordSize 8 = %d want 40", ts, got)
     60 	}
     61 }
     62 
     63 // Issue 16464
     64 func TestAlignofNaclSlice(t *testing.T) {
     65 	const src = `
     66 package main
     67 
     68 var s struct {
     69 	x *int
     70 	y []byte
     71 }
     72 `
     73 	ts := findStructType(t, src)
     74 	sizes := &types.StdSizes{WordSize: 4, MaxAlign: 8}
     75 	var fields []*types.Var
     76 	// Make a copy manually :(
     77 	for i := 0; i < ts.NumFields(); i++ {
     78 		fields = append(fields, ts.Field(i))
     79 	}
     80 	offsets := sizes.Offsetsof(fields)
     81 	if offsets[0] != 0 || offsets[1] != 4 {
     82 		t.Errorf("OffsetsOf(%v) = %v want %v", ts, offsets, []int{0, 4})
     83 	}
     84 }
     85 
     86 func TestIssue16902(t *testing.T) {
     87 	const src = `
     88 package a
     89 
     90 import "unsafe"
     91 
     92 const _ = unsafe.Offsetof(struct{ x int64 }{}.x)
     93 `
     94 	fset := token.NewFileSet()
     95 	f, err := parser.ParseFile(fset, "x.go", src, 0)
     96 	if err != nil {
     97 		t.Fatal(err)
     98 	}
     99 	info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
    100 	conf := types.Config{
    101 		Importer: importer.Default(),
    102 		Sizes:    &types.StdSizes{WordSize: 8, MaxAlign: 8},
    103 	}
    104 	_, err = conf.Check("x", fset, []*ast.File{f}, &info)
    105 	if err != nil {
    106 		t.Fatal(err)
    107 	}
    108 	for _, tv := range info.Types {
    109 		_ = conf.Sizes.Sizeof(tv.Type)
    110 		_ = conf.Sizes.Alignof(tv.Type)
    111 	}
    112 }
    113