func (j *Job) Run() { // If the job panics, just print a stack trace. // Don't let the whole process die. defer func() { if err := recover(); err != nil { if revelError := revel.NewErrorFromPanic(err); revelError != nil { revel.ERROR.Print(err, "\n", revelError.Stack) } else { revel.ERROR.Print(err, "\n", string(debug.Stack())) } } }() if !selfConcurrent { j.running.Lock() defer j.running.Unlock() } if workPermits != nil { workPermits <- struct{}{} defer func() { <-workPermits }() } atomic.StoreUint32(&j.status, 1) defer atomic.StoreUint32(&j.status, 0) j.inner.Run() }
// Run runs a single test, given by the argument. func (c TestRunner) Run(suite, test string) revel.Result { result := TestResult{Name: test} for _, testSuite := range revel.TestSuites { t := reflect.TypeOf(testSuite).Elem() if t.Name() != suite { continue } // Found the suite, create a new instance and run the named method. v := reflect.New(t) func() { defer func() { if err := recover(); err != nil { error := revel.NewErrorFromPanic(err) if error == nil { result.ErrorHtml = template.HTML(html.EscapeString(fmt.Sprint(err))) } else { var buffer bytes.Buffer tmpl, _ := revel.MainTemplateLoader.Template("TestRunner/FailureDetail.html") tmpl.Render(&buffer, error) result.ErrorSummary = errorSummary(error) result.ErrorHtml = template.HTML(buffer.String()) } } }() // Initialize the test suite with a NewTestSuite() testSuiteInstance := v.Elem().FieldByName("TestSuite") testSuiteInstance.Set(reflect.ValueOf(revel.NewTestSuite())) // Call Before(), call the test, and call After(). if m := v.MethodByName("Before"); m.IsValid() { m.Call(NONE) } if m := v.MethodByName("After"); m.IsValid() { defer m.Call(NONE) } v.MethodByName(test).Call(NONE) // No panic means success. result.Passed = true }() break } return c.RenderJson(result) }
// This function handles a panic in a json API action invocation. // It cleans up the stack trace, logs it, and responds with an error json message. func handleInvocationPanicJson(c *revel.Controller, err interface{}) { // User Initiated panic with error response doesn't need to print the whole stack trace. if errResponse, ok := err.(*JsonErrorResponder); ok { c.Result = JsonErrorResult{errResponse} } else if errResponse, ok := err.(JsonErrorResponder); ok { c.Result = JsonErrorResult{&errResponse} } else { // System initiated panic. Use a JSON error response as we shouldn't // be returning HTML for a JSON defined API. error := revel.NewErrorFromPanic(err) revel.ERROR.Print(err, "\n", error.Stack) if error == nil { revel.ERROR.Print(err, "\n", string(debug.Stack())) } else { revel.ERROR.Print(err, "\n", error.Stack) } var JsonErrorResponder = PanicResponseFactory(err) c.Result = JsonErrorResult{&JsonErrorResponder} } }