blob: a382c1b6d5e89fd7328e5a99b431b3a0d4928b83 [file] [log] [blame]
// 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.