func TestResolveFile(t *testing.T) { for _, test := range resolveFileTest { expectedWrapper := fmt.Sprintf(` node 'x' { class { '__X': } } class __X { %s } `, test.expectedManifest, ) expectedAST := ast.NewAST() err := parser.Parse( expectedAST, "expected.ms", strings.NewReader(expectedWrapper), ) if err != nil { t.Log(expectedWrapper) t.Fatal(err) } realAST := ast.NewAST() realErr := parser.Parse( realAST, "real.ms", strings.NewReader(test.inputManifest), ) if realErr != nil { t.Log(test.inputManifest) t.Fatal(realErr) } if resolvedDecls, err := Resolve(realAST); err != nil { t.Log(test.inputManifest) t.Error(err) } else if decls := expectedAST.Classes[0].Block.Declarations; !ast.DeclarationsEquals(decls, resolvedDecls) { t.Logf("%#v", decls) t.Logf("%#v", resolvedDecls) declsClass := &ast.Class{Block: ast.Block{Declarations: decls}} resolvedDeclsClass := &ast.Class{Block: ast.Block{ Declarations: resolvedDecls, }} t.Log(expectedWrapper) t.Fatalf( "Got bad manifest, expected\n>>%s<< but got\n>>%s<<", declsClass.String(), resolvedDeclsClass.String(), ) } } }
func TestResolveClass(t *testing.T) { for _, test := range resolveClassTest { expectedAST := ast.NewAST() err := parser.Parse( expectedAST, "expected.ms", strings.NewReader(test.expectedManifest), ) if err != nil { t.Log(test.inputManifest) t.Fatal(err) } realAST := ast.NewAST() realErr := parser.Parse( realAST, "real.ms", strings.NewReader(test.inputManifest), ) if realErr != nil { t.Fatal(realErr) } gs := newGlobalState() gs.populateClassesByName(realAST.Classes) gs.populateDefinesByName(realAST.Defines) resolver := newClassResolver( gs, &realAST.Classes[0], nil, "real.ms", realAST.Classes[0].LineNum, ) if resolvedClass, err := resolver.resolve(); err != nil { t.Log(test.inputManifest) t.Fatal(err) } else { c := expectedAST.Classes[0] c.Filename = "real.ms" if !c.Equals(&resolvedClass) { t.Logf("%#v", c) t.Logf("%#v", resolvedClass) t.Fatal( "Got bad manifest, expected", c.String(), "got", resolvedClass.String(), ) } if len(resolver.ls.varDefsByName) != 0 && false { t.Fatal( "Not all variables were resolved in", test.inputManifest, resolver.ls.varDefsByName, ) } } } }
func TestResolveBadVariable(t *testing.T) { for _, test := range badVariableTest { ast := ast.NewAST() err := parser.Parse( ast, "err.ms", strings.NewReader(test.inputManifest), ) if err != nil { t.Log(test.inputManifest) t.Fatal(err) } gs := newGlobalState() resolver := newClassResolver( gs, &ast.Classes[0], nil, "err.ms", ast.Classes[0].LineNum, ) resolved, resolveErr := resolver.resolve() if resolveErr == nil { t.Log(test.inputManifest) t.Log(&resolved) t.Fatal("Got no error for", test.comment) } else { var e, expE *Err if ce, ok := resolveErr.(*CyclicError); ok { e = &ce.Err } else { e = resolveErr.(*Err) } if ce, ok := test.expectedError.(*CyclicError); ok { expE = &ce.Err } else { expE = test.expectedError.(*Err) } if cyclicE, ok := test.expectedError.(*CyclicError); ok { if re, cyclic := resolveErr.(*CyclicError); !cyclic { t.Log(test.inputManifest) t.Errorf( "%s: Got non-cyclic error: %s", test.comment, resolveErr, ) } else if !reflect.DeepEqual(cyclicE.Cycle, re.Cycle) { t.Log(test.inputManifest) t.Logf("Expected %#v", cyclicE) t.Logf("Got %#v", re) t.Errorf("%s: Got bad cycle error: %s", test.comment, e) } } if e.Line != expE.Line || e.Type != expE.Type { t.Log(test.inputManifest) t.Errorf( "%s: Got bad error: %s. Expected %s", test.comment, e, expE, ) } } } }
func TestBadExpressionManifests(t *testing.T) { for _, test := range badExpressionManifests { realManifest := fmt.Sprintf("class c { %s }", test.expression) ast := ast.NewAST() if err := parser.Parse(ast, "test.ms", strings.NewReader(realManifest)); err != nil { t.Log(realManifest) t.Error(err) continue } if _, err := Resolve(ast); err == nil || err.Error() != test.expectedError { t.Log(test.expression) t.Error("Got bad error:", err) } } }
func TestBadDefs(t *testing.T) { for _, test := range badDefsTest { realAST := ast.NewAST() realErr := parser.Parse( realAST, "real.ms", strings.NewReader(test.manifest), ) if realErr != nil { t.Log(test.manifest) t.Fatal(realErr) } if _, err := Resolve(realAST); err == nil { t.Log(test.manifest) t.Error("Got no error for bad file") } else if err.Error() != test.expectedErr { t.Log(test.manifest) t.Error("Got bad error:", err) } } }
func main() { help := false run := false verbose := false flag.BoolVar(&help, "h", false, "Shows this message") flag.BoolVar(&run, "run", false, "Actually execute the manifest") flag.BoolVar(&verbose, "v", false, "Verbose output") dirName := "../testdata" flag.Parse() if help { showHelp() return } if args := flag.CommandLine.Args(); len(args) == 1 { dirName = args[0] } mfst := ast.NewAST() if err := parseDirAsASTRecursively(mfst, dirName); err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } resolved, resolvedErr := resolver.Resolve(mfst) if resolvedErr != nil { fmt.Fprintln(os.Stderr, resolvedErr.Error()) os.Exit(1) } reduced, reducedErr := reducer.Reduce(resolved) if reducedErr != nil { fmt.Fprintln(os.Stderr, reducedErr.Error()) os.Exit(1) } steps, stepsErr := stepconverter.Convert(reduced) if stepsErr != nil { fmt.Fprintln(os.Stderr, stepsErr.Error()) os.Exit(1) } planner := planner.New() plan, planErr := planner.Plan(steps) if planErr != nil { fmt.Fprintln(os.Stderr, planErr.Error()) os.Exit(1) } if run { realExc, realExcErr := executor.New("../script") if realExcErr != nil { fmt.Fprintln(os.Stderr, realExcErr.Error()) os.Exit(1) } if err := executor.ExecutePlan(plan, realExc); err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } } else { exc := executor.DryRun(verbose) if err := executor.ExecutePlan(plan, exc); err != nil { panic(err) } } }