Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3351)

Delta Between Two Patch Sets: oracle/oracle_test.go

Issue 13270045: code review 13270045: go.tools/oracle: add option to output results in JSON s... (Closed)
Left Patch Set: diff -r 28b59754195f https://code.google.com/p/go.tools Created 10 years, 7 months ago
Right Patch Set: diff -r 07183b5c385c https://code.google.com/p/go.tools Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « oracle/oracle.go ('k') | oracle/peers.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package oracle_test 5 package oracle_test
6 6
7 // This file defines a test framework for oracle queries. 7 // This file defines a test framework for oracle queries.
8 // 8 //
9 // The files beneath testdata/src/main contain Go programs containing 9 // The files beneath testdata/src/main contain Go programs containing
10 // query annotations of the form: 10 // query annotations of the form:
11 // 11 //
12 // @verb id "select" 12 // @verb id "select"
13 // 13 //
14 // where verb is the query mode (e.g. "callers"), id is a unique name 14 // where verb is the query mode (e.g. "callers"), id is a unique name
15 // for this query, and "select" is a regular expression matching the 15 // for this query, and "select" is a regular expression matching the
16 // substring of the current line that is the query's input selection. 16 // substring of the current line that is the query's input selection.
17 // 17 //
18 // The expected output for each query is provided in the accompanying 18 // The expected output for each query is provided in the accompanying
19 // .golden file. 19 // .golden file.
20 // 20 //
21 // (Location information is not included because it's too fragile to 21 // (Location information is not included because it's too fragile to
22 // display as text. TODO(adonovan): think about how we can test its 22 // display as text. TODO(adonovan): think about how we can test its
23 // correctness, since it is critical information.) 23 // correctness, since it is critical information.)
24 // 24 //
25 // Run this test with: 25 // Run this test with:
26 // % go test code.google.com/p/go.tools/oracle -update 26 // % go test code.google.com/p/go.tools/oracle -update
27 // to update the golden files. 27 // to update the golden files.
28 28
29 // TODO(adonovan): improve coverage:
30 // - output of @callgraph is nondeterministic.
31 // - as are lists of labels.
32
33 import ( 29 import (
34 "bytes" 30 "bytes"
31 "encoding/json"
35 "flag" 32 "flag"
36 "fmt" 33 "fmt"
37 "go/build" 34 "go/build"
38 "go/parser" 35 "go/parser"
39 "go/token" 36 "go/token"
40 "io" 37 "io"
41 "io/ioutil" 38 "io/ioutil"
42 "os" 39 "os"
43 "os/exec" 40 "os/exec"
44 "regexp" 41 "regexp"
42 "runtime"
45 "strconv" 43 "strconv"
46 "strings" 44 "strings"
47 "testing" 45 "testing"
48 46
49 "code.google.com/p/go.tools/oracle" 47 "code.google.com/p/go.tools/oracle"
50 ) 48 )
51 49
52 var updateFlag = flag.Bool("update", false, "Update the golden files.") 50 var updateFlag = flag.Bool("update", false, "Update the golden files.")
53 51
54 type query struct { 52 type query struct {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 // stripLocation removes a "file:line: " prefix. 149 // stripLocation removes a "file:line: " prefix.
152 func stripLocation(line string) string { 150 func stripLocation(line string) string {
153 if i := strings.Index(line, ": "); i >= 0 { 151 if i := strings.Index(line, ": "); i >= 0 {
154 line = line[i+2:] 152 line = line[i+2:]
155 } 153 }
156 return line 154 return line
157 } 155 }
158 156
159 // doQuery poses query q to the oracle and writes its response and 157 // doQuery poses query q to the oracle and writes its response and
160 // error (if any) to out. 158 // error (if any) to out.
161 func doQuery(out io.Writer, q *query) { 159 func doQuery(out io.Writer, q *query, useJson bool) {
162 fmt.Fprintf(out, "-------- @%s %s --------\n", q.verb, q.id) 160 fmt.Fprintf(out, "-------- @%s %s --------\n", q.verb, q.id)
163 161
164 capture := new(bytes.Buffer) // capture standard output
165 var buildContext = build.Default 162 var buildContext = build.Default
166 buildContext.GOPATH = "testdata" 163 buildContext.GOPATH = "testdata"
167 » err := oracle.Main([]string{q.filename}, 164 » res, err := oracle.Query([]string{q.filename},
168 q.verb, 165 q.verb,
169 » » fmt.Sprintf("%s %d-%d", q.filename, q.start, q.end), 166 » » fmt.Sprintf("%s:%d-%d", q.filename, q.start, q.end),
170 » » /*PTA-log=*/ nil, capture, &buildContext) 167 » » /*PTA-log=*/ nil, &buildContext)
171 168 » if err != nil {
172 » for _, line := range strings.Split(capture.String(), "\n") { 169 » » fmt.Fprintf(out, "\nError: %s\n", stripLocation(err.Error()))
173 » » fmt.Fprintf(out, "%s\n", stripLocation(line)) 170 » » return
174 » } 171 » }
175 172
176 » if err != nil { 173 » if useJson {
177 » » fmt.Fprintf(out, "Error: %s\n", stripLocation(err.Error())) 174 » » // JSON output
175 » » b, err := json.Marshal(res)
176 » » if err != nil {
177 » » » fmt.Fprintf(out, "JSON error: %s\n", err.Error())
178 » » » return
179 » » }
180 » » var buf bytes.Buffer
181 » » if err := json.Indent(&buf, b, "", "\t"); err != nil {
182 » » » fmt.Fprintf(out, "json.Indent failed: %s", err)
183 » » » return
184 » » }
185 » » out.Write(buf.Bytes())
186 » } else {
187 » » // "plain" (compiler diagnostic format) output
188 » » capture := new(bytes.Buffer) // capture standard output
189 » » res.WriteTo(capture)
190 » » for _, line := range strings.Split(capture.String(), "\n") {
191 » » » fmt.Fprintf(out, "%s\n", stripLocation(line))
192 » » }
178 } 193 }
179 } 194 }
180 195
181 func TestOracle(t *testing.T) { 196 func TestOracle(t *testing.T) {
197 switch runtime.GOOS {
198 case "windows":
199 t.Skipf("skipping test on %q (no /usr/bin/diff)", runtime.GOOS)
200 }
201
182 for _, filename := range []string{ 202 for _, filename := range []string{
183 "testdata/src/main/calls.go", 203 "testdata/src/main/calls.go",
184 "testdata/src/main/callgraph.go", 204 "testdata/src/main/callgraph.go",
185 "testdata/src/main/describe.go", 205 "testdata/src/main/describe.go",
186 "testdata/src/main/freevars.go", 206 "testdata/src/main/freevars.go",
187 "testdata/src/main/implements.go", 207 "testdata/src/main/implements.go",
188 "testdata/src/main/imports.go", 208 "testdata/src/main/imports.go",
189 "testdata/src/main/peers.go", 209 "testdata/src/main/peers.go",
210 // JSON:
211 "testdata/src/main/callgraph-json.go",
212 "testdata/src/main/calls-json.go",
213 "testdata/src/main/peers-json.go",
214 "testdata/src/main/describe-json.go",
190 } { 215 } {
216 useJson := strings.HasSuffix(filename, "-json.go")
191 queries := parseQueries(t, filename) 217 queries := parseQueries(t, filename)
192 golden := filename + "lden" 218 golden := filename + "lden"
193 got := filename + "t" 219 got := filename + "t"
194 gotfh, err := os.Create(got) 220 gotfh, err := os.Create(got)
195 if err != nil { 221 if err != nil {
196 t.Errorf("Create(%s) failed: %s", got, err) 222 t.Errorf("Create(%s) failed: %s", got, err)
197 continue 223 continue
198 } 224 }
199 defer gotfh.Close() 225 defer gotfh.Close()
200 226
201 // Run the oracle on each query, redirecting its output 227 // Run the oracle on each query, redirecting its output
202 // and error (if any) to the foo.got file. 228 // and error (if any) to the foo.got file.
203 for _, q := range queries { 229 for _, q := range queries {
204 » » » doQuery(gotfh, q) 230 » » » doQuery(gotfh, q, useJson)
205 } 231 }
206 232
207 // Compare foo.got with foo.golden. 233 // Compare foo.got with foo.golden.
208 » » cmd := exec.Command("/usr/bin/diff", "-u3", golden, got) // assu mes POSIX 234 » » cmd := exec.Command("/usr/bin/diff", "-u", golden, got) // assum es POSIX
209 buf := new(bytes.Buffer) 235 buf := new(bytes.Buffer)
210 cmd.Stdout = buf 236 cmd.Stdout = buf
211 if err := cmd.Run(); err != nil { 237 if err := cmd.Run(); err != nil {
212 t.Errorf("Oracle tests for %s failed: %s.\n%s\n", 238 t.Errorf("Oracle tests for %s failed: %s.\n%s\n",
213 filename, err, buf) 239 filename, err, buf)
214 240
215 if *updateFlag { 241 if *updateFlag {
216 t.Logf("Updating %s...", golden) 242 t.Logf("Updating %s...", golden)
217 if err := exec.Command("/bin/cp", got, golden).R un(); err != nil { 243 if err := exec.Command("/bin/cp", got, golden).R un(); err != nil {
218 t.Errorf("Update failed: %s", err) 244 t.Errorf("Update failed: %s", err)
219 } 245 }
220 } 246 }
221 } 247 }
222 } 248 }
223 } 249 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b