// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved. // Revel Framework source code and usage is governed by a MIT style // license that can be found in the LICENSE file. package harness import ( "go/ast" "go/parser" "go/token" "reflect" "strings" "testing" "github.com/revel/revel" ) const validationKeysSource = ` package test func (c *Application) testFunc(a, b int, user models.User) revel.Result { // Line 5 c.Validation.Required(a) c.Validation.Required(a).Message("Error message") c.Validation.Required(a). Message("Error message") // Line 11 c.Validation.Required(user.Name) c.Validation.Required(user.Name).Message("Error message") // Line 15 c.Validation.MinSize(b, 12) c.Validation.MinSize(b, 12).Message("Error message") c.Validation.MinSize(b, 12) // Line 21 c.Validation.Required(b == 5) } func (m Model) Validate(v *revel.Validation) { // Line 26 v.Required(m.name) v.Required(m.name == "something"). Message("Error Message") v.Required(!m.bool) } ` var expectedValidationKeys = []map[int]string{ { 6: "a", 7: "a", 8: "a", 12: "user.Name", 13: "user.Name", 16: "b", 17: "b", 19: "b", 22: "b", }, { 27: "m.name", 28: "m.name", 30: "m.bool", }, } // This tests the recording of line number to validation key of the preceeding // example source. func TestGetValidationKeys(t *testing.T) { fset := token.NewFileSet() file, err := parser.ParseFile(fset, "validationKeysSource", validationKeysSource, 0) if err != nil { t.Fatal(err) } if len(file.Decls) != 2 { t.Fatal("Expected 2 decl in the source, found", len(file.Decls)) } for i, decl := range file.Decls { lineKeys := getValidationKeys(fset, decl.(*ast.FuncDecl), map[string]string{"revel": revel.RevelImportPath}) for k, v := range expectedValidationKeys[i] { if lineKeys[k] != v { t.Errorf("Not found - %d: %v - Actual Map: %v", k, v, lineKeys) } } if len(lineKeys) != len(expectedValidationKeys[i]) { t.Error("Validation key map not the same size as expected:", lineKeys) } } } var TypeExprs = map[string]TypeExpr{ "int": {"int", "", 0, true}, "*int": {"*int", "", 1, true}, "[]int": {"[]int", "", 2, true}, "...int": {"[]int", "", 2, true}, "[]*int": {"[]*int", "", 3, true}, "...*int": {"[]*int", "", 3, true}, "MyType": {"MyType", "pkg", 0, true}, "*MyType": {"*MyType", "pkg", 1, true}, "[]MyType": {"[]MyType", "pkg", 2, true}, "...MyType": {"[]MyType", "pkg", 2, true}, "[]*MyType": {"[]*MyType", "pkg", 3, true}, "...*MyType": {"[]*MyType", "pkg", 3, true}, } func TestTypeExpr(t *testing.T) { for typeStr, expected := range TypeExprs { // Handle arrays and ... myself, since ParseExpr() does not. array := strings.HasPrefix(typeStr, "[]") if array { typeStr = typeStr[2:] } ellipsis := strings.HasPrefix(typeStr, "...") if ellipsis { typeStr = typeStr[3:] } expr, err := parser.ParseExpr(typeStr) if err != nil { t.Error("Failed to parse test expr:", typeStr) continue } if array { expr = &ast.ArrayType{Lbrack: expr.Pos(), Len: nil, Elt: expr} } if ellipsis { expr = &ast.Ellipsis{Ellipsis: expr.Pos(), Elt: expr} } actual := NewTypeExpr("pkg", expr) if !reflect.DeepEqual(expected, actual) { t.Error("Fail, expected", expected, ", was", actual) } } } func TestProcessBookingSource(t *testing.T) { revel.Init("prod", "github.com/revel/examples/booking", "") sourceInfo, err := ProcessSource([]string{revel.AppPath}) if err != nil { t.Fatal("Failed to process booking source with error:", err) } controllerPackage := "github.com/revel/examples/booking/app/controllers" expectedControllerSpecs := []*TypeInfo{ {"GorpController", controllerPackage, "controllers", nil, nil}, {"Application", controllerPackage, "controllers", nil, nil}, {"Hotels", controllerPackage, "controllers", nil, nil}, } if len(sourceInfo.ControllerSpecs()) != len(expectedControllerSpecs) { t.Errorf("Unexpected number of controllers found. Expected %d, Found %d", len(expectedControllerSpecs), len(sourceInfo.ControllerSpecs())) } NEXT_TEST: for _, expected := range expectedControllerSpecs { for _, actual := range sourceInfo.ControllerSpecs() { if actual.StructName == expected.StructName { if actual.ImportPath != expected.ImportPath { t.Errorf("%s expected to have import path %s, actual %s", actual.StructName, expected.ImportPath, actual.ImportPath) } if actual.PackageName != expected.PackageName { t.Errorf("%s expected to have package name %s, actual %s", actual.StructName, expected.PackageName, actual.PackageName) } continue NEXT_TEST } } t.Errorf("Expected to find controller %s, but did not. Actuals: %s", expected.StructName, sourceInfo.ControllerSpecs()) } } func BenchmarkProcessBookingSource(b *testing.B) { revel.Init("", "github.com/revel/examples/booking", "") revel.GetRootLogHandler().Disable() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := ProcessSource(revel.CodePaths) if err != nil { b.Error("Unexpected error:", err) } } }