...

Source file src/go/format/format_test.go

Documentation: go/format

		 1  // Copyright 2012 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  package format
		 6  
		 7  import (
		 8  	"bytes"
		 9  	"go/ast"
		10  	"go/parser"
		11  	"go/token"
		12  	"os"
		13  	"strings"
		14  	"testing"
		15  )
		16  
		17  const testfile = "format_test.go"
		18  
		19  func diff(t *testing.T, dst, src []byte) {
		20  	line := 1
		21  	offs := 0 // line offset
		22  	for i := 0; i < len(dst) && i < len(src); i++ {
		23  		d := dst[i]
		24  		s := src[i]
		25  		if d != s {
		26  			t.Errorf("dst:%d: %s\n", line, dst[offs:i+1])
		27  			t.Errorf("src:%d: %s\n", line, src[offs:i+1])
		28  			return
		29  		}
		30  		if s == '\n' {
		31  			line++
		32  			offs = i + 1
		33  		}
		34  	}
		35  	if len(dst) != len(src) {
		36  		t.Errorf("len(dst) = %d, len(src) = %d\nsrc = %q", len(dst), len(src), src)
		37  	}
		38  }
		39  
		40  func TestNode(t *testing.T) {
		41  	src, err := os.ReadFile(testfile)
		42  	if err != nil {
		43  		t.Fatal(err)
		44  	}
		45  
		46  	fset := token.NewFileSet()
		47  	file, err := parser.ParseFile(fset, testfile, src, parser.ParseComments)
		48  	if err != nil {
		49  		t.Fatal(err)
		50  	}
		51  
		52  	var buf bytes.Buffer
		53  
		54  	if err = Node(&buf, fset, file); err != nil {
		55  		t.Fatal("Node failed:", err)
		56  	}
		57  
		58  	diff(t, buf.Bytes(), src)
		59  }
		60  
		61  // Node is documented to not modify the AST.
		62  // Test that it is so even when numbers are normalized.
		63  func TestNodeNoModify(t *testing.T) {
		64  	const (
		65  		src		= "package p\n\nconst _ = 0000000123i\n"
		66  		golden = "package p\n\nconst _ = 123i\n"
		67  	)
		68  
		69  	fset := token.NewFileSet()
		70  	file, err := parser.ParseFile(fset, "", src, parser.ParseComments)
		71  	if err != nil {
		72  		t.Fatal(err)
		73  	}
		74  
		75  	// Capture original address and value of a BasicLit node
		76  	// which will undergo formatting changes during printing.
		77  	wantLit := file.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0].(*ast.BasicLit)
		78  	wantVal := wantLit.Value
		79  
		80  	var buf bytes.Buffer
		81  	if err = Node(&buf, fset, file); err != nil {
		82  		t.Fatal("Node failed:", err)
		83  	}
		84  	diff(t, buf.Bytes(), []byte(golden))
		85  
		86  	// Check if anything changed after Node returned.
		87  	gotLit := file.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0].(*ast.BasicLit)
		88  	gotVal := gotLit.Value
		89  
		90  	if gotLit != wantLit {
		91  		t.Errorf("got *ast.BasicLit address %p, want %p", gotLit, wantLit)
		92  	}
		93  	if gotVal != wantVal {
		94  		t.Errorf("got *ast.BasicLit value %q, want %q", gotVal, wantVal)
		95  	}
		96  }
		97  
		98  func TestSource(t *testing.T) {
		99  	src, err := os.ReadFile(testfile)
	 100  	if err != nil {
	 101  		t.Fatal(err)
	 102  	}
	 103  
	 104  	res, err := Source(src)
	 105  	if err != nil {
	 106  		t.Fatal("Source failed:", err)
	 107  	}
	 108  
	 109  	diff(t, res, src)
	 110  }
	 111  
	 112  // Test cases that are expected to fail are marked by the prefix "ERROR".
	 113  // The formatted result must look the same as the input for successful tests.
	 114  var tests = []string{
	 115  	// declaration lists
	 116  	`import "go/format"`,
	 117  	"var x int",
	 118  	"var x int\n\ntype T struct{}",
	 119  
	 120  	// statement lists
	 121  	"x := 0",
	 122  	"f(a, b, c)\nvar x int = f(1, 2, 3)",
	 123  
	 124  	// indentation, leading and trailing space
	 125  	"\tx := 0\n\tgo f()",
	 126  	"\tx := 0\n\tgo f()\n\n\n",
	 127  	"\n\t\t\n\n\tx := 0\n\tgo f()\n\n\n",
	 128  	"\n\t\t\n\n\t\t\tx := 0\n\t\t\tgo f()\n\n\n",
	 129  	"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n",		 // no indentation added inside raw strings
	 130  	"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\n\t\tfoo\n`\n\n\n", // no indentation removed inside raw strings
	 131  
	 132  	// comments
	 133  	"/* Comment */",
	 134  	"\t/* Comment */ ",
	 135  	"\n/* Comment */ ",
	 136  	"i := 5 /* Comment */",				 // issue #5551
	 137  	"\ta()\n//line :1",						 // issue #11276
	 138  	"\t//xxx\n\ta()\n//line :2",		// issue #11276
	 139  	"\ta() //line :1\n\tb()\n",		 // issue #11276
	 140  	"x := 0\n//line :1\n//line :2", // issue #11276
	 141  
	 142  	// whitespace
	 143  	"",		 // issue #11275
	 144  	" ",		// issue #11275
	 145  	"\t",	 // issue #11275
	 146  	"\t\t", // issue #11275
	 147  	"\n",	 // issue #11275
	 148  	"\n\n", // issue #11275
	 149  	"\t\n", // issue #11275
	 150  
	 151  	// erroneous programs
	 152  	"ERROR1 + 2 +",
	 153  	"ERRORx :=	0",
	 154  
	 155  	// build comments
	 156  	"// copyright\n\n//go:build x\n\npackage p\n",
	 157  	"// copyright\n\n//go:build x\n// +build x\n\npackage p\n",
	 158  }
	 159  
	 160  func String(s string) (string, error) {
	 161  	res, err := Source([]byte(s))
	 162  	if err != nil {
	 163  		return "", err
	 164  	}
	 165  	return string(res), nil
	 166  }
	 167  
	 168  func TestPartial(t *testing.T) {
	 169  	for _, src := range tests {
	 170  		if strings.HasPrefix(src, "ERROR") {
	 171  			// test expected to fail
	 172  			src = src[5:] // remove ERROR prefix
	 173  			res, err := String(src)
	 174  			if err == nil && res == src {
	 175  				t.Errorf("formatting succeeded but was expected to fail:\n%q", src)
	 176  			}
	 177  		} else {
	 178  			// test expected to succeed
	 179  			res, err := String(src)
	 180  			if err != nil {
	 181  				t.Errorf("formatting failed (%s):\n%q", err, src)
	 182  			} else if res != src {
	 183  				t.Errorf("formatting incorrect:\nsource: %q\nresult: %q", src, res)
	 184  			}
	 185  		}
	 186  	}
	 187  }
	 188  

View as plain text