1// 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
5package linebreaks
6
7import (
8	"bytes"
9	"fmt"
10	"io"
11	"os"
12	"reflect"
13	"strings"
14	"testing"
15)
16
17type writerTestEntry struct {
18	header *Header
19	contents string
20}
21
22type writerTest struct {
23	file string  // filename of expected output
24	entries []*writerTestEntry
25}
26
27var writerTests = []*writerTest{
28	&writerTest{
29		file: "testdata/writer.tar",
30		entries: []*writerTestEntry{
31			&writerTestEntry{
32				header: &Header{
33					Name: "small.txt",
34					Mode: 0640,
35					Uid: 73025,
36					Gid: 5000,
37					Size: 5,
38					Mtime: 1246508266,
39					Typeflag: '0',
40					Uname: "dsymonds",
41					Gname: "eng",
42				},
43				contents: "Kilts",
44			},
45			&writerTestEntry{
46				header: &Header{
47					Name: "small2.txt",
48					Mode: 0640,
49					Uid: 73025,
50					Gid: 5000,
51					Size: 11,
52					Mtime: 1245217492,
53					Typeflag: '0',
54					Uname: "dsymonds",
55					Gname: "eng",
56				},
57				contents: "Google.com\n",
58			},
59		},
60	},
61	// The truncated test file was produced using these commands:
62	//   dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
63	//   tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
64	&writerTest{
65		file: "testdata/writer-big.tar",
66		entries: []*writerTestEntry{
67			&writerTestEntry{
68				header: &Header{
69					Name: "tmp/16gig.txt",
70					Mode: 0640,
71					Uid: 73025,
72					Gid: 5000,
73					Size: 16 << 30,
74					Mtime: 1254699560,
75					Typeflag: '0',
76					Uname: "dsymonds",
77					Gname: "eng",
78				},
79				// no contents
80			},
81		},
82	},
83}
84
85type untarTest struct {
86	file string
87	headers []*Header
88}
89
90var untarTests = []*untarTest{
91	&untarTest{
92		file: "testdata/gnu.tar",
93		headers: []*Header{
94			&Header{
95				Name: "small.txt",
96				Mode: 0640,
97				Uid: 73025,
98				Gid: 5000,
99				Size: 5,
100				Mtime: 1244428340,
101				Typeflag: '0',
102				Uname: "dsymonds",
103				Gname: "eng",
104			},
105			&Header{
106				Name: "small2.txt",
107				Mode: 0640,
108				Uid: 73025,
109				Gid: 5000,
110				Size: 11,
111				Mtime: 1244436044,
112				Typeflag: '0',
113				Uname: "dsymonds",
114				Gname: "eng",
115			},
116		},
117	},
118	&untarTest{
119		file: "testdata/star.tar",
120		headers: []*Header{
121			&Header{
122				Name: "small.txt",
123				Mode: 0640,
124				Uid: 73025,
125				Gid: 5000,
126				Size: 5,
127				Mtime: 1244592783,
128				Typeflag: '0',
129				Uname: "dsymonds",
130				Gname: "eng",
131				Atime: 1244592783,
132				Ctime: 1244592783,
133			},
134			&Header{
135				Name: "small2.txt",
136				Mode: 0640,
137				Uid: 73025,
138				Gid: 5000,
139				Size: 11,
140				Mtime: 1244592783,
141				Typeflag: '0',
142				Uname: "dsymonds",
143				Gname: "eng",
144				Atime: 1244592783,
145				Ctime: 1244592783,
146			},
147		},
148	},
149	&untarTest{
150		file: "testdata/v7.tar",
151		headers: []*Header{
152			&Header{
153				Name: "small.txt",
154				Mode: 0444,
155				Uid: 73025,
156				Gid: 5000,
157				Size: 5,
158				Mtime: 1244593104,
159				Typeflag: '\x00',
160			},
161			&Header{
162				Name: "small2.txt",
163				Mode: 0444,
164				Uid: 73025,
165				Gid: 5000,
166				Size: 11,
167				Mtime: 1244593104,
168				Typeflag: '\x00',
169			},
170		},
171	},
172}
173
174var facts = map[int] string {
175	0: "1",
176	1: "1",
177	2: "2",
178	10: "3628800",
179	20: "2432902008176640000",
180	100: "933262154439441526816992388562667004907159682643816214685929" +
181		"638952175999932299156089414639761565182862536979208272237582" +
182		"51185210916864000000000000000000000000",
183}
184
185func usage() {
186	fmt.Fprintf(os.Stderr,
187		// TODO(gri): the 2nd string of this string list should not be indented
188		"usage: godoc package [name ...]\n" +
189		"	godoc -http=:6060\n")
190	flag.PrintDefaults()
191	os.Exit(2)
192}
193
194func TestReader(t *testing.T) {
195testLoop:
196	for i, test := range untarTests {
197		f, err := os.Open(test.file, os.O_RDONLY, 0444)
198		if err != nil {
199			t.Errorf("test %d: Unexpected error: %v", i, err)
200			continue
201		}
202		tr := NewReader(f)
203		for j, header := range test.headers {
204			hdr, err := tr.Next()
205			if err != nil || hdr == nil {
206				t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err)
207				f.Close()
208				continue testLoop
209			}
210			if !reflect.DeepEqual(hdr, header) {
211				t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
212					 i, j, *hdr, *header)
213			}
214		}
215		hdr, err := tr.Next()
216		if hdr != nil || err != nil {
217			t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, err)
218		}
219		f.Close()
220	}
221}
222
223// Respect line breaks in function calls.
224func _() {
225	f(x)
226	f(x,
227	  x)
228	f(x,
229	  x,
230	)
231	f(
232	  x,
233	  x)
234	f(
235	  x,
236	  x,
237	)
238}
239
240// Respect line breaks in function declarations.
241func _(x T) {}
242func _(x T,
243       y T) {}
244func _(x T,
245       y T,
246) {}
247func _(
248       x T,
249       y T) {}
250func _(
251       x T,
252       y T,
253) {}
254
255// Example from issue 2597.
256func ManageStatus0(
257	in <-chan *Status,
258	req <-chan Request,
259	stat chan<- *TargetInfo,
260	TargetHistorySize int) {
261}
262
263func ManageStatus1(
264	in <-chan *Status,
265	req <-chan Request,
266	stat chan<- *TargetInfo,
267	TargetHistorySize int,
268) {
269}
270
271// There should be exactly one linebreak after this comment.
272