blob: 73d731e2e1b77cd2d761f56ce7731560bfcc8ecc [file] [log] [blame]
// Copyright 2020 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 (
"bytes"
"encoding/json"
"io/ioutil"
"net/url"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"time"
"go.fuchsia.dev/fuchsia/tools/testing/runtests"
"go.fuchsia.dev/fuchsia/tools/testing/tap"
"go.fuchsia.dev/fuchsia/tools/testing/testrunner"
)
func TestRecordingOfOutputs(t *testing.T) {
start := time.Unix(0, 0)
results := []testrunner.TestResult{
{
Name: "fuchsia-pkg://foo#test_a",
GNLabel: "//a/b/c:test_a(//toolchain)",
Result: runtests.TestFailure,
StartTime: start,
EndTime: start.Add(5 * time.Millisecond),
DataSinks: runtests.DataSinkReference{
Sinks: runtests.DataSinkMap{
"sinks": []runtests.DataSink{
{
Name: "SINK_A1",
File: "sink_a1.txt",
},
{
Name: "SINK_A2",
File: "sink_a2.txt",
},
}},
},
Stdio: []byte("STDOUT_A"),
},
{
Name: "test_b",
GNLabel: "//a/b/c:test_b(//toolchain)",
Result: runtests.TestSuccess,
StartTime: start,
EndTime: start.Add(10 * time.Millisecond),
Stdio: []byte("STDERR_B"),
},
}
dataDir := t.TempDir()
outDir := filepath.Join(dataDir, "out")
var buf bytes.Buffer
producer := tap.NewProducer(&buf)
producer.Plan(len(results))
o, err := createTestOutputs(producer, outDir)
if err != nil {
t.Fatalf("failed to create a test outputs object: %v", err)
}
defer o.Close()
outputFileA := filepath.Join(url.PathEscape("fuchsia-pkg//foo#test_a"), "0", "stdout-and-stderr.txt")
outputFileB := filepath.Join("test_b", "0", "stdout-and-stderr.txt")
expectedSummary := runtests.TestSummary{
Tests: []runtests.TestDetails{{
Name: "fuchsia-pkg://foo#test_a",
GNLabel: "//a/b/c:test_a(//toolchain)",
OutputFiles: []string{outputFileA},
Result: runtests.TestFailure,
StartTime: start,
DurationMillis: 5,
DataSinks: runtests.DataSinkMap{
"sinks": []runtests.DataSink{
{
Name: "SINK_A1",
File: "sink_a1.txt",
},
{
Name: "SINK_A2",
File: "sink_a2.txt",
},
},
},
}, {
Name: "test_b",
GNLabel: "//a/b/c:test_b(//toolchain)",
OutputFiles: []string{outputFileB},
Result: runtests.TestSuccess,
StartTime: start,
DurationMillis: 10,
// The data sinks will be added through a call to updateDataSinks().
DataSinks: runtests.DataSinkMap{
"sinks": []runtests.DataSink{
{
Name: "SINK_B",
File: "other_dir/sink_b.txt",
},
},
},
}},
}
summaryBytes, err := json.Marshal(&expectedSummary)
if err != nil {
t.Fatalf("failed to marshal expected summary: %v", err)
}
expectedSinks := map[string]string{
"sink_a1.txt": "SINK_A1",
"sink_a2.txt": "SINK_A2",
"sink_b.txt": "SINK_B",
}
// Populate all of the expected output files.
expectedContents := map[string]string{
outputFileA: "STDOUT_A",
outputFileB: "STDERR_B",
"summary.json": string(summaryBytes),
}
for name, content := range expectedSinks {
// Add sinks to expectedContents.
expectedContents[name] = content
path := filepath.Join(o.outDir, name)
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o700); err != nil {
t.Fatalf("failed to make directory %q for outputs: %v", dir, err)
}
if err := ioutil.WriteFile(path, []byte(content), 0o400); err != nil {
t.Fatalf("failed to write contents %q to file %q: %v", content, name, err)
}
}
for _, result := range results {
if err := o.record(result); err != nil {
t.Fatalf("failed to record result of %q: %v", result.Name, err)
}
}
o.updateDataSinks(map[string]runtests.DataSinkReference{
"test_b": {
Sinks: runtests.DataSinkMap{
"sinks": []runtests.DataSink{
{
Name: "SINK_B",
File: "sink_b.txt",
},
}},
},
}, "other_dir")
o.Close()
// Verify that the summary as expected.
actualSummary := o.summary
if !reflect.DeepEqual(actualSummary, expectedSummary) {
t.Errorf("unexpected summary:\nexpected: %v\nactual: %v\n", expectedSummary, actualSummary)
}
// Verify that the TAP output is as expected.
expectedTAPOutput := strings.TrimSpace(`
TAP version 13
1..2
not ok 1 fuchsia-pkg://foo#test_a (5ms)
ok 2 test_b (10ms)
`)
actualTAPOutput := strings.TrimSpace(buf.String())
if actualTAPOutput != expectedTAPOutput {
t.Errorf("unexpected TAP output:\nexpected: %v\nactual: %v\n", expectedTAPOutput, actualTAPOutput)
}
// Verify that the outDir's contents are as expected.
outDirContents := make(map[string]string)
for name := range expectedContents {
path := filepath.Join(outDir, name)
b, err := ioutil.ReadFile(path)
if err != nil {
t.Errorf("failed to read file %q in out dir: %v", path, err)
}
outDirContents[name] = string(b)
}
if !reflect.DeepEqual(expectedContents, outDirContents) {
t.Fatalf("unexpected contents from out dir:\nexpected: %#v\nactual: %#v\n", expectedContents, outDirContents)
}
}