OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [go/] [printer/] [printer_test.go] - Blame information for rev 774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 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 printer
6
 
7
import (
8
        "bytes"
9
        "flag"
10
        "go/ast"
11
        "go/parser"
12
        "go/token"
13
        "io/ioutil"
14
        "path/filepath"
15
        "testing"
16
        "time"
17
)
18
 
19
const (
20
        dataDir  = "testdata"
21
        tabwidth = 8
22
)
23
 
24
var update = flag.Bool("update", false, "update golden files")
25
 
26
var fset = token.NewFileSet()
27
 
28
func lineString(text []byte, i int) string {
29
        i0 := i
30
        for i < len(text) && text[i] != '\n' {
31
                i++
32
        }
33
        return string(text[i0:i])
34
}
35
 
36
type checkMode uint
37
 
38
const (
39
        export checkMode = 1 << iota
40
        rawFormat
41
)
42
 
43
func runcheck(t *testing.T, source, golden string, mode checkMode) {
44
        // parse source
45
        prog, err := parser.ParseFile(fset, source, nil, parser.ParseComments)
46
        if err != nil {
47
                t.Error(err)
48
                return
49
        }
50
 
51
        // filter exports if necessary
52
        if mode&export != 0 {
53
                ast.FileExports(prog) // ignore result
54
                prog.Comments = nil   // don't print comments that are not in AST
55
        }
56
 
57
        // determine printer configuration
58
        cfg := Config{Tabwidth: tabwidth}
59
        if mode&rawFormat != 0 {
60
                cfg.Mode |= RawFormat
61
        }
62
 
63
        // format source
64
        var buf bytes.Buffer
65
        if err := cfg.Fprint(&buf, fset, prog); err != nil {
66
                t.Error(err)
67
        }
68
        res := buf.Bytes()
69
 
70
        // update golden files if necessary
71
        if *update {
72
                if err := ioutil.WriteFile(golden, res, 0644); err != nil {
73
                        t.Error(err)
74
                }
75
                return
76
        }
77
 
78
        // get golden
79
        gld, err := ioutil.ReadFile(golden)
80
        if err != nil {
81
                t.Error(err)
82
                return
83
        }
84
 
85
        // compare lengths
86
        if len(res) != len(gld) {
87
                t.Errorf("len = %d, expected %d (= len(%s))", len(res), len(gld), golden)
88
        }
89
 
90
        // compare contents
91
        for i, line, offs := 0, 1, 0; i < len(res) && i < len(gld); i++ {
92
                ch := res[i]
93
                if ch != gld[i] {
94
                        t.Errorf("%s:%d:%d: %s", source, line, i-offs+1, lineString(res, offs))
95
                        t.Errorf("%s:%d:%d: %s", golden, line, i-offs+1, lineString(gld, offs))
96
                        t.Error()
97
                        return
98
                }
99
                if ch == '\n' {
100
                        line++
101
                        offs = i + 1
102
                }
103
        }
104
}
105
 
106
func check(t *testing.T, source, golden string, mode checkMode) {
107
        // start a timer to produce a time-out signal
108
        tc := make(chan int)
109
        go func() {
110
                time.Sleep(10 * time.Second) // plenty of a safety margin, even for very slow machines
111
                tc <- 0
112
        }()
113
 
114
        // run the test
115
        cc := make(chan int)
116
        go func() {
117
                runcheck(t, source, golden, mode)
118
                cc <- 0
119
        }()
120
 
121
        // wait for the first finisher
122
        select {
123
        case <-tc:
124
                // test running past time out
125
                t.Errorf("%s: running too slowly", source)
126
        case <-cc:
127
                // test finished within alloted time margin
128
        }
129
}
130
 
131
type entry struct {
132
        source, golden string
133
        mode           checkMode
134
}
135
 
136
// Use gotest -update to create/update the respective golden files.
137
var data = []entry{
138
        {"empty.input", "empty.golden", 0},
139
        {"comments.input", "comments.golden", 0},
140
        {"comments.input", "comments.x", export},
141
        {"linebreaks.input", "linebreaks.golden", 0},
142
        {"expressions.input", "expressions.golden", 0},
143
        {"expressions.input", "expressions.raw", rawFormat},
144
        {"declarations.input", "declarations.golden", 0},
145
        {"statements.input", "statements.golden", 0},
146
        {"slow.input", "slow.golden", 0},
147
}
148
 
149
func TestFiles(t *testing.T) {
150
        for i, e := range data {
151
                source := filepath.Join(dataDir, e.source)
152
                golden := filepath.Join(dataDir, e.golden)
153
                check(t, source, golden, e.mode)
154
                // TODO(gri) check that golden is idempotent
155
                //check(t, golden, golden, e.mode)
156
                if testing.Short() && i >= 3 {
157
                        break
158
                }
159
        }
160
}
161
 
162
// TestLineComments, using a simple test case, checks that consequtive line
163
// comments are properly terminated with a newline even if the AST position
164
// information is incorrect.
165
//
166
func TestLineComments(t *testing.T) {
167
        const src = `// comment 1
168
        // comment 2
169
        // comment 3
170
        package main
171
        `
172
 
173
        fset := token.NewFileSet()
174
        f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
175
        if err != nil {
176
                panic(err) // error in test
177
        }
178
 
179
        var buf bytes.Buffer
180
        fset = token.NewFileSet() // use the wrong file set
181
        Fprint(&buf, fset, f)
182
 
183
        nlines := 0
184
        for _, ch := range buf.Bytes() {
185
                if ch == '\n' {
186
                        nlines++
187
                }
188
        }
189
 
190
        const expected = 3
191
        if nlines < expected {
192
                t.Errorf("got %d, expected %d\n", nlines, expected)
193
                t.Errorf("result:\n%s", buf.Bytes())
194
        }
195
}
196
 
197
// Verify that the printer can be invoked during initialization.
198
func init() {
199
        const name = "foobar"
200
        var buf bytes.Buffer
201
        if err := Fprint(&buf, fset, &ast.Ident{Name: name}); err != nil {
202
                panic(err) // error in test
203
        }
204
        // in debug mode, the result contains additional information;
205
        // ignore it
206
        if s := buf.String(); !debug && s != name {
207
                panic("got " + s + ", want " + name)
208
        }
209
}
210
 
211
// Verify that the printer doesn't crash if the AST contains BadXXX nodes.
212
func TestBadNodes(t *testing.T) {
213
        const src = "package p\n("
214
        const res = "package p\nBadDecl\n"
215
        f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
216
        if err == nil {
217
                t.Error("expected illegal program") // error in test
218
        }
219
        var buf bytes.Buffer
220
        Fprint(&buf, fset, f)
221
        if buf.String() != res {
222
                t.Errorf("got %q, expected %q", buf.String(), res)
223
        }
224
}
225
 
226
// Print and parse f with
227
func testComment(t *testing.T, f *ast.File, srclen int, comment *ast.Comment) {
228
        f.Comments[0].List[0] = comment
229
        var buf bytes.Buffer
230
        for offs := 0; offs <= srclen; offs++ {
231
                buf.Reset()
232
                // Printing f should result in a correct program no
233
                // matter what the (incorrect) comment position is.
234
                if err := Fprint(&buf, fset, f); err != nil {
235
                        t.Error(err)
236
                }
237
                if _, err := parser.ParseFile(fset, "", buf.Bytes(), 0); err != nil {
238
                        t.Fatalf("incorrect program for pos = %d:\n%s", comment.Slash, buf.String())
239
                }
240
                // Position information is just an offset.
241
                // Move comment one byte down in the source.
242
                comment.Slash++
243
        }
244
}
245
 
246
// Verify that the printer produces always produces a correct program
247
// even if the position information of comments introducing newlines
248
// is incorrect.
249
func TestBadComments(t *testing.T) {
250
        const src = `
251
// first comment - text and position changed by test
252
package p
253
import "fmt"
254
const pi = 3.14 // rough circle
255
var (
256
        x, y, z int = 1, 2, 3
257
        u, v float64
258
)
259
func fibo(n int) {
260
        if n < 2 {
261
                return n /* seed values */
262
        }
263
        return fibo(n-1) + fibo(n-2)
264
}
265
`
266
 
267
        f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
268
        if err != nil {
269
                t.Error(err) // error in test
270
        }
271
 
272
        comment := f.Comments[0].List[0]
273
        pos := comment.Pos()
274
        if fset.Position(pos).Offset != 1 {
275
                t.Error("expected offset 1") // error in test
276
        }
277
 
278
        testComment(t, f, len(src), &ast.Comment{pos, "//-style comment"})
279
        testComment(t, f, len(src), &ast.Comment{pos, "/*-style comment */"})
280
        testComment(t, f, len(src), &ast.Comment{pos, "/*-style \n comment */"})
281
        testComment(t, f, len(src), &ast.Comment{pos, "/*-style comment \n\n\n */"})
282
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.