github.com/jbking/gohan@v0.0.0-20151217002006-b41ccf1c2a96/extension/framework/runner/runner.go (about) 1 // Copyright (C) 2015 NTT Innovation Institute, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package runner 17 18 import ( 19 "fmt" 20 "io/ioutil" 21 "os" 22 "path/filepath" 23 "regexp" 24 25 "github.com/dop251/otto" 26 "github.com/robertkrimen/otto/ast" 27 "github.com/robertkrimen/otto/parser" 28 ) 29 30 const ( 31 // GeneralError denotes runner error not related to tests failures 32 GeneralError = "" 33 ) 34 35 type metaError struct { 36 error 37 } 38 39 // TestRunner abstracts running extension tests from a single file 40 type TestRunner struct { 41 testFileName string 42 setUp bool 43 tearDown bool 44 } 45 46 var setUpPattern = regexp.MustCompile("^setUp$") 47 var tearDownPattern = regexp.MustCompile("^tearDown$") 48 var testPattern = regexp.MustCompile("^test.*") 49 50 // NewTestRunner creates a new test runner for a given test file 51 func NewTestRunner(testFileName string) *TestRunner { 52 return &TestRunner{ 53 testFileName: testFileName, 54 } 55 } 56 57 // Run performs extension tests from the file specified at runner's creation 58 func (runner *TestRunner) Run() map[string]error { 59 src, err := ioutil.ReadFile(runner.testFileName) 60 if err != nil { 61 return map[string]error{ 62 GeneralError: fmt.Errorf("Failed to read file '%s': %s", runner.testFileName, err.Error()), 63 } 64 } 65 66 program, err := parser.ParseFile(nil, runner.testFileName, src, 0) 67 if err != nil { 68 return map[string]error{ 69 GeneralError: fmt.Errorf("Failed to parse file '%s': %s", runner.testFileName, err.Error()), 70 } 71 } 72 tests := []string{} 73 for _, declaration := range program.DeclarationList { 74 if functionDeclaration, ok := declaration.(*ast.FunctionDeclaration); ok { 75 name := functionDeclaration.Function.Name.Name 76 switch { 77 case setUpPattern.MatchString(name): 78 runner.setUp = true 79 case tearDownPattern.MatchString(name): 80 runner.tearDown = true 81 case testPattern.MatchString(name): 82 tests = append(tests, name) 83 } 84 } 85 } 86 87 env := NewEnvironment(runner.testFileName, src) 88 89 directory, _ := os.Getwd() 90 if err := os.Chdir(filepath.Dir(runner.testFileName)); err != nil { 91 return map[string]error{ 92 GeneralError: fmt.Errorf("Failed to change directory to '%s': %s", 93 filepath.Dir(runner.testFileName), 94 err.Error()), 95 } 96 } 97 defer os.Chdir(directory) 98 99 errors := map[string]error{} 100 for _, test := range tests { 101 errors[test] = runner.runTest(test, env) 102 if _, ok := errors[test].(metaError); ok { 103 return map[string]error{ 104 GeneralError: errors[test], 105 } 106 } 107 } 108 109 return errors 110 } 111 112 func (runner *TestRunner) runTest(testName string, env *Environment) (err error) { 113 err = env.InitializeEnvironment() 114 if err != nil { 115 return metaError{err} 116 } 117 defer env.ClearEnvironment() 118 119 if runner.setUp { 120 _, err = env.VM.Call("setUp", nil) 121 if err != nil { 122 return 123 } 124 } 125 126 defer func() { 127 if failed := recover(); failed != nil { 128 if _, ok := failed.(error); ok { 129 err = failed.(error) 130 } else { 131 err = fmt.Errorf("%v", failed) 132 } 133 } 134 }() 135 136 if runner.tearDown { 137 defer func() { 138 _, tearDownError := env.VM.Call("tearDown", nil) 139 if tearDownError != nil && err == nil { 140 err = tearDownError 141 } 142 }() 143 } 144 145 _, err = env.VM.Call(testName, nil) 146 if err != nil { 147 if ottoError, ok := err.(*otto.Error); ok { 148 err = fmt.Errorf(ottoError.String()) 149 } 150 } 151 mockError := env.CheckAllMockCallsMade() 152 if err == nil { 153 err = mockError 154 } 155 return 156 }