func TestErrorMetadata(t *testing.T) { var checkParseErr = func(path string, expErr string) { sc := scanner.Scanner{ Position: scanner.Position{ Filename: path, }, } f, err := util.Open(path) if err != nil { t.Errorf("Couldn't open %s", path) } _, err = parse(*sc.Init(f)) if err.Error() != expErr { t.Errorf("Expected \"%s\"\ngot \"%s\"", expErr, err) return } } var checkEvalErr = func(path string, expErr string) { sc := scanner.Scanner{ Position: scanner.Position{ Filename: path, }, } f, err := util.Open(path) if err != nil { t.Errorf("Couldn't open %s", path) } parsed, err := parse(*sc.Init(f)) if err != nil { t.Errorf("Unexpected parse error: %s", parsed) } _, _, err = eval(astRoot(parsed)) if err.Error() != expErr { t.Errorf("Expected \"%s\"\ngot \"%s\"", expErr, err) return } } util.AppFs = afero.NewMemMapFs() util.WriteFile("paren.spec", []byte(` // This is a comment. (define Test "abc"`), 0644) checkParseErr("paren.spec", "paren.spec:3: unbalanced Parenthesis") util.WriteFile("undefined.spec", []byte(` (+ 1 b)`), 0644) checkEvalErr("undefined.spec", "undefined.spec:2: unassigned variable: b") util.WriteFile("bad_type.spec", []byte(` (define a "1") (+ 1 a)`), 0644) checkEvalErr("bad_type.spec", `bad_type.spec:3: bad arithmetic argument: "1"`) // Test that functions which evaluate generated S-expressions still have proper // error messages. util.WriteFile("generated_sexp.spec", []byte(`(apply + (list 1 "1"))`), 0644) checkEvalErr("generated_sexp.spec", `generated_sexp.spec:1: bad arithmetic argument: "1"`) }
func updateConfig(conn db.Conn, configPath string) error { pathStr, _ := os.LookupEnv(quiltPath) if pathStr == "" { pathStr = stitch.GetQuiltPath() } f, err := util.Open(configPath) if err != nil { f, err = util.Open(filepath.Join(pathStr, configPath)) if err != nil { return err } } defer f.Close() sc := scanner.Scanner{ Position: scanner.Position{ Filename: configPath, }, } spec, err := stitch.New(*sc.Init(bufio.NewReader(f)), pathStr, false) if err != nil { return err } return engine.UpdatePolicy(conn, spec) }
func resolveImportsRec(asts []ast, path string, imported []string, download bool) ([]ast, error) { var newAsts []ast top := true // Imports are required to be at the top of the file. for _, ast := range asts { name := parseImport(ast) if name == "" { newAsts = append(newAsts, ast) top = false continue } if !top { return nil, errors.New("import must be begin the module") } // Check for any import cycles. for _, importedModule := range imported { if name == importedModule { return nil, fmt.Errorf("import cycle: %s", append(imported, name)) } } modulePath := filepath.Join(path, name+".spec") var sc scanner.Scanner sc.Filename = modulePath if _, err := os.Stat(modulePath); os.IsNotExist(err) && download { GetSpec(name) } f, err := util.Open(modulePath) if err != nil { return nil, fmt.Errorf("unable to open import %s", name) } defer f.Close() sc.Init(bufio.NewReader(f)) parsed, err := parse(sc) if err != nil { return nil, err } // Rename module name to last name in import path name = filepath.Base(name) parsed, err = resolveImportsRec(parsed, path, append(imported, name), download) if err != nil { return nil, err } module := astModule{body: parsed, moduleName: astString(name)} newAsts = append(newAsts, module) } return newAsts, nil }
func TestReadme(t *testing.T) { f, err := util.Open("../README.md") if err != nil { t.Errorf("Failed to open README: %s", err.Error()) return } defer f.Close() r := bufio.NewReader(f) start := "<!-- BEGIN CODE -->\n" end := "<!-- END CODE -->\n" var code string recording := false for { line, err := r.ReadString('\n') if err == io.EOF { if recording { fmt.Printf("Unbalanced code blocks.") return } break } if err != nil { t.Errorf("Failed to read README: %s", err.Error()) return } if line == start { if recording { t.Errorf("Unbalanced code blocks.") return } recording = true continue } if line == end { if !recording { t.Errorf("Unbalanced code blocks.") return } recording = false } if recording { code += fmt.Sprintf("%s", line) } } if err = checkConfig(code); err != nil { t.Errorf(err.Error()) } }
func configRunOnce(configPath string, quiltPath string) error { f, err := util.Open(configPath) if err != nil { return err } defer f.Close() var sc scanner.Scanner _, err = stitch.New(*sc.Init(bufio.NewReader(f)), quiltPath, false) if err != nil { return err } return nil }
func checkSpec(file string, info os.FileInfo, err error) error { if filepath.Ext(file) != ".spec" { return nil } f, err := util.Open(file) if err != nil { return err } defer f.Close() sc := scanner.Scanner{ Position: scanner.Position{ Filename: file, }, } _, err = New(*sc.Init(bufio.NewReader(f)), GetQuiltPath(), true) return err }
func TestReadme(t *testing.T) { f, err := util.Open("../README.md") if err != nil { t.Errorf("Failed to open README: %s", err.Error()) return } defer f.Close() scanner := bufio.NewScanner(f) parser := readmeParser{} parser.codeBlocks = make(map[string]string) for scanner.Scan() { if err := parser.parse(scanner.Text() + "\n"); err != nil { t.Errorf("Failed to parse README: %s", err.Error()) return } } if err := scanner.Err(); err != nil { t.Errorf("Failed to read README: %s", err.Error()) return } blocks, err := parser.blocks() if err != nil { t.Errorf("Failed to parse README: %s", err.Error()) return } goPath := os.Getenv("GOPATH") quiltPath := filepath.Join(goPath, "src") for _, block := range blocks { if err = checkConfig(block, quiltPath); err != nil { t.Errorf(err.Error()) } } }