mirror of
https://github.com/golang/go.git
synced 2025-10-22 12:33:19 +00:00
go/doc, godoc, gotest: support for reading example documentation
This CL introduces the go.Example type and go.Examples functions that are used to represent and extract code samples from Go source. They should be of the form: // Output of this function. func ExampleFoo() { fmt.Println("Output of this function.") } It also modifies godoc to read example code from _test.go files, and include them in the HTML output with JavaScript-driven toggles. It also implements testing of example functions with gotest. The stdout/stderr is compared against the output comment on the function. This CL includes examples for the sort.Ints function and the sort.SortInts type. After patching this CL in and re-building go/doc and godoc, try godoc -http=localhost:6060 and visit http://localhost:6060/pkg/sort/ R=gri, r, rsc CC=golang-dev https://golang.org/cl/5137041
This commit is contained in:
parent
155e21cc7f
commit
af1ae438b9
12 changed files with 292 additions and 24 deletions
84
src/pkg/testing/example.go
Normal file
84
src/pkg/testing/example.go
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2009 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.
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type InternalExample struct {
|
||||
Name string
|
||||
F func()
|
||||
Output string
|
||||
}
|
||||
|
||||
func RunExamples(examples []InternalExample) (ok bool) {
|
||||
ok = true
|
||||
|
||||
stdout, stderr := os.Stdout, os.Stderr
|
||||
defer func() {
|
||||
os.Stdout, os.Stderr = stdout, stderr
|
||||
if e := recover(); e != nil {
|
||||
if err, ok := e.(os.Error); ok {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
panic(e)
|
||||
}
|
||||
}()
|
||||
|
||||
for _, eg := range examples {
|
||||
if *chatty {
|
||||
fmt.Fprintln(os.Stderr, "=== RUN:", eg.Name)
|
||||
}
|
||||
|
||||
// capture stdout and stderr for testing purposes
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Stdout, os.Stderr = w, w
|
||||
outC := make(chan string)
|
||||
go func() {
|
||||
buf := new(bytes.Buffer)
|
||||
_, err := io.Copy(buf, r)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
outC <- buf.String()
|
||||
}()
|
||||
|
||||
// run example
|
||||
ns := -time.Nanoseconds()
|
||||
eg.F()
|
||||
ns += time.Nanoseconds()
|
||||
|
||||
// close pipe, restore stdout/stderr, get output
|
||||
w.Close()
|
||||
os.Stdout, os.Stderr = stdout, stderr
|
||||
out := <-outC
|
||||
|
||||
// report any errors
|
||||
if out != eg.Output {
|
||||
fmt.Fprintf(
|
||||
os.Stderr,
|
||||
"--- FAIL: %s\ngot:\n%s\nwant:\n%s\n",
|
||||
eg.Name, out, eg.Output,
|
||||
)
|
||||
ok = false
|
||||
} else if *chatty {
|
||||
tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
|
||||
fmt.Fprintln(os.Stderr, "--- PASS:", eg.Name, tstr)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue