Skip to content
Snippets Groups Projects
Commit 7aea95e4 authored by Ken Brooks's avatar Ken Brooks
Browse files

merged changes from upstream master

parents e17a5ddd 4ab3c311
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"bufio" "bufio"
"flag" "flag"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
...@@ -20,7 +21,7 @@ import ( ...@@ -20,7 +21,7 @@ import (
) )
var ( var (
version = "undefined" version = "v1.3.0-dev"
schemaFlag = flag.String("s", "", "primary JSON schema to validate against, required") schemaFlag = flag.String("s", "", "primary JSON schema to validate against, required")
quietFlag = flag.Bool("q", false, "quiet, only print validation failures and errors") quietFlag = flag.Bool("q", false, "quiet, only print validation failures and errors")
versionFlag = flag.Bool("v", false, "print version and exit") versionFlag = flag.Bool("v", false, "print version and exit")
...@@ -37,13 +38,13 @@ func init() { ...@@ -37,13 +38,13 @@ func init() {
func main() { func main() {
log.SetFlags(0) log.SetFlags(0)
os.Exit(realMain(os.Args[1:])) os.Exit(realMain(os.Args[1:], os.Stdout))
} }
func realMain(args []string) int { func realMain(args []string, w io.Writer) int {
flag.CommandLine.Parse(args) flag.CommandLine.Parse(args)
if *versionFlag { if *versionFlag {
fmt.Println(version) fmt.Fprintln(w, version)
return 0 return 0
} }
if *schemaFlag == "" { if *schemaFlag == "" {
...@@ -70,7 +71,6 @@ func realMain(args []string) int { ...@@ -70,7 +71,6 @@ func realMain(args []string) int {
if !filepath.IsAbs(pattern) { if !filepath.IsAbs(pattern) {
pattern = filepath.Join(dir, pattern) pattern = filepath.Join(dir, pattern)
} }
docs = append(docs, glob(pattern)...) docs = append(docs, glob(pattern)...)
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
...@@ -89,9 +89,9 @@ func realMain(args []string) int { ...@@ -89,9 +89,9 @@ func realMain(args []string) int {
} }
for _, ref := range refFlags { for _, ref := range refFlags {
for _, p := range glob(ref) { for _, p := range glob(ref) {
absPath, absPathErr := filepath.Abs(p) absPath, err := filepath.Abs(p)
if absPathErr != nil { if err != nil {
log.Fatalf("%s: unable to convert to absolute path: %s\n", absPath, absPathErr) log.Fatalf("%s: unable to convert to absolute path: %s\n", absPath, err)
} }
if absPath == schemaPath { if absPath == schemaPath {
...@@ -125,17 +125,17 @@ func realMain(args []string) int { ...@@ -125,17 +125,17 @@ func realMain(args []string) int {
failures := make([]string, 0) failures := make([]string, 0)
errors := make([]string, 0) errors := make([]string, 0)
for _, p := range docs { for _, p := range docs {
//fmt.Println(p)
wg.Add(1) wg.Add(1)
go func(path string) { go func(path string) {
defer wg.Done() defer wg.Done()
sem <- 0 sem <- 0
defer func() { <-sem }() defer func() { <-sem }()
loader, err := jsonLoader(path) loader, err := jsonLoader(path)
if err != nil { if err != nil {
msg := fmt.Sprintf("%s: error: load doc %s\n", path, err) msg := fmt.Sprintf("%s: error: load doc: %s", path, err)
fmt.Println(msg) fmt.Fprintln(w, msg)
errors = append(errors, msg) errors = append(errors, msg)
return return
} }
...@@ -143,7 +143,7 @@ func realMain(args []string) int { ...@@ -143,7 +143,7 @@ func realMain(args []string) int {
switch { switch {
case err != nil: case err != nil:
msg := fmt.Sprintf("%s: error: validate: %s", path, err) msg := fmt.Sprintf("%s: error: validate: %s", path, err)
fmt.Println(msg) fmt.Fprintln(w, msg)
errors = append(errors, msg) errors = append(errors, msg)
case !result.Valid(): case !result.Valid():
...@@ -152,11 +152,11 @@ func realMain(args []string) int { ...@@ -152,11 +152,11 @@ func realMain(args []string) int {
lines[i] = fmt.Sprintf("%s: fail: %s", path, desc) lines[i] = fmt.Sprintf("%s: fail: %s", path, desc)
} }
msg := strings.Join(lines, "\n") msg := strings.Join(lines, "\n")
fmt.Println(msg) fmt.Fprintln(w, msg)
failures = append(failures, msg) failures = append(failures, msg)
case !*quietFlag: case !*quietFlag:
fmt.Printf("%s: pass\n", path) fmt.Fprintf(w, "%s: pass\n", path)
} }
}(p) }(p)
} }
...@@ -165,12 +165,12 @@ func realMain(args []string) int { ...@@ -165,12 +165,12 @@ func realMain(args []string) int {
// Summarize results (e.g. errors) // Summarize results (e.g. errors)
if !*quietFlag { if !*quietFlag {
if len(failures) > 0 { if len(failures) > 0 {
fmt.Printf("%d of %d failed validation\n", len(failures), len(docs)) fmt.Fprintf(w, "%d of %d failed validation\n", len(failures), len(docs))
fmt.Println(strings.Join(failures, "\n")) fmt.Fprintln(w, strings.Join(failures, "\n"))
} }
if len(errors) > 0 { if len(errors) > 0 {
fmt.Printf("%d of %d malformed documents\n", len(errors), len(docs)) fmt.Fprintf(w, "%d of %d malformed documents\n", len(errors), len(docs))
fmt.Println(strings.Join(errors, "\n")) fmt.Fprintln(w, strings.Join(errors, "\n"))
} }
} }
exit := 0 exit := 0
...@@ -234,18 +234,14 @@ func glob(pattern string) []string { ...@@ -234,18 +234,14 @@ func glob(pattern string) []string {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
universalPaths := make([]string, 0)
paths, err := filepath.Glob(pattern) paths, err := filepath.Glob(pattern)
for _, mypath := range paths {
universalPaths = append(universalPaths, filepath.ToSlash(mypath))
}
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
if len(universalPaths) == 0 { if len(paths) == 0 {
log.Fatalf("%s: no such file or directory", pattern) log.Fatalf("%s: no such file or directory", pattern)
} }
return universalPaths return paths
} }
type stringFlags []string type stringFlags []string
......
// +build windows !windows
package main package main
import ( import (
"log" "path/filepath"
"sort"
"strings"
"testing"
) )
func ExampleMain_pass_ymlschema_ymldoc() { func TestMain(t *testing.T) {
exit := realMain([]string{"-s", "testdata/schema.yml", "testdata/data-pass.yml"}) tests := []struct {
if exit != 0 { in string
log.Fatalf("exit: got %d, want 0", exit) out []string
} exit int
// Output: } {
// testdata/data-pass.yml: pass {
} "-s testdata/schema.yml testdata/data-pass.yml",
[]string{"testdata/data-pass.yml: pass"},
func ExampleMain_pass_jsonschema_ymldoc() { 0,
exit := realMain([]string{"-s", "testdata/schema.json", "testdata/data-pass.yml"}) }, {
if exit != 0 { "-s testdata/schema.json testdata/data-pass.yml",
log.Fatalf("exit: got %d, want 0", exit) []string{"testdata/data-pass.yml: pass"},
} 0,
// Output: }, {
// testdata/data-pass.yml: pass "-s testdata/schema.json testdata/data-pass.json",
} []string{"testdata/data-pass.json: pass"},
0,
func ExampleMain_pass_jsonschema_jsondoc() { }, {
exit := realMain([]string{"-s", "testdata/schema.json", "testdata/data-pass.json"}) "-s testdata/schema.yml testdata/data-pass.json",
if exit != 0 { []string{"testdata/data-pass.json: pass"},
log.Fatalf("exit: got %d, want 0", exit) 0,
} }, {
// Output: "-q -s testdata/schema.yml testdata/data-fail.yml",
// testdata/data-pass.json: pass []string{"testdata/data-fail.yml: fail: (root): foo is required"},
} 1,
}, {
func ExampleMain_pass_ymlschema_jsondoc() { "-q -s testdata/schema.json testdata/data-fail.yml",
exit := realMain([]string{"-s", "testdata/schema.yml", "testdata/data-pass.json"}) []string{"testdata/data-fail.yml: fail: (root): foo is required"},
if exit != 0 { 1,
log.Fatalf("exit: got %d, want 0", exit) }, {
} "-q -s testdata/schema.json testdata/data-fail.json",
// Output: []string{"testdata/data-fail.json: fail: (root): foo is required"},
// testdata/data-pass.json: pass 1,
} }, {
"-q -s testdata/schema.yml testdata/data-fail.json",
func ExampleMain_fail_ymlschema_ymldoc() { []string{"testdata/data-fail.json: fail: (root): foo is required"},
exit := realMain([]string{"-q", "-s", "testdata/schema.yml", "testdata/data-fail.yml"}) 1,
if exit != 1 { }, {
log.Fatalf("exit: got %d, want 1", exit) "-q -s testdata/schema.json testdata/data-error.json",
} []string{"testdata/data-error.json: error: validate: invalid character 'o' in literal null (expecting 'u')"},
// Output: 2,
// testdata/data-fail.yml: fail: (root): foo is required }, {
} "-q -s testdata/schema.yml testdata/data-error.yml",
[]string{"testdata/data-error.yml: error: load doc: yaml: found unexpected end of stream"},
func ExampleMain_fail_jsonschema_ymldoc() { 2,
exit := realMain([]string{"-q", "-s", "testdata/schema.json", "testdata/data-fail.yml"}) }, {
if exit != 1 { "-q -s testdata/schema.json testdata/data-*.json",
log.Fatalf("exit: got %d, want 1", exit) []string{
} "testdata/data-fail.json: fail: (root): foo is required",
// Output: "testdata/data-error.json: error: validate: invalid character 'o' in literal null (expecting 'u')",
// testdata/data-fail.yml: fail: (root): foo is required }, 3,
} }, {
"-q -s testdata/schema.yml testdata/data-*.yml",
func ExampleMain_fail_jsonschema_jsondoc() { []string{
exit := realMain([]string{"-q", "-s", "testdata/schema.json", "testdata/data-fail.json"}) "testdata/data-error.yml: error: load doc: yaml: found unexpected end of stream",
if exit != 1 { "testdata/data-fail.yml: fail: (root): foo is required",
log.Fatalf("exit: got %d, want 1", exit) }, 3,
} },
// Output:
// testdata/data-fail.json: fail: (root): foo is required
}
func ExampleMain_fail_ymlschema_jsondoc() {
exit := realMain([]string{"-q", "-s", "testdata/schema.yml", "testdata/data-fail.json"})
if exit != 1 {
log.Fatalf("exit: got %d, want 1", exit)
}
// Output:
// testdata/data-fail.json: fail: (root): foo is required
} }
func ExampleMain_error_jsonschema_jsondoc() { for _, tt := range tests {
exit := realMain([]string{"-q", "-s", "testdata/schema.json", "testdata/data-error.json"}) in := strings.ReplaceAll(tt.in, "/", string(filepath.Separator))
if exit != 2 { sort.Strings(tt.out)
log.Fatalf("exit: got %d, want 2", exit) out := strings.Join(tt.out, "\n")
} out = strings.ReplaceAll(out, "/", string(filepath.Separator))
// Output:
// testdata/data-error.json: error: validate: invalid character 'o' in literal null (expecting 'u')
}
func ExampleMain_error_ymlschema_ymldoc() { t.Run(in, func(t *testing.T) {
exit := realMain([]string{"-q", "-s", "testdata/schema.yml", "testdata/data-error.yml"}) var w strings.Builder
if exit != 2 { exit := realMain(strings.Split(in, " "), &w)
log.Fatalf("exit: got %d, want 2", exit) if exit != tt.exit {
t.Fatalf("exit: got %d, want %d", exit, tt.exit)
} }
// Output: lines := strings.Split(w.String(), "\n")
// testdata/data-error.yml: error: load doc yaml: found unexpected end of stream sort.Strings(lines)
got := strings.Join(lines[1:], "\n")
if got != out {
t.Errorf("got\n%s\nwant\n%s", got, out)
} }
})
func ExampleMain_glob_jsonschema_jsondoc() {
exit := realMain([]string{"-q", "-s", "testdata/schema.json", "testdata/data-*.json"})
if exit != 3 {
log.Fatalf("exit: got %d, want 3", exit)
} }
// Unordered output:
// testdata/data-error.json: error: validate: invalid character 'o' in literal null (expecting 'u')
// testdata/data-fail.json: fail: (root): foo is required
} }
func ExampleMain_glob_ymlschema_ymldoc() {
exit := realMain([]string{"-q", "-s", "testdata/schema.yml", "testdata/data-*.yml"})
if exit != 3 {
log.Fatalf("exit: got %d, want 3", exit)
}
// Unordered output:
// testdata/data-fail.yml: fail: (root): foo is required
//
// testdata/data-error.yml: error: load doc yaml: found unexpected end of stream
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment