trace_schema_validator can be used to verify that trace2 event output conforms to the expectations set by the API documentation and codified in event_schema.json (or strict_schema.json). This allows us to build a regression test to verify that trace2 output does not change unexpectedly. Signed-off-by: Josh Steadmon <steadmon@xxxxxxxxxx> --- t/trace_schema_validator/.gitignore | 1 + t/trace_schema_validator/Makefile | 18 ++++ .../trace_schema_validator.go | 82 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 t/trace_schema_validator/.gitignore create mode 100644 t/trace_schema_validator/Makefile create mode 100644 t/trace_schema_validator/trace_schema_validator.go diff --git a/t/trace_schema_validator/.gitignore b/t/trace_schema_validator/.gitignore new file mode 100644 index 0000000000..c3f1e04e9e --- /dev/null +++ b/t/trace_schema_validator/.gitignore @@ -0,0 +1 @@ +trace_schema_validator diff --git a/t/trace_schema_validator/Makefile b/t/trace_schema_validator/Makefile new file mode 100644 index 0000000000..50bd266518 --- /dev/null +++ b/t/trace_schema_validator/Makefile @@ -0,0 +1,18 @@ +RM = rm -f +PROGRAMS = trace_schema_validator +GOCMD = go +GOBUILD = $(GOCMD) build +GOGET = $(GOCMD) get + +.PHONY: fetch_deps clean + +all: $(PROGRAMS) + +trace_schema_validator: fetch_deps trace_schema_validator.go + $(GOBUILD) -o trace_schema_validator + +fetch_deps: + $(GOGET) github.com/xeipuuv/gojsonschema + +clean: + $(RM) $(PROGRAMS) diff --git a/t/trace_schema_validator/trace_schema_validator.go b/t/trace_schema_validator/trace_schema_validator.go new file mode 100644 index 0000000000..bfda3c405e --- /dev/null +++ b/t/trace_schema_validator/trace_schema_validator.go @@ -0,0 +1,82 @@ +// trace_schema_validator validates individual lines of an input file against a +// provided JSON-Schema for git trace2 event output. +// +// Note that this expects each object to validate to be on its own line in the +// input file (AKA JSON-Lines format). This is what Git natively writes with +// GIT_TRACE2_EVENT enabled. +// +// Traces can be collected by setting the GIT_TRACE2_EVENT environment variable +// to an absolute path and running any Git command; traces will be appended to +// the file. +// +// Traces can then be verified like so: +// trace_schema_validator \ +// --trace2-event-file /path/to/trace/output \ +// --schema-file /path/to/schema +package main + +import ( + "bufio" + "flag" + "log" + "os" + "path/filepath" + + "github.com/xeipuuv/gojsonschema" +) + +// Required flags +var schemaFile = flag.String("schema-file", "", "JSON-Schema filename") +var trace2EventFile = flag.String("trace2-event-file", "", "trace2 event filename") +var progress = flag.Int("progress", 0, "Print progress message each time we have validated this many lines. --progress=0 means no messages are printed") + +func main() { + flag.Parse() + if *schemaFile == "" || *trace2EventFile == "" { + log.Fatal("Both --schema-file and --trace2-event-file are required.") + } + schemaURI, err := filepath.Abs(*schemaFile) + if err != nil { + log.Fatal("Can't get absolute path for schema file: ", err) + } + schemaURI = "file://" + schemaURI + + schemaLoader := gojsonschema.NewReferenceLoader(schemaURI) + schema, err := gojsonschema.NewSchema(schemaLoader) + if err != nil { + log.Fatal("Problem loading schema: ", err) + } + + tracesFile, err := os.Open(*trace2EventFile) + if err != nil { + log.Fatal("Problem opening trace file: ", err) + } + defer tracesFile.Close() + + scanner := bufio.NewScanner(tracesFile) + + count := 0 + for ; scanner.Scan(); count++ { + if *progress != 0 && count%*progress == 0 { + log.Print("Validated items: ", count) + } + event := gojsonschema.NewStringLoader(scanner.Text()) + result, err := schema.Validate(event) + if err != nil { + log.Fatal(err) + } + if !result.Valid() { + log.Printf("Trace event line %d is invalid: %s", count+1, scanner.Text()) + for _, desc := range result.Errors() { + log.Print("- ", desc) + } + os.Exit(1) + } + } + + if err := scanner.Err(); err != nil { + log.Fatal("Scanning error: ", err) + } + + log.Print("Validated events: ", count) +} -- 2.22.0.709.g102302147b-goog