| // Copyright 2018 The BoringSSL Authors | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     https://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | package ar | 
 |  | 
 | import ( | 
 | 	"bytes" | 
 | 	"flag" | 
 | 	"os" | 
 | 	"path/filepath" | 
 | 	"testing" | 
 | ) | 
 |  | 
 | var testDataDir = flag.String("testdata", "testdata", "The path to the test data directory.") | 
 |  | 
 | type arTest struct { | 
 | 	name string | 
 | 	in   string | 
 | 	out  map[string]string | 
 | 	// 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{ | 
 | 	{ | 
 | 		"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, | 
 | 	}, | 
 | } | 
 |  | 
 | 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) | 
 | 			} | 
 |  | 
 | 			for file, contentsPath := range test.out { | 
 | 				expected, err := os.ReadFile(test.Path(contentsPath)) | 
 | 				if err != nil { | 
 | 					t.Fatalf("error reading %s: %s", contentsPath, err) | 
 | 				} | 
 | 				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 { | 
 | 				if _, ok := test.out[file]; !ok { | 
 | 					t.Errorf("output contained unexpected file %q", file) | 
 | 				} | 
 | 			} | 
 | 		}) | 
 | 	} | 
 | } |