github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/src/go/doc/doc_test.go (about)

     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 doc
     6  
     7  import (
     8  	"bytes"
     9  	"flag"
    10  	"fmt"
    11  	"go/parser"
    12  	"go/printer"
    13  	"go/token"
    14  	"io/ioutil"
    15  	"os"
    16  	"path/filepath"
    17  	"regexp"
    18  	"strings"
    19  	"testing"
    20  	"text/template"
    21  )
    22  
    23  var update = flag.Bool("update", false, "update golden (.out) files")
    24  var files = flag.String("files", "", "consider only Go test files matching this regular expression")
    25  
    26  const dataDir = "testdata"
    27  
    28  var templateTxt = readTemplate("template.txt")
    29  
    30  func readTemplate(filename string) *template.Template {
    31  	t := template.New(filename)
    32  	t.Funcs(template.FuncMap{
    33  		"node":     nodeFmt,
    34  		"synopsis": synopsisFmt,
    35  		"indent":   indentFmt,
    36  	})
    37  	return template.Must(t.ParseFiles(filepath.Join(dataDir, filename)))
    38  }
    39  
    40  func nodeFmt(node interface{}, fset *token.FileSet) string {
    41  	var buf bytes.Buffer
    42  	printer.Fprint(&buf, fset, node)
    43  	return strings.Replace(strings.TrimSpace(buf.String()), "\n", "\n\t", -1)
    44  }
    45  
    46  func synopsisFmt(s string) string {
    47  	const n = 64
    48  	if len(s) > n {
    49  		// cut off excess text and go back to a word boundary
    50  		s = s[0:n]
    51  		if i := strings.LastIndexAny(s, "\t\n "); i >= 0 {
    52  			s = s[0:i]
    53  		}
    54  		s = strings.TrimSpace(s) + " ..."
    55  	}
    56  	return "// " + strings.Replace(s, "\n", " ", -1)
    57  }
    58  
    59  func indentFmt(indent, s string) string {
    60  	end := ""
    61  	if strings.HasSuffix(s, "\n") {
    62  		end = "\n"
    63  		s = s[:len(s)-1]
    64  	}
    65  	return indent + strings.Replace(s, "\n", "\n"+indent, -1) + end
    66  }
    67  
    68  func isGoFile(fi os.FileInfo) bool {
    69  	name := fi.Name()
    70  	return !fi.IsDir() &&
    71  		len(name) > 0 && name[0] != '.' && // ignore .files
    72  		filepath.Ext(name) == ".go"
    73  }
    74  
    75  type bundle struct {
    76  	*Package
    77  	FSet *token.FileSet
    78  }
    79  
    80  func test(t *testing.T, mode Mode) {
    81  	// determine file filter
    82  	filter := isGoFile
    83  	if *files != "" {
    84  		rx, err := regexp.Compile(*files)
    85  		if err != nil {
    86  			t.Fatal(err)
    87  		}
    88  		filter = func(fi os.FileInfo) bool {
    89  			return isGoFile(fi) && rx.MatchString(fi.Name())
    90  		}
    91  	}
    92  
    93  	// get packages
    94  	fset := token.NewFileSet()
    95  	pkgs, err := parser.ParseDir(fset, dataDir, filter, parser.ParseComments)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  
   100  	// test packages
   101  	for _, pkg := range pkgs {
   102  		importpath := dataDir + "/" + pkg.Name
   103  		doc := New(pkg, importpath, mode)
   104  
   105  		// golden files always use / in filenames - canonicalize them
   106  		for i, filename := range doc.Filenames {
   107  			doc.Filenames[i] = filepath.ToSlash(filename)
   108  		}
   109  
   110  		// print documentation
   111  		var buf bytes.Buffer
   112  		if err := templateTxt.Execute(&buf, bundle{doc, fset}); err != nil {
   113  			t.Error(err)
   114  			continue
   115  		}
   116  		got := buf.Bytes()
   117  
   118  		// update golden file if necessary
   119  		golden := filepath.Join(dataDir, fmt.Sprintf("%s.%d.golden", pkg.Name, mode))
   120  		if *update {
   121  			err := ioutil.WriteFile(golden, got, 0644)
   122  			if err != nil {
   123  				t.Error(err)
   124  			}
   125  			continue
   126  		}
   127  
   128  		// get golden file
   129  		want, err := ioutil.ReadFile(golden)
   130  		if err != nil {
   131  			t.Error(err)
   132  			continue
   133  		}
   134  
   135  		// compare
   136  		if !bytes.Equal(got, want) {
   137  			t.Errorf("package %s\n\tgot:\n%s\n\twant:\n%s", pkg.Name, got, want)
   138  		}
   139  	}
   140  }
   141  
   142  func Test(t *testing.T) {
   143  	test(t, 0)
   144  	test(t, AllDecls)
   145  	test(t, AllMethods)
   146  }