|  | // +build !nacl,!js | 
|  | // run | 
|  |  | 
|  | // Copyright 2018 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. | 
|  |  | 
|  | // Ensure that label redefinition errors print out | 
|  | // a column number that matches the start of the current label's | 
|  | // definition instead of the label delimiting token ":" | 
|  |  | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "bytes" | 
|  | "fmt" | 
|  | "io/ioutil" | 
|  | "log" | 
|  | "os" | 
|  | "os/exec" | 
|  | "path/filepath" | 
|  | "regexp" | 
|  | ) | 
|  |  | 
|  | func main() { | 
|  | tmpdir, err := ioutil.TempDir("", "issue26411") | 
|  | if err != nil { | 
|  | log.Fatalf("Failed to create temporary directory: %v", err) | 
|  | } | 
|  | defer os.RemoveAll(tmpdir) | 
|  |  | 
|  | tests := []struct { | 
|  | code   string | 
|  | errors []string | 
|  | }{ | 
|  | { | 
|  | code: ` | 
|  | package main | 
|  |  | 
|  | func main() { | 
|  | foo: | 
|  | foo: | 
|  | } | 
|  | `, | 
|  | errors: []string{ | 
|  | "^.+:5:1: label foo defined and not used\n", | 
|  | ".+:6:1: label foo already defined at .+:5:1\n$", | 
|  | }, | 
|  | }, | 
|  | { | 
|  | code: ` | 
|  | package main | 
|  |  | 
|  | func main() { | 
|  |  | 
|  | bar: | 
|  | bar: | 
|  | bar: | 
|  | bar            : | 
|  | } | 
|  | `, | 
|  |  | 
|  | errors: []string{ | 
|  | "^.+:6:13: label bar defined and not used\n", | 
|  | ".+:7:4: label bar already defined at .+:6:13\n", | 
|  | ".+:8:1: label bar already defined at .+:6:13\n", | 
|  | ".+:9:1: label bar already defined at .+:6:13\n$", | 
|  | }, | 
|  | }, | 
|  | } | 
|  |  | 
|  | for i, test := range tests { | 
|  | filename := filepath.Join(tmpdir, fmt.Sprintf("%d.go", i)) | 
|  | if err := ioutil.WriteFile(filename, []byte(test.code), 0644); err != nil { | 
|  | log.Printf("#%d: failed to create file %s", i, filename) | 
|  | continue | 
|  | } | 
|  | output, _ := exec.Command("go", "tool", "compile", filename).CombinedOutput() | 
|  |  | 
|  | // remove each matching error from the output | 
|  | for _, err := range test.errors { | 
|  | rx := regexp.MustCompile(err) | 
|  | match := rx.Find(output) | 
|  | output = bytes.Replace(output, match, nil, 1) // remove match (which might be nil) from output | 
|  | } | 
|  |  | 
|  | // at this point all output should have been consumed | 
|  | if len(output) != 0 { | 
|  | log.Printf("Test case %d has unmatched errors:\n%s", i, output) | 
|  | } | 
|  | } | 
|  | } |