golang.org/x/tools@v0.21.0/present/parse_test.go (about)

     1  // Copyright 2020 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 present
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"html/template"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"runtime"
    15  	"testing"
    16  )
    17  
    18  func TestTestdata(t *testing.T) {
    19  	tmpl := template.Must(Template().Parse(testTmpl))
    20  	filesP, err := filepath.Glob("testdata/*.p")
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	filesMD, err := filepath.Glob("testdata/*.md")
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	files := append(filesP, filesMD...)
    29  	for _, file := range files {
    30  		file := file
    31  		name := filepath.Base(file)
    32  		if name == "README" {
    33  			continue
    34  		}
    35  		t.Run(name, func(t *testing.T) {
    36  			data, err := os.ReadFile(file)
    37  			if err != nil {
    38  				t.Fatalf("%s: %v", file, err)
    39  			}
    40  			marker := []byte("\n---\n")
    41  			i := bytes.Index(data, marker)
    42  			if i < 0 {
    43  				t.Fatalf("%s: cannot find --- marker in input", file)
    44  			}
    45  			input, html := data[:i+1], data[i+len(marker):]
    46  			doc, err := Parse(bytes.NewReader(input), name, 0)
    47  			if err != nil {
    48  				t.Fatalf("%s: %v", file, err)
    49  			}
    50  			var buf bytes.Buffer
    51  			if err := doc.Render(&buf, tmpl); err != nil {
    52  				t.Fatalf("%s: %v", file, err)
    53  			}
    54  			if !bytes.Equal(buf.Bytes(), html) {
    55  				diffText, err := diff("present-test-", "want", html, "have", buf.Bytes())
    56  				if err != nil {
    57  					t.Fatalf("%s: diff: %v", file, err)
    58  				}
    59  				t.Errorf("%s: incorrect html:\n%s", file, diffText)
    60  			}
    61  		})
    62  	}
    63  }
    64  
    65  func diff(prefix string, name1 string, b1 []byte, name2 string, b2 []byte) ([]byte, error) {
    66  	f1, err := writeTempFile(prefix, b1)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	defer os.Remove(f1)
    71  
    72  	f2, err := writeTempFile(prefix, b2)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	defer os.Remove(f2)
    77  
    78  	cmd := "diff"
    79  	if runtime.GOOS == "plan9" {
    80  		cmd = "/bin/ape/diff"
    81  	}
    82  
    83  	data, err := exec.Command(cmd, "-u", f1, f2).Output()
    84  	if len(data) > 0 {
    85  		// diff exits with a non-zero status when the files don't match.
    86  		// Ignore that failure as long as we get output.
    87  		err = nil
    88  	} else if exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {
    89  		err = fmt.Errorf("%w\nstderr:\n%s)", err, exit.Stderr)
    90  	}
    91  
    92  	data = bytes.Replace(data, []byte(f1), []byte(name1), -1)
    93  	data = bytes.Replace(data, []byte(f2), []byte(name2), -1)
    94  
    95  	return data, err
    96  }
    97  
    98  func writeTempFile(prefix string, data []byte) (string, error) {
    99  	file, err := os.CreateTemp("", prefix)
   100  	if err != nil {
   101  		return "", err
   102  	}
   103  	_, err = file.Write(data)
   104  	if err1 := file.Close(); err == nil {
   105  		err = err1
   106  	}
   107  	if err != nil {
   108  		os.Remove(file.Name())
   109  		return "", err
   110  	}
   111  	return file.Name(), nil
   112  }
   113  
   114  var testTmpl = `
   115  {{define "root" -}}
   116  <h1>{{.Title}}</h1>
   117  {{with .Subtitle}}<h2>{{.}}</h2>
   118  {{end -}}
   119  {{range .Authors}}<author>
   120  {{range .Elem}}{{elem $.Template .}}{{end}}</author>
   121  {{end -}}
   122  {{range .Sections}}<section>{{elem $.Template .}}</section>
   123  {{end -}}
   124  {{end}}
   125  
   126  {{define "newline"}}{{/* No automatic line break. Paragraphs are free-form. */}}
   127  {{end}}
   128  
   129  {{define "section"}}
   130  {{if .Title}}<h2 id="TOC_{{.FormattedNumber}}">{{.Title}}</h2>
   131  {{end -}}
   132  {{range .Elem}}{{elem $.Template .}}{{end}}
   133  {{- end}}
   134  
   135  {{define "list" -}}
   136  <ul>
   137  {{range .Bullet -}}
   138  <li>{{style .}}</li>
   139  {{end -}}
   140  </ul>
   141  {{end}}
   142  
   143  {{define "text" -}}
   144  {{if .Pre -}}
   145  <pre>{{range .Lines}}{{.}}{{end}}</pre>
   146  {{else -}}
   147  <p>{{range $i, $l := .Lines}}{{if $i}}{{template "newline"}}{{end}}{{style $l}}{{end}}</p>
   148  {{end -}}
   149  {{end}}
   150  
   151  {{define "code" -}}
   152  {{if .Play -}}
   153  <div class="playground">{{.Text}}</div>
   154  {{else -}}
   155  <div class="code">{{.Text}}</div>
   156  {{end -}}
   157  {{end}}
   158  
   159  {{define "image" -}}
   160  <img src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}} alt="">
   161  {{end}}
   162  
   163  {{define "caption" -}}
   164  <figcaption>{{style .Text}}</figcaption>
   165  {{end}}
   166  
   167  {{define "iframe" -}}
   168  <iframe src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}></iframe>
   169  {{end}}
   170  
   171  {{define "link" -}}
   172  <p class="link"><a href="{{.URL}}">{{style .Label}}</a></p>
   173  {{end}}
   174  
   175  {{define "html" -}}{{.HTML}}{{end}}
   176  `