1// Copyright (c) 2011 Mikkel Krautz
2// The use of this source code is goverened by a BSD-style
3// license that can be found in the LICENSE-file.
4
5package ar
6
7import (
8	"bytes"
9	"io"
10	"os"
11	"testing"
12)
13
14var fbsd82Archive []archiveTest = []archiveTest{
15	{
16		&Header{
17			Name:  "/",
18			Mode:  0,
19			Mtime: 1315607407,
20			Uid:   0,
21			Gid:   0,
22			Size:  4,
23		},
24		[]byte{0x0, 0x0, 0x0, 0x0},
25	},
26	{
27		&Header{
28			Name:  "a",
29			Mode:  0100644,
30			Mtime: 1315607373,
31			Uid:   1001,
32			Gid:   1001,
33			Size:  2,
34		},
35		[]byte{'a', '\n'},
36	},
37	{
38		&Header{
39			Name:  "b",
40			Mode:  0100644,
41			Mtime: 1315607374,
42			Uid:   1001,
43			Gid:   1001,
44			Size:  2,
45		},
46		[]byte{'b', '\n'},
47	},
48	{
49		&Header{
50			Name:  "c",
51			Mode:  0100644,
52			Mtime: 1315607376,
53			Uid:   1001,
54			Gid:   1001,
55			Size:  2,
56		},
57		[]byte{'c', '\n'},
58	},
59}
60
61var lionArchive []archiveTest = []archiveTest{
62	{
63		&Header{
64			Name:  "__.SYMDEF SORTED",
65			Mode:  0100644,
66			Mtime: 1315593186,
67			Uid:   501,
68			Gid:   20,
69			Size:  8,
70		},
71		[]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
72	},
73	{
74		&Header{
75			Name:  "a",
76			Mode:  0100644,
77			Mtime: 1315593158,
78			Uid:   501,
79			Gid:   20,
80			Size:  8,
81		},
82		[]byte("a\n\n\n\n\n\n\n"),
83	},
84	{
85		&Header{
86			Name:  "b",
87			Mode:  0100644,
88			Mtime: 1315593165,
89			Uid:   501,
90			Gid:   20,
91			Size:  8,
92		},
93		[]byte("b\n\n\n\n\n\n\n"),
94	},
95	{
96		&Header{
97			Name:  "c",
98			Mode:  0100644,
99			Mtime: 1315593166,
100			Uid:   501,
101			Gid:   20,
102			Size:  8,
103		},
104		[]byte("c\n\n\n\n\n\n\n"),
105	},
106}
107
108var linuxArchive []archiveTest = []archiveTest{
109	{
110		&Header{
111			Name:  "0",
112			Mode:  0100770,
113			Mtime: 1369126995,
114			Uid:   0,
115			Gid:   1001,
116			Size:  0,
117		},
118		[]byte{},
119	},
120	{
121		&Header{
122			Name:  "1",
123			Mode:  0100770,
124			Mtime: 1369127013,
125			Uid:   0,
126			Gid:   1001,
127			Size:  1,
128		},
129		[]byte("a"),
130	},
131	{
132		&Header{
133			Name:  "2",
134			Mode:  0100770,
135			Mtime: 1369127016,
136			Uid:   0,
137			Gid:   1001,
138			Size:  2,
139		},
140		[]byte("ab"),
141	},
142	{
143		&Header{
144			Name:  "3",
145			Mode:  0100770,
146			Mtime: 1369127019,
147			Uid:   0,
148			Gid:   1001,
149			Size:  3,
150		},
151		[]byte("abc"),
152	},
153	{
154		&Header{
155			Name:  "long-long-file-name",
156			Mode:  0100770,
157			Mtime: 1369127028,
158			Uid:   0,
159			Gid:   1001,
160			Size:  25,
161		},
162		[]byte("Gopher's name is Gordon.\n"),
163	},
164}
165
166func read(t *testing.T, r io.Reader, testArchive []archiveTest, readBody bool) {
167	ar := NewReader(r)
168	for _, testEntry := range testArchive {
169		hdr, err := ar.Next()
170		if err != nil {
171			t.Fatal(err)
172		}
173		if !headerCmp(hdr, testEntry.hdr) {
174			t.Fatalf("header mismatch:\nread = %+v\norig = %+v", hdr, testEntry.hdr)
175		}
176		if readBody {
177			fbuf := make([]byte, hdr.Size)
178			_, err = io.ReadFull(ar, fbuf)
179			if err != nil {
180				t.Fatal(err)
181			}
182			if !bytes.Equal(fbuf, testEntry.data) {
183				t.Fatalf("data mismatch\nread = %v\norig = %v", fbuf, testEntry.data)
184			}
185		}
186	}
187
188	_, err := ar.Next()
189	if err != io.EOF {
190		t.Fatalf("expected EOF, got %v", err)
191	}
192}
193
194func testRead(t *testing.T, r io.ReadSeeker, testArchive []archiveTest) {
195	read(t, r, testArchive, true)
196	r.Seek(0, 0)
197	read(t, r, testArchive, false)
198}
199
200// Test the we can correctly read and parse a FreeBSD 8.2 generated ar file.
201func TestReadFreeBSD82LibArchive(t *testing.T) {
202	f, err := os.Open("testdata/test-bsd-freebsd82-libarchive.ar")
203	if err != nil {
204		t.Fatal(err)
205	}
206	defer f.Close()
207	testRead(t, f, fbsd82Archive)
208}
209
210// Test the we can correctly read and parse a Mac OS X Lion generated ar file.
211// It is generated in the same way as the FreeBSD archive ahove, but ar on OS X
212// seems to pad the archived files with a lot of newlines.
213// Attempting to "ar x" the archive also reproduces the newlines in the extracted
214// files, so they are not a form of padding, but are intended to be there, somehow.
215func TestReadMacOSXLionOld(t *testing.T) {
216	f, err := os.Open("testdata/test-bsd-macosx.ar")
217	if err != nil {
218		t.Fatal(err)
219	}
220	defer f.Close()
221	testRead(t, f, lionArchive)
222}
223
224func TestReadLinux(t *testing.T) {
225	f, err := os.Open("testdata/test-gnu-linux.ar")
226	if err != nil {
227		t.Fatal(err)
228	}
229	defer f.Close()
230	testRead(t, f, linuxArchive)
231}
232