[dump_breapad_symbols] use tarutil for Tar archive creation.
Delete main_test.go since it no longer adds value.
Change-Id: Ifab10e4f72c3d2bb723f8b6d9ed1114dfd4fddf4
diff --git a/cmd/dump_breakpad_symbols/main.go b/cmd/dump_breakpad_symbols/main.go
index 1b1eb87..a239786 100755
--- a/cmd/dump_breakpad_symbols/main.go
+++ b/cmd/dump_breakpad_symbols/main.go
@@ -15,7 +15,6 @@
"flag"
"fmt"
"io"
- "io/ioutil"
"log"
"os"
"os/exec"
@@ -25,6 +24,7 @@
"fuchsia.googlesource.com/tools/breakpad"
"fuchsia.googlesource.com/tools/elflib"
+ "fuchsia.googlesource.com/tools/tarutil"
)
const usage = `usage: dump_breakpad_symbols [options] file1 file2 ... fileN
@@ -67,12 +67,6 @@
tarFilepath string
)
-// ExecDumpSyms runs the beakpad `dump_syms` command and returns the output.
-type ExecDumpSyms = func(args []string) ([]byte, error)
-
-// CreateFile returns an io.ReadWriteCloser for the file at the given path.
-type CreateFile = func(path string) (io.ReadWriteCloser, error)
-
func init() {
flag.Usage = func() {
fmt.Fprint(os.Stderr, usage)
@@ -94,15 +88,6 @@
}
func execute(ctx context.Context) error {
- // Callback to run breakpad `dump_syms` command.
- execDumpSyms := func(args []string) ([]byte, error) {
- return exec.Command(dumpSymsPath, args...).Output()
- }
-
- // Callback to create new files.
- createFile := func(path string) (io.ReadWriteCloser, error) {
- return os.Create(path)
- }
// Open the input files for reading. In practice there are very few files,
// so it's fine to open them all at once.
var inputReaders []io.Reader
@@ -117,7 +102,7 @@
}
// Process the IDsFiles.
- summary := processIdsFiles(inputReaders, outdir, execDumpSyms, createFile)
+ summary := processIdsFiles(inputReaders, outdir)
// Write the Ninja dep file.
depfile := depfile{outputPath: tarFilepath, inputPaths: inputPaths}
@@ -133,22 +118,29 @@
return fmt.Errorf("wrote 0 bytes to %q", depFilepath)
}
- // Create and open tarball.
- tarFile, err := os.Create(tarFilepath)
+ // Write the tar archive containing all symbol files.
+ tarfd, err := os.Create(tarFilepath)
if err != nil {
- return fmt.Errorf("could not create file %s: %v", tarFilepath, err)
+ return fmt.Errorf("failed to create %q: %v", tarFilepath, err)
}
- defer tarFile.Close()
-
- // Collect Breakpad symbol files generated by the build to a tarball.
- if err := writeTarball(tarFile, summary, outdir); err != nil {
- return fmt.Errorf("failed to generate tarball %s: %v", tarFilepath, err)
+ gzw := gzip.NewWriter(tarfd)
+ defer gzw.Close()
+ tw := tar.NewWriter(gzw)
+ for _, fp := range summary {
+ fd, err := os.Open(fp)
+ if err != nil {
+ return err
+ }
+ defer fd.Close()
+ if err := tarutil.TarReader(tw, fd, fp); err != nil {
+ return fmt.Errorf("failed to archive %q: %v", fp, err)
+ }
}
return nil
}
// processIdsFiles dumps symbol data for each executable in a set of ids files.
-func processIdsFiles(idsFiles []io.Reader, outdir string, execDumpSyms ExecDumpSyms, createFile CreateFile) map[string]string {
+func processIdsFiles(idsFiles []io.Reader, outdir string) map[string]string {
// Binary paths we've already seen. Duplicates are skipped.
visited := make(map[string]bool)
binaryToSymbolFile := make(map[string]string)
@@ -173,7 +165,7 @@
// Record that we've seen this binary path.
visited[binaryPath] = true
- symbolFilepath, err := generateSymbolFile(binaryPath, createFile, execDumpSyms)
+ symbolFilepath, err := generateSymbolFile(binaryPath)
if err != nil {
log.Println(err)
continue
@@ -187,9 +179,9 @@
return binaryToSymbolFile
}
-func generateSymbolFile(path string, createFile CreateFile, execDumpSyms ExecDumpSyms) (outputPath string, err error) {
+func generateSymbolFile(path string) (outputPath string, err error) {
outputPath = createSymbolFilepath(outdir, path)
- output, err := execDumpSyms([]string{path})
+ output, err := exec.Command(dumpSymsPath, path).Output()
if err != nil {
return "", fmt.Errorf("failed to generate symbol data for %s: %v", path, err)
}
@@ -217,7 +209,7 @@
// Ensure the module section specifies this is a Fuchsia binary instead of Linux
// binary, which is the default for the dump_syms tool.
symbolFile.ModuleSection.OS = "Fuchsia"
- symbolFd, err := createFile(outputPath)
+ symbolFd, err := os.Create(outputPath)
if err != nil {
return "", fmt.Errorf("failed to create symbol file %s: %v", outputPath, err)
}
@@ -287,38 +279,3 @@
return absPath
}
-
-func writeTarball(w io.Writer, summary map[string]string, parentDir string) error {
- gw := gzip.NewWriter(w)
- defer gw.Close()
- // Create a tarWriter to perform the tarring task.
- tw := tar.NewWriter(gw)
- defer tw.Close()
-
- // Iterate through the summary file, writting each symbol file to the tarball buffer.
- for _, file := range summary {
- data, err := ioutil.ReadFile(file)
- if err != nil {
- return fmt.Errorf("failed to read the symbol data file %s: %v", file, err)
- }
-
- // Add a file with its relative path instead of absolute path to the tarball.
- rel, err := filepath.Rel(parentDir, file)
- if err != nil {
- return fmt.Errorf("failed to get the relative path from %s to %s: %v", parentDir, file, err)
- }
- hdr := &tar.Header{
- Name: rel,
- Mode: 0600,
- Size: int64(len(data)),
- }
- if err := tw.WriteHeader(hdr); err != nil {
- return fmt.Errorf("failed to write header for tarball: %v", err)
- }
- if _, err := tw.Write([]byte(data)); err != nil {
- return fmt.Errorf("failed to write contents for tarball: %v", err)
- }
- }
-
- return nil
-}
diff --git a/cmd/dump_breakpad_symbols/main_test.go b/cmd/dump_breakpad_symbols/main_test.go
deleted file mode 100644
index a382c1b..0000000
--- a/cmd/dump_breakpad_symbols/main_test.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-package main
-
-import (
- "archive/tar"
- "bytes"
- "compress/gzip"
- "fmt"
- "io"
- "io/ioutil"
- "testing"
-)
-
-// FakeFile is a file-like io.ReadWriteCloser for testing.
-type FakeFile struct {
- path string
- *bytes.Buffer
-}
-
-// The filepath of this FakeFile.
-func (f *FakeFile) Name() string {
- return f.path
-}
-
-// Close implements io.WriteCloser.
-func (f *FakeFile) Close() error {
- // Noop
- return nil
-}
-
-func NewFakeFile(path string, contents string) *FakeFile {
- return &FakeFile{
- Buffer: bytes.NewBuffer([]byte(contents)),
- path: path,
- }
-}
-
-func checkTarContents(contents []byte, expectedTarFileContents map[string][]byte) error {
- var contentsBuffer bytes.Buffer
- contentsBuffer.Write(contents)
- // Open and iterate through the files in the archive.
- gzf, err := gzip.NewReader(&contentsBuffer)
- if err != nil {
- return fmt.Errorf("reading tarball failed, %v", err)
- }
-
- tr := tar.NewReader(gzf)
- actualTarFileContents := make(map[string][]byte)
- for {
- hdr, err := tr.Next()
- if err == io.EOF {
- break // End of archive.
- }
- if err != nil {
- return fmt.Errorf("reading tarball failed, %v", err)
- }
- actualData := make([]byte, hdr.Size)
- if _, err := tr.Read(actualData); err != nil && err != io.EOF {
- return fmt.Errorf("reading tarball data failed, %v", err)
- }
- actualTarFileContents[hdr.Name] = actualData
- }
-
- for expectedFileName, expectedFileContents := range expectedTarFileContents {
- actualFileContents, exist := actualTarFileContents[expectedFileName]
- if !exist {
- return fmt.Errorf("expecting %s to be found in tarball but not found", expectedFileName)
- }
- if !bytes.Equal(actualFileContents, expectedFileContents) {
- return fmt.Errorf("expecting contents in %s to be found same but not", expectedFileName)
- }
- }
- return nil
-}
-
-func TestRunCommand(t *testing.T) {
- // Expects dump_breakpad_symbols to produce the specified summary and
- // ninja depfile from the given input sources.
- expectOutputs := func(t *testing.T, inputs []*FakeFile, expectedDepFile string, expectedTarFileContents map[string][]byte, outDir string) {
- tarFile := NewFakeFile("breakpad_symbols.tar.gz", "")
-
- // Callback to mock executing the breakpad dump_syms binary.
- execDumpSyms := func(args []string) ([]byte, error) {
- return []byte("FAKE_SYMBOL_DATA_LINE_1\nFAKE_SYMBOL_DATA_LINE_2"), nil
- }
-
- // Callback to perform file I/O.
- createFile := func(path string) (io.ReadWriteCloser, error) {
- return NewFakeFile(path, ""), nil
- }
-
- // Convert input files from `[]FakeFile` to `[]io.Reader`.
- fileReaders := make([]io.Reader, len(inputs))
- for i := range inputs {
- fileReaders[i] = inputs[i]
- }
-
- // Process the input files.
- summary := processIdsFiles(fileReaders, outDir, execDumpSyms, createFile)
-
- // Write the tarball file.
- if err := writeTarball(tarFile, summary, outDir); err != nil {
- t.Fatalf("failed to write tarball %s: %v", tarFile.Name(), err)
- }
-
- // Extract input filepaths.
- inputPaths := make([]string, len(inputs))
- for i := range inputs {
- inputPaths[i] = inputs[i].Name()
- }
-
- // Expect matching tarball.
- actualTarFile, err := ioutil.ReadAll(tarFile)
- if err != nil {
- t.Fatal(err)
- }
- if err := checkTarContents(actualTarFile, expectedTarFileContents); err != nil {
- t.Fatalf("%v", err)
- }
- }
-
- t.Run("should produce an emtpy summary if no data is provided", func(t *testing.T) {
- inputSources := []*FakeFile{
- NewFakeFile("idsA.txt", ""),
- NewFakeFile("idsB.txt", ""),
- }
- expectedDepFile := fmt.Sprintf("breakpad_symbols.tar.gz: %s %s\n", "idsA.txt", "idsB.txt")
- expectOutputs(t, inputSources, expectedDepFile, make(map[string][]byte), "out/")
- })
-}
-
-// No tests to verify the output of dump_syms. Assume it does the right thing.