2018-11-25 18:19:03 +00:00
|
|
|
// Copyright (c) 2018, Google Inc.
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice appear in all copies.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
|
|
|
|
|
|
package ar
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"flag"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
var testDataDir = flag.String("testdata", "testdata", "The path to the test data directory.")
|
|
|
|
|
|
|
|
type arTest struct {
|
|
|
|
name string
|
|
|
|
in string
|
2018-11-25 21:51:57 +00:00
|
|
|
out map[string]string
|
2018-11-25 18:19:03 +00:00
|
|
|
// allowPadding is true if the contents may have trailing newlines at end.
|
|
|
|
// On macOS, ar calls ranlib which pads all inputs up to eight bytes with
|
|
|
|
// newlines. Unlike ar's native padding up to two bytes, this padding is
|
|
|
|
// included in the size field, so it is not removed when decoding.
|
|
|
|
allowPadding bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (test *arTest) Path(file string) string {
|
|
|
|
return filepath.Join(*testDataDir, test.name, file)
|
|
|
|
}
|
|
|
|
|
|
|
|
func removeTrailingNewlines(in []byte) []byte {
|
|
|
|
for len(in) > 0 && in[len(in)-1] == '\n' {
|
|
|
|
in = in[:len(in)-1]
|
|
|
|
}
|
|
|
|
return in
|
|
|
|
}
|
|
|
|
|
|
|
|
var arTests = []arTest{
|
2018-11-25 21:51:57 +00:00
|
|
|
{
|
|
|
|
"linux",
|
|
|
|
"libsample.a",
|
|
|
|
map[string]string{
|
|
|
|
"foo.c.o": "foo.c.o",
|
|
|
|
"bar.cc.o": "bar.cc.o",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mac",
|
|
|
|
"libsample.a",
|
|
|
|
map[string]string{
|
|
|
|
"foo.c.o": "foo.c.o",
|
|
|
|
"bar.cc.o": "bar.cc.o",
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"windows",
|
|
|
|
"sample.lib",
|
|
|
|
map[string]string{
|
|
|
|
"CMakeFiles\\sample.dir\\foo.c.obj": "foo.c.obj",
|
|
|
|
"CMakeFiles\\sample.dir\\bar.cc.obj": "bar.cc.obj",
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
2018-11-25 18:19:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAR(t *testing.T) {
|
|
|
|
for _, test := range arTests {
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
|
|
in, err := os.Open(test.Path(test.in))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("opening input failed: %s", err)
|
|
|
|
}
|
|
|
|
defer in.Close()
|
|
|
|
|
|
|
|
ret, err := ParseAR(in)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("reading input failed: %s", err)
|
|
|
|
}
|
|
|
|
|
2018-11-25 21:51:57 +00:00
|
|
|
for file, contentsPath := range test.out {
|
|
|
|
expected, err := ioutil.ReadFile(test.Path(contentsPath))
|
2018-11-25 18:19:03 +00:00
|
|
|
if err != nil {
|
2018-11-25 21:51:57 +00:00
|
|
|
t.Fatalf("error reading %s: %s", contentsPath, err)
|
2018-11-25 18:19:03 +00:00
|
|
|
}
|
|
|
|
got, ok := ret[file]
|
|
|
|
if test.allowPadding {
|
|
|
|
got = removeTrailingNewlines(got)
|
|
|
|
expected = removeTrailingNewlines(got)
|
|
|
|
}
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("file %s missing from output", file)
|
|
|
|
} else if !bytes.Equal(got, expected) {
|
|
|
|
t.Errorf("contents for file %s did not match", file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for file, _ := range ret {
|
2018-11-25 21:51:57 +00:00
|
|
|
if _, ok := test.out[file]; !ok {
|
2018-11-25 18:19:03 +00:00
|
|
|
t.Errorf("output contained unexpected file %q", file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|