blob: 0baddd6cc836de590dadd3da8284ab8915f7d64e [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 (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"go.fuchsia.dev/fuchsia/tools/build/ninjago/compdb"
"go.fuchsia.dev/fuchsia/tools/build/ninjago/ninjagraph"
"go.fuchsia.dev/fuchsia/tools/build/ninjago/ninjalog"
)
func TestJoin(t *testing.T) {
// Alaways create new copies of test edges so their memoized fields don't
// carry between tests.
edge1 := func() *ninjagraph.Edge { return &ninjagraph.Edge{Outputs: []int64{1}} }
edge2 := func() *ninjagraph.Edge { return &ninjagraph.Edge{Inputs: []int64{1}, Outputs: []int64{2}} }
edge3 := func() *ninjagraph.Edge { return &ninjagraph.Edge{Inputs: []int64{1}, Outputs: []int64{3}} }
for _, v := range []struct {
name string
artifacts artifacts
criticalPath bool
wantSteps []ninjalog.Step
}{
{
name: "empty",
},
{
name: "join compdb",
artifacts: artifacts{
steps: []ninjalog.Step{
{
Out: "a",
CmdHash: ninjalog.MurmurHash64A([]byte("touch a")),
},
{
Out: "b",
CmdHash: ninjalog.MurmurHash64A([]byte("touch b")),
},
{
Out: "c",
},
},
commands: []compdb.Command{
{Command: "touch a", Output: "a", Arguments: []string{"a arg"}},
{Command: "touch b"},
},
},
wantSteps: []ninjalog.Step{
{
Out: "a",
CmdHash: ninjalog.MurmurHash64A([]byte("touch a")),
Command: &compdb.Command{Command: "touch a", Output: "a", Arguments: []string{"a arg"}},
},
{
Out: "b",
CmdHash: ninjalog.MurmurHash64A([]byte("touch b")),
Command: &compdb.Command{Command: "touch b"},
},
{
Out: "c",
},
},
},
{
name: "join graph for critical path",
artifacts: artifacts{
steps: []ninjalog.Step{
{
Out: "1",
CmdHash: ninjalog.MurmurHash64A([]byte("touch 1")),
End: time.Second,
},
{
Out: "2",
Start: time.Second,
End: 10 * time.Second,
},
{
Out: "3",
Start: time.Second,
End: 2 * time.Second,
},
},
commands: []compdb.Command{
{Command: "touch 1"},
},
// 1 ------> 2 (critical path)
// \
// ---> 3
graph: ninjagraph.Graph{
Nodes: map[int64]*ninjagraph.Node{
1: {
ID: 1,
Path: "1",
In: edge1(),
Outs: []*ninjagraph.Edge{edge2(), edge3()},
},
2: {ID: 2, Path: "2", In: edge2()},
3: {ID: 3, Path: "3", In: edge3()},
},
Edges: []*ninjagraph.Edge{edge1(), edge2(), edge3()},
},
},
criticalPath: true,
wantSteps: []ninjalog.Step{
{
Out: "1",
End: time.Second,
CmdHash: ninjalog.MurmurHash64A([]byte("touch 1")),
Command: &compdb.Command{Command: "touch 1"},
OnCriticalPath: true,
Drag: time.Second,
},
{
Out: "2",
Start: time.Second,
End: 10 * time.Second,
OnCriticalPath: true,
Drag: 8 * time.Second,
},
{
Out: "3",
Start: time.Second,
End: 2 * time.Second,
TotalFloat: 8 * time.Second,
},
},
},
{
name: "missing step",
artifacts: artifacts{
// The graph is expecting a step to for edge3, but it's missing.
steps: []ninjalog.Step{{Out: "1"}, {Out: "2"}},
graph: ninjagraph.Graph{
Nodes: map[int64]*ninjagraph.Node{
1: {
ID: 1,
Path: "1",
In: edge1(),
Outs: []*ninjagraph.Edge{edge2(), edge3()},
},
2: {ID: 2, Path: "2", In: edge2()},
3: {ID: 3, Path: "3", In: edge3()},
},
Edges: []*ninjagraph.Edge{edge1(), edge2(), edge3()},
},
},
criticalPath: true,
wantSteps: []ninjalog.Step{
{Out: "1", OnCriticalPath: true},
{Out: "2", OnCriticalPath: true},
// edge3 is excluded because it has no step associated.
},
},
} {
t.Run(v.name, func(t *testing.T) {
got, err := join(v.artifacts, v.criticalPath)
if err != nil {
t.Fatalf("join(%+v, %t) failed: %v", v.artifacts, v.criticalPath, err)
}
if diff := cmp.Diff(v.wantSteps, got); diff != "" {
t.Fatalf("join(%+v, %t) got steps diff (-want, +got):\n%s", v.artifacts, v.criticalPath, diff)
}
})
}
}