Source file misc/cgo/errors/argposition_test.go

     1  // Copyright 2021 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  // Issue 42580: cmd/cgo: shifting identifier position in ast
     6  
     7  package errorstest
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"go/ast"
    13  	"go/parser"
    14  	"go/token"
    15  	"io/ioutil"
    16  	"os"
    17  	"os/exec"
    18  	"path/filepath"
    19  	"strings"
    20  	"testing"
    21  )
    22  
    23  type ShortPosition struct {
    24  	Line    int
    25  	Column  int
    26  	Visited bool
    27  }
    28  
    29  type IdentPositionInfo map[string][]ShortPosition
    30  
    31  type Visitor struct {
    32  	identPosInfo IdentPositionInfo
    33  	fset         *token.FileSet
    34  	t            *testing.T
    35  }
    36  
    37  func (v *Visitor) Visit(node ast.Node) ast.Visitor {
    38  	if ident, ok := node.(*ast.Ident); ok {
    39  		if expectedPositions, ok := v.identPosInfo[ident.Name]; ok {
    40  			gotMatch := false
    41  			var errorMessage strings.Builder
    42  			for caseIndex, expectedPos := range expectedPositions {
    43  				actualPosition := v.fset.PositionFor(ident.Pos(), true)
    44  				errorOccured := false
    45  				if expectedPos.Line != actualPosition.Line {
    46  					fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
    47  					errorOccured = true
    48  				}
    49  				if expectedPos.Column != actualPosition.Column {
    50  					fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
    51  					errorOccured = true
    52  				}
    53  				if errorOccured {
    54  					continue
    55  				}
    56  				gotMatch = true
    57  				expectedPositions[caseIndex].Visited = true
    58  			}
    59  
    60  			if !gotMatch {
    61  				v.t.Errorf(errorMessage.String())
    62  			}
    63  		}
    64  	}
    65  	return v
    66  }
    67  
    68  func TestArgumentsPositions(t *testing.T) {
    69  	testdata, err := filepath.Abs("testdata")
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	tmpPath := t.TempDir()
    75  
    76  	dir := filepath.Join(tmpPath, "src", "testpositions")
    77  	if err := os.MkdirAll(dir, 0755); err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	cmd := exec.Command("go", "tool", "cgo",
    82  		"-srcdir", testdata,
    83  		"-objdir", dir,
    84  		"issue42580.go")
    85  	cmd.Stderr = new(bytes.Buffer)
    86  
    87  	err = cmd.Run()
    88  	if err != nil {
    89  		t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr)
    90  	}
    91  	mainProcessed, err := ioutil.ReadFile(filepath.Join(dir, "issue42580.cgo1.go"))
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	fset := token.NewFileSet()
    96  	f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors)
    97  	if err != nil {
    98  		fmt.Println(err)
    99  		return
   100  	}
   101  
   102  	expectation := IdentPositionInfo{
   103  		"checkedPointer": []ShortPosition{
   104  			ShortPosition{
   105  				Line:   32,
   106  				Column: 56,
   107  			},
   108  		},
   109  		"singleInnerPointerChecked": []ShortPosition{
   110  			ShortPosition{
   111  				Line:   37,
   112  				Column: 91,
   113  			},
   114  		},
   115  		"doublePointerChecked": []ShortPosition{
   116  			ShortPosition{
   117  				Line:   42,
   118  				Column: 91,
   119  			},
   120  		},
   121  	}
   122  	for _, decl := range f.Decls {
   123  		if fdecl, ok := decl.(*ast.FuncDecl); ok {
   124  			ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body)
   125  		}
   126  	}
   127  	for ident, positions := range expectation {
   128  		for _, position := range positions {
   129  			if !position.Visited {
   130  				t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident)
   131  			}
   132  		}
   133  	}
   134  }
   135  

View as plain text