202 lines
4.8 KiB
Go
202 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
stdlog "log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
"text/template"
|
|
"time"
|
|
|
|
"oss.terrastruct.com/d2/lib/log"
|
|
)
|
|
|
|
//go:embed template.html
|
|
var TEMPLATE_HTML string
|
|
|
|
type TemplateData struct {
|
|
Tests []TestItem
|
|
}
|
|
|
|
type TestItem struct {
|
|
Name string
|
|
ExpSVG *string
|
|
GotSVG string
|
|
}
|
|
|
|
func main() {
|
|
deltaFlag := false
|
|
vFlag := false
|
|
testCaseFlag := ""
|
|
testSetFlag := ""
|
|
cpuProfileFlag := false
|
|
memProfileFlag := false
|
|
flag.BoolVar(&deltaFlag, "delta", false, "Generate the report only for cases that changed.")
|
|
flag.StringVar(&testSetFlag, "test-set", "", "Only run set of tests matching this string. e.g. regressions")
|
|
flag.StringVar(&testCaseFlag, "test-case", "", "Only run tests matching this string. e.g. all_shapes")
|
|
flag.BoolVar(&cpuProfileFlag, "cpuprofile", false, "Profile test cpu usage. `go tool pprof out/cpu.prof`")
|
|
flag.BoolVar(&memProfileFlag, "memprofile", false, "Profile test memory usage. `go tool pprof out/mem.prof`")
|
|
skipTests := flag.Bool("skip-tests", false, "Skip running tests first")
|
|
flag.BoolVar(&vFlag, "v", false, "verbose")
|
|
flag.Parse()
|
|
|
|
vString := ""
|
|
if vFlag {
|
|
vString = "-v"
|
|
}
|
|
testMatchString := fmt.Sprintf("-run=TestE2E/%s/%s", testSetFlag, testCaseFlag)
|
|
|
|
cpuProfileStr := ""
|
|
if cpuProfileFlag {
|
|
cpuProfileStr = `-cpuprofile=out/cpu.prof`
|
|
}
|
|
memProfileStr := ""
|
|
if memProfileFlag {
|
|
memProfileStr = `-memprofile=out/mem.prof`
|
|
}
|
|
|
|
testDir := os.Getenv("TEST_DIR")
|
|
if testDir == "" {
|
|
testDir = "./e2etests"
|
|
}
|
|
|
|
if !*skipTests {
|
|
ctx := log.Stderr(context.Background())
|
|
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
|
|
defer cancel()
|
|
cmd := exec.CommandContext(ctx, "go", "test", testDir, testMatchString, cpuProfileStr, memProfileStr, vString)
|
|
cmd.Env = os.Environ()
|
|
cmd.Env = append(cmd.Env, "FORCE_COLOR=1")
|
|
cmd.Env = append(cmd.Env, "DEBUG=1")
|
|
cmd.Env = append(cmd.Env, "TEST_MODE=on")
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
log.Debug(ctx, cmd.String())
|
|
_ = cmd.Run()
|
|
}
|
|
|
|
var tests []TestItem
|
|
err := filepath.Walk(filepath.Join(testDir, "testdata"), func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if info.IsDir() {
|
|
files, err := ioutil.ReadDir(path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
var testFile os.FileInfo
|
|
for _, f := range files {
|
|
if strings.HasSuffix(f.Name(), "exp.svg") {
|
|
testFile = f
|
|
break
|
|
}
|
|
}
|
|
|
|
if testFile != nil {
|
|
testCaseRoot := filepath.Dir(path)
|
|
matchTestCase := true
|
|
if testCaseFlag != "" {
|
|
matchTestCase, _ = regexp.MatchString(testCaseFlag, filepath.Base(testCaseRoot))
|
|
}
|
|
matchTestSet := true
|
|
if testSetFlag != "" {
|
|
matchTestSet, _ = regexp.MatchString(testSetFlag, filepath.Base(filepath.Dir(testCaseRoot)))
|
|
}
|
|
|
|
if matchTestSet && matchTestCase {
|
|
absPath, err := filepath.Abs(path)
|
|
if err != nil {
|
|
stdlog.Fatal(err)
|
|
}
|
|
fullPath := filepath.Join(absPath, testFile.Name())
|
|
hasGot := false
|
|
gotPath := strings.Replace(fullPath, "exp.svg", "got.svg", 1)
|
|
if _, err := os.Stat(gotPath); err == nil {
|
|
hasGot = true
|
|
}
|
|
// e.g. arrowhead_adjustment/dagre
|
|
name := filepath.Join(filepath.Base(testCaseRoot), info.Name())
|
|
if deltaFlag {
|
|
if hasGot {
|
|
tests = append(tests, TestItem{
|
|
Name: name,
|
|
ExpSVG: &fullPath,
|
|
GotSVG: gotPath,
|
|
})
|
|
}
|
|
} else {
|
|
test := TestItem{
|
|
Name: name,
|
|
ExpSVG: nil,
|
|
GotSVG: fullPath,
|
|
}
|
|
if hasGot {
|
|
test.GotSVG = gotPath
|
|
}
|
|
tests = append(tests, test)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if len(tests) > 0 {
|
|
tmpl, err := template.New("report").Parse(TEMPLATE_HTML)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
path := os.Getenv("REPORT_OUTPUT")
|
|
if path == "" {
|
|
path = filepath.Join(testDir, "./out/e2e_report.html")
|
|
}
|
|
err = os.MkdirAll(filepath.Dir(path), 0755)
|
|
if err != nil {
|
|
stdlog.Fatal(err)
|
|
}
|
|
f, err := os.Create(path)
|
|
if err != nil {
|
|
panic(fmt.Errorf("error creating file `%s`. %v", path, err))
|
|
}
|
|
absReportDir, err := filepath.Abs(filepath.Dir(path))
|
|
if err != nil {
|
|
stdlog.Fatal(err)
|
|
}
|
|
|
|
// get the test path relative to the report
|
|
reportRelPath := func(testPath string) string {
|
|
relTestPath, err := filepath.Rel(absReportDir, testPath)
|
|
if err != nil {
|
|
stdlog.Fatal(err)
|
|
}
|
|
return relTestPath
|
|
}
|
|
|
|
// update test paths to be relative to report file
|
|
for i := range tests {
|
|
testItem := &tests[i]
|
|
testItem.GotSVG = reportRelPath(testItem.GotSVG)
|
|
if testItem.ExpSVG != nil {
|
|
*testItem.ExpSVG = reportRelPath(*testItem.ExpSVG)
|
|
}
|
|
}
|
|
|
|
if err := tmpl.Execute(f, TemplateData{Tests: tests}); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|