github.com/mmatczuk/gohan@v0.0.0-20170206152520-30e45d9bdb69/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 "regexp" 23 24 "github.com/robertkrimen/otto" 25 "github.com/robertkrimen/otto/ast" 26 "github.com/robertkrimen/otto/parser" 27 28 l "github.com/cloudwan/gohan/log" 29 ) 30 31 const ( 32 // GeneralError denotes runner error not related to tests failures 33 GeneralError = "" 34 ) 35 36 // TestRunner abstracts running extension tests from a single file 37 type TestRunner struct { 38 testFileName string 39 printAllLogs bool 40 testFilter *regexp.Regexp 41 42 setUp bool 43 tearDown bool 44 } 45 46 // TestRunnerErrors map[testFunction]error 47 type TestRunnerErrors map[string]error 48 49 type metaError struct { 50 error 51 } 52 53 var setUpPattern = regexp.MustCompile("^setUp$") 54 var tearDownPattern = regexp.MustCompile("^tearDown$") 55 var testPattern = regexp.MustCompile("^test.*") 56 57 // NewTestRunner creates a new test runner for a given test file 58 func NewTestRunner(testFileName string, printAllLogs bool, testFilter string) *TestRunner { 59 return &TestRunner{ 60 testFileName: testFileName, 61 printAllLogs: printAllLogs, 62 testFilter: regexp.MustCompile(testFilter), 63 } 64 } 65 66 // Run performs extension tests from the file specified at runner's creation 67 func (runner *TestRunner) Run() TestRunnerErrors { 68 src, err := ioutil.ReadFile(runner.testFileName) 69 if err != nil { 70 return generalError(fmt.Errorf("Failed to read file '%s': %s", runner.testFileName, err.Error())) 71 } 72 73 program, err := parser.ParseFile(nil, runner.testFileName, src, 0) 74 if err != nil { 75 return generalError(fmt.Errorf("Failed to parse file '%s': %s", runner.testFileName, err.Error())) 76 } 77 tests := []string{} 78 for _, declaration := range program.DeclarationList { 79 if functionDeclaration, ok := declaration.(*ast.FunctionDeclaration); ok { 80 name := functionDeclaration.Function.Name.Name 81 switch { 82 case setUpPattern.MatchString(name): 83 runner.setUp = true 84 case tearDownPattern.MatchString(name): 85 runner.tearDown = true 86 case testPattern.MatchString(name) && runner.testFilter.MatchString(name): 87 tests = append(tests, name) 88 } 89 } 90 } 91 92 env := NewEnvironment(runner.testFileName, src) 93 94 errors := TestRunnerErrors{} 95 for _, test := range tests { 96 errors[test] = runner.runTest(test, env) 97 98 if !runner.printAllLogs { 99 w := l.BufWritter{} 100 if errors[test] != nil { 101 w.Dump(os.Stderr) 102 } 103 w.Reset() 104 } 105 106 if _, ok := errors[test].(metaError); ok { 107 return generalError(errors[test]) 108 } 109 } 110 111 return errors 112 } 113 114 func generalError(err error) TestRunnerErrors { 115 return TestRunnerErrors{ 116 GeneralError: err, 117 } 118 } 119 120 func (runner *TestRunner) runTest(testName string, env *Environment) (err error) { 121 defer func() { 122 runner.printTestResult(testName, err) 123 }() 124 125 err = env.InitializeEnvironment() 126 if err != nil { 127 return metaError{err} 128 } 129 defer env.ClearEnvironment() 130 131 if runner.setUp { 132 _, err = env.VM.Call("setUp", nil) 133 if err != nil { 134 return 135 } 136 } 137 138 defer func() { 139 if failed := recover(); failed != nil { 140 if _, ok := failed.(error); ok { 141 err = failed.(error) 142 } else { 143 err = fmt.Errorf("%v", failed) 144 } 145 } 146 }() 147 148 if runner.tearDown { 149 defer func() { 150 _, tearDownError := env.VM.Call("tearDown", nil) 151 if tearDownError != nil && err == nil { 152 err = tearDownError 153 } 154 }() 155 } 156 157 _, err = env.VM.Call(testName, nil) 158 if err != nil { 159 if ottoError, ok := err.(*otto.Error); ok { 160 err = fmt.Errorf(ottoError.String()) 161 } 162 } 163 mockError := env.CheckAllMockCallsMade() 164 if err == nil { 165 err = mockError 166 } 167 return 168 } 169 170 func (runner *TestRunner) printTestResult(testName string, testErr error) { 171 if testErr != nil { 172 log.Error(fmt.Sprintf("\t FAIL (%s:%s): %s", 173 runner.testFileName, testName, testErr.Error())) 174 } else { 175 log.Notice("\t PASS (%s:%s)", 176 runner.testFileName, testName) 177 } 178 }