vendor tsgo
This commit is contained in:
153
tools/tsgo/internal/execute/build/graph_test.go
Normal file
153
tools/tsgo/internal/execute/build/graph_test.go
Normal file
@@ -0,0 +1,153 @@
|
||||
package build_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/core"
|
||||
"github.com/microsoft/typescript-go/internal/execute/build"
|
||||
"github.com/microsoft/typescript-go/internal/execute/tsctests"
|
||||
"github.com/microsoft/typescript-go/internal/tsoptions"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestBuildOrderGenerator(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []*buildOrderTestCase{
|
||||
{"specify two roots", []string{"A", "G"}, []string{"D", "E", "C", "B", "A", "G"}, false},
|
||||
{"multiple parts of the same graph in various orders", []string{"A"}, []string{"D", "E", "C", "B", "A"}, false},
|
||||
{"multiple parts of the same graph in various orders", []string{"A", "C", "D"}, []string{"D", "E", "C", "B", "A"}, false},
|
||||
{"multiple parts of the same graph in various orders", []string{"D", "C", "A"}, []string{"D", "E", "C", "B", "A"}, false},
|
||||
{"other orderings", []string{"F"}, []string{"E", "F"}, false},
|
||||
{"other orderings", []string{"E"}, []string{"E"}, false},
|
||||
{"other orderings", []string{"F", "C", "A"}, []string{"E", "F", "D", "C", "B", "A"}, false},
|
||||
{"returns circular order", []string{"H"}, []string{"E", "J", "I", "H"}, true},
|
||||
{"returns circular order", []string{"A", "H"}, []string{"D", "E", "C", "B", "A", "J", "I", "H"}, true},
|
||||
}
|
||||
for _, testcase := range testCases {
|
||||
testcase.run(t)
|
||||
}
|
||||
}
|
||||
|
||||
type buildOrderTestCase struct {
|
||||
name string
|
||||
projects []string
|
||||
expected []string
|
||||
circular bool
|
||||
}
|
||||
|
||||
func (b *buildOrderTestCase) configName(project string) string {
|
||||
return fmt.Sprintf("/home/src/workspaces/project/%s/tsconfig.json", project)
|
||||
}
|
||||
|
||||
func (b *buildOrderTestCase) projectName(config string) string {
|
||||
str := strings.TrimPrefix(config, "/home/src/workspaces/project/")
|
||||
str = strings.TrimSuffix(str, "/tsconfig.json")
|
||||
return str
|
||||
}
|
||||
|
||||
func (b *buildOrderTestCase) run(t *testing.T) {
|
||||
t.Helper()
|
||||
t.Run(b.name+" - "+strings.Join(b.projects, ","), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
files := make(map[string]any)
|
||||
deps := map[string][]string{
|
||||
"A": {"B", "C"},
|
||||
"B": {"C", "D"},
|
||||
"C": {"D", "E"},
|
||||
"F": {"E"},
|
||||
"H": {"I"},
|
||||
"I": {"J"},
|
||||
"J": {"H", "E"},
|
||||
}
|
||||
reverseDeps := map[string][]string{}
|
||||
for project, deps := range deps {
|
||||
for _, dep := range deps {
|
||||
reverseDeps[dep] = append(reverseDeps[dep], project)
|
||||
}
|
||||
}
|
||||
verifyDeps := func(orchestrator *build.Orchestrator, buildOrder []string, hasDownStream bool) {
|
||||
for index, project := range buildOrder {
|
||||
upstream := core.Map(orchestrator.Upstream(b.configName(project)), b.projectName)
|
||||
expectedUpstream := deps[project]
|
||||
assert.Assert(t, len(upstream) <= len(expectedUpstream), fmt.Sprintf("Expected upstream for %s to be at most %d, got %d", project, len(expectedUpstream), len(upstream)))
|
||||
for _, expected := range expectedUpstream {
|
||||
if slices.Contains(buildOrder[:index], expected) {
|
||||
assert.Assert(t, slices.Contains(upstream, expected), fmt.Sprintf("Expected upstream for %s to contain %s", project, expected))
|
||||
} else {
|
||||
assert.Assert(t, !slices.Contains(upstream, expected), fmt.Sprintf("Expected upstream for %s to not contain %s", project, expected))
|
||||
}
|
||||
}
|
||||
|
||||
downstream := core.Map(orchestrator.Downstream(b.configName(project)), b.projectName)
|
||||
expectedDownstream := core.IfElse(hasDownStream, reverseDeps[project], nil)
|
||||
assert.Assert(t, len(downstream) <= len(expectedDownstream), fmt.Sprintf("Expected downstream for %s to be at most %d, got %d", project, len(expectedDownstream), len(downstream)))
|
||||
for _, expected := range expectedDownstream {
|
||||
if slices.Contains(buildOrder[index+1:], expected) {
|
||||
assert.Assert(t, slices.Contains(downstream, expected), fmt.Sprintf("Expected downstream for %s to contain %s", project, expected))
|
||||
} else {
|
||||
assert.Assert(t, !slices.Contains(downstream, expected), fmt.Sprintf("Expected downstream for %s to not contain %s", project, expected))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, project := range []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"} {
|
||||
files[fmt.Sprintf("/home/src/workspaces/project/%s/%s.ts", project, project)] = "export {}"
|
||||
referencesStr := ""
|
||||
if deps, ok := deps[project]; ok {
|
||||
referencesStr = fmt.Sprintf(`, "references": [%s]`, strings.Join(core.Map(deps, func(dep string) string {
|
||||
return fmt.Sprintf(`{ "path": "../%s" }`, dep)
|
||||
}), ","))
|
||||
}
|
||||
files[b.configName(project)] = fmt.Sprintf(`{
|
||||
"compilerOptions": { "composite": true },
|
||||
"files": ["./%s.ts"],
|
||||
%s
|
||||
}`, project, referencesStr)
|
||||
}
|
||||
|
||||
sys := tsctests.NewTscSystem(files, true, "/home/src/workspaces/project")
|
||||
args := append([]string{"--build", "--dry"}, b.projects...)
|
||||
buildCommand := tsoptions.ParseBuildCommandLine(args, sys)
|
||||
orchestrator := build.NewOrchestrator(build.Options{
|
||||
Sys: sys,
|
||||
Command: buildCommand,
|
||||
})
|
||||
orchestrator.GenerateGraph(nil)
|
||||
buildOrder := core.Map(orchestrator.Order(), b.projectName)
|
||||
assert.DeepEqual(t, buildOrder, b.expected)
|
||||
verifyDeps(orchestrator, buildOrder, false)
|
||||
|
||||
if !b.circular {
|
||||
for project, projectDeps := range deps {
|
||||
child := b.configName(project)
|
||||
childIndex := slices.Index(buildOrder, child)
|
||||
if childIndex == -1 {
|
||||
continue
|
||||
}
|
||||
for _, dep := range projectDeps {
|
||||
parent := b.configName(dep)
|
||||
parentIndex := slices.Index(buildOrder, parent)
|
||||
|
||||
assert.Assert(t, childIndex > parentIndex, fmt.Sprintf("Expecting child %s to be built after parent %s", project, dep))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
orchestrator.GenerateGraphReusingOldTasks()
|
||||
buildOrder2 := core.Map(orchestrator.Order(), b.projectName)
|
||||
assert.DeepEqual(t, buildOrder2, b.expected)
|
||||
|
||||
argsWatch := append([]string{"--build", "--watch"}, b.projects...)
|
||||
buildCommandWatch := tsoptions.ParseBuildCommandLine(argsWatch, sys)
|
||||
orchestrator = build.NewOrchestrator(build.Options{
|
||||
Sys: sys,
|
||||
Command: buildCommandWatch,
|
||||
})
|
||||
orchestrator.GenerateGraph(nil)
|
||||
buildOrder3 := core.Map(orchestrator.Order(), b.projectName)
|
||||
verifyDeps(orchestrator, buildOrder3, true)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user