check command
This commit is contained in:
parent
6178b0c7a1
commit
f45e6bab4b
54
cmd/treerack/check.go
Normal file
54
cmd/treerack/check.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type checkOptions struct {
|
||||||
|
syntaxOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func flagSetCheck(o *checkOptions, output io.Writer) *flag.FlagSet {
|
||||||
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
fs.Usage = func() {}
|
||||||
|
fs.SetOutput(output)
|
||||||
|
fs.StringVar(&o.syntax, "syntax-string", "", syntaxStringUsage)
|
||||||
|
fs.StringVar(&o.syntaxFile, "syntax", "", syntaxFileUsage)
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
func flagErrorCheck(fs *flag.FlagSet) {
|
||||||
|
stderr()
|
||||||
|
stderr("Options:")
|
||||||
|
fs.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func helpCheck() {
|
||||||
|
stdout(checkUsage)
|
||||||
|
stdout()
|
||||||
|
stdout("Options:")
|
||||||
|
fs := flagSetCheck(&checkOptions{}, wout)
|
||||||
|
fs.PrintDefaults()
|
||||||
|
stdout()
|
||||||
|
stdout(checkExample)
|
||||||
|
stdout()
|
||||||
|
stdout(docRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(args []string) int {
|
||||||
|
if len(args) > 0 && args[0] == "-help" {
|
||||||
|
helpCheck()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var options checkOptions
|
||||||
|
fs := flagSetCheck(&options, werr)
|
||||||
|
if err := fs.Parse(args); err != nil {
|
||||||
|
flagErrorCheck(fs)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
_, code := open(options.syntaxOptions, fs)
|
||||||
|
return code
|
||||||
|
}
|
103
cmd/treerack/check_test.go
Normal file
103
cmd/treerack/check_test.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestCheck(t *testing.T) {
|
||||||
|
runMainTest(t,
|
||||||
|
mainTest{
|
||||||
|
title: "help",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check", "-help",
|
||||||
|
},
|
||||||
|
stdout: []string{
|
||||||
|
checkUsage,
|
||||||
|
"-syntax",
|
||||||
|
"-syntax-string",
|
||||||
|
checkExample,
|
||||||
|
docRef,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "invalid flag",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check", "-foo",
|
||||||
|
},
|
||||||
|
exit: -1,
|
||||||
|
stderr: []string{
|
||||||
|
"-syntax",
|
||||||
|
"-syntax-string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "multiple inputs",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check", "-syntax", "foo.treerack", "-syntax-string", `foo = "bar"`,
|
||||||
|
},
|
||||||
|
exit: -1,
|
||||||
|
stderr: []string{
|
||||||
|
"only one",
|
||||||
|
"-syntax",
|
||||||
|
"-syntax-string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "no input",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check",
|
||||||
|
},
|
||||||
|
exit: -1,
|
||||||
|
stderr: []string{
|
||||||
|
"missing syntax input",
|
||||||
|
"-syntax",
|
||||||
|
"-syntax-string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "invalid input",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check", "-syntax-string", "foo",
|
||||||
|
},
|
||||||
|
exit: -1,
|
||||||
|
stderr: []string{
|
||||||
|
"parse failed",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "file open fails",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check", "-syntax", "noexist.treerack",
|
||||||
|
},
|
||||||
|
exit: -1,
|
||||||
|
stderr: []string{
|
||||||
|
"file",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "syntax as stdin",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "check",
|
||||||
|
},
|
||||||
|
stdin: `foo = "bar"`,
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "syntax as file",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "generate", "-syntax", "foo_test.treerack",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mainTest{
|
||||||
|
title: "syntax as string",
|
||||||
|
args: []string{
|
||||||
|
"treerack", "generate", "-syntax-string", `foo = "bar"`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
@ -23,3 +23,8 @@ const generateUsage = `treerack generate takes a syntax description from the sta
|
|||||||
|
|
||||||
const generateExample = `Example:
|
const generateExample = `Example:
|
||||||
treerack generate -syntax syntax.treerack > parser.go`
|
treerack generate -syntax syntax.treerack > parser.go`
|
||||||
|
|
||||||
|
const checkUsage = `treerack check takes a syntax description from the standard input, or a file, or inline string, and validates it to check whether it represents a valid syntax. It returns with non-zero exit code and prints the problem if the syntax is not valid.`
|
||||||
|
|
||||||
|
const checkExample = `Example:
|
||||||
|
treerack check -syntax syntax.treerack`
|
||||||
|
@ -1,24 +1,19 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"flag"
|
"flag"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/aryszka/treerack"
|
"github.com/aryszka/treerack"
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type generateOptions struct {
|
type generateOptions struct {
|
||||||
syntax string
|
syntaxOptions
|
||||||
syntaxFile string
|
|
||||||
packageName string
|
packageName string
|
||||||
export bool
|
export bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func flagSet(o *generateOptions, output io.Writer) *flag.FlagSet {
|
func flagSetGenerate(o *generateOptions, output io.Writer) *flag.FlagSet {
|
||||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
fs.Usage = func() {}
|
fs.Usage = func() {}
|
||||||
fs.SetOutput(output)
|
fs.SetOutput(output)
|
||||||
@ -29,11 +24,17 @@ func flagSet(o *generateOptions, output io.Writer) *flag.FlagSet {
|
|||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flagErrorGenerate(fs *flag.FlagSet) {
|
||||||
|
stderr()
|
||||||
|
stderr("Options:")
|
||||||
|
fs.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
func helpGenerate() {
|
func helpGenerate() {
|
||||||
stdout(generateUsage)
|
stdout(generateUsage)
|
||||||
stdout()
|
stdout()
|
||||||
stdout("Options:")
|
stdout("Options:")
|
||||||
fs := flagSet(&generateOptions{}, wout)
|
fs := flagSetGenerate(&generateOptions{}, wout)
|
||||||
fs.PrintDefaults()
|
fs.PrintDefaults()
|
||||||
stdout()
|
stdout()
|
||||||
stdout(generateExample)
|
stdout(generateExample)
|
||||||
@ -41,26 +42,6 @@ func helpGenerate() {
|
|||||||
stdout(docRef)
|
stdout(docRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
func flagError(fs *flag.FlagSet) {
|
|
||||||
stderr()
|
|
||||||
stderr("Options:")
|
|
||||||
fs.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
func multipleInputsError(fs *flag.FlagSet) {
|
|
||||||
stderr("only one of syntax file or syntax string is allowed")
|
|
||||||
stderr()
|
|
||||||
stderr("Options:")
|
|
||||||
fs.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
func noInputError(fs *flag.FlagSet) {
|
|
||||||
stderr("missing syntax input")
|
|
||||||
stderr()
|
|
||||||
stderr("Options:")
|
|
||||||
fs.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
func generate(args []string) int {
|
func generate(args []string) int {
|
||||||
if len(args) > 0 && args[0] == "-help" {
|
if len(args) > 0 && args[0] == "-help" {
|
||||||
helpGenerate()
|
helpGenerate()
|
||||||
@ -68,47 +49,15 @@ func generate(args []string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var options generateOptions
|
var options generateOptions
|
||||||
fs := flagSet(&options, werr)
|
fs := flagSetGenerate(&options, werr)
|
||||||
if err := fs.Parse(args); err != nil {
|
if err := fs.Parse(args); err != nil {
|
||||||
flagError(fs)
|
flagErrorGenerate(fs)
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.syntaxFile != "" && options.syntax != "" {
|
s, code := open(options.syntaxOptions, fs)
|
||||||
multipleInputsError(fs)
|
if code != 0 {
|
||||||
return -1
|
return code
|
||||||
}
|
|
||||||
|
|
||||||
var hasInput bool
|
|
||||||
if options.syntaxFile == "" && options.syntax == "" {
|
|
||||||
hasInput = isTest && rin != nil || !isTest && !terminal.IsTerminal(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !hasInput && options.syntaxFile == "" && options.syntax == "" {
|
|
||||||
noInputError(fs)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
var input io.Reader
|
|
||||||
if hasInput {
|
|
||||||
input = rin
|
|
||||||
} else if options.syntaxFile != "" {
|
|
||||||
f, err := os.Open(options.syntaxFile)
|
|
||||||
if err != nil {
|
|
||||||
stderr(err)
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
input = f
|
|
||||||
} else if options.syntax != "" {
|
|
||||||
input = bytes.NewBufferString(options.syntax)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &treerack.Syntax{}
|
|
||||||
if err := s.ReadSyntax(input); err != nil {
|
|
||||||
stderr(err)
|
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var goptions treerack.GeneratorOptions
|
var goptions treerack.GeneratorOptions
|
||||||
|
@ -22,6 +22,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
|
case "check":
|
||||||
|
code := check(os.Args[2:])
|
||||||
|
exit(code)
|
||||||
case "generate":
|
case "generate":
|
||||||
code := generate(os.Args[2:])
|
code := generate(os.Args[2:])
|
||||||
exit(code)
|
exit(code)
|
||||||
|
@ -123,20 +123,30 @@ func (mt mainTest) run(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if stdout != nil {
|
if stdout != nil {
|
||||||
|
var failed bool
|
||||||
for i := range mt.stdout {
|
for i := range mt.stdout {
|
||||||
if !strings.Contains(stdout.String(), mt.stdout[i]) {
|
if !strings.Contains(stdout.String(), mt.stdout[i]) {
|
||||||
t.Error("invalid output")
|
t.Error("invalid output")
|
||||||
t.Log(stdout.String())
|
failed = true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if failed {
|
||||||
|
t.Log(stdout.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var failed bool
|
||||||
for i := range mt.stderr {
|
for i := range mt.stderr {
|
||||||
if !strings.Contains(stderr.String(), mt.stderr[i]) {
|
if !strings.Contains(stderr.String(), mt.stderr[i]) {
|
||||||
t.Error("invalid error output")
|
t.Error("invalid error output")
|
||||||
t.Log(stderr.String())
|
failed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if failed {
|
||||||
|
t.Log(stderr.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if mt.title == "" {
|
if mt.title == "" {
|
||||||
|
71
cmd/treerack/open.go
Normal file
71
cmd/treerack/open.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/aryszka/treerack"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type syntaxOptions struct {
|
||||||
|
syntax string
|
||||||
|
syntaxFile string
|
||||||
|
}
|
||||||
|
|
||||||
|
func multipleSyntaxesError(fs *flag.FlagSet) {
|
||||||
|
stderr("only one of syntax file or syntax string is allowed")
|
||||||
|
stderr()
|
||||||
|
stderr("Options:")
|
||||||
|
fs.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func missingSyntaxError(fs *flag.FlagSet) {
|
||||||
|
stderr("missing syntax input")
|
||||||
|
stderr()
|
||||||
|
stderr("Options:")
|
||||||
|
fs.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func open(options syntaxOptions, fs *flag.FlagSet) (*treerack.Syntax, int) {
|
||||||
|
if options.syntaxFile != "" && options.syntax != "" {
|
||||||
|
multipleSyntaxesError(fs)
|
||||||
|
return nil, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasInput bool
|
||||||
|
if options.syntaxFile == "" && options.syntax == "" {
|
||||||
|
hasInput = isTest && rin != nil || !isTest && !terminal.IsTerminal(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasInput && options.syntaxFile == "" && options.syntax == "" {
|
||||||
|
missingSyntaxError(fs)
|
||||||
|
return nil, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
var input io.Reader
|
||||||
|
if hasInput {
|
||||||
|
input = rin
|
||||||
|
} else if options.syntaxFile != "" {
|
||||||
|
f, err := os.Open(options.syntaxFile)
|
||||||
|
if err != nil {
|
||||||
|
stderr(err)
|
||||||
|
return nil, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
input = f
|
||||||
|
} else if options.syntax != "" {
|
||||||
|
input = bytes.NewBufferString(options.syntax)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &treerack.Syntax{}
|
||||||
|
if err := s.ReadSyntax(input); err != nil {
|
||||||
|
stderr(err)
|
||||||
|
return nil, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, 0
|
||||||
|
}
|
@ -9,6 +9,8 @@ read, with error reporting
|
|||||||
what was the bug with the large json from eskip?
|
what was the bug with the large json from eskip?
|
||||||
|
|
||||||
[next]
|
[next]
|
||||||
|
check
|
||||||
|
parse
|
||||||
error reports
|
error reports
|
||||||
- take the last
|
- take the last
|
||||||
simplify generator output
|
simplify generator output
|
||||||
|
1142
self/self.go
1142
self/self.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user