Exemple #1
0
/*
	'actual' should be an `*errors.Error`; 'expected' should be an `*errors.ErrorClass`;
	we'll check that the error is under the umbrella of the error class.
*/
func ShouldBeErrorClass(actual interface{}, expected ...interface{}) string {
	err, ok := actual.(error)
	if !ok {
		return fmt.Sprintf("You must provide an `error` as the first argument to this assertion; got `%T`", actual)
	}

	var class *errors.ErrorClass
	switch len(expected) {
	case 0:
		return "You must provide a spacemonkey `ErrorClass` as the expectation parameter to this assertion."
	case 1:
		cls, ok := expected[0].(*errors.ErrorClass)
		if !ok {
			return "You must provide a spacemonkey `ErrorClass` as the expectation parameter to this assertion."
		}
		class = cls
	default:
		return "You must provide one parameter as an expectation to this assertion."
	}

	// checking if this is nil is surprisingly complicated due to https://golang.org/doc/faq#nil_error
	if reflect.ValueOf(err).IsNil() {
		return fmt.Sprintf("Expected error to be of class %q but it was nil!", class.String())
	}

	spaceClass := errors.GetClass(err)
	if spaceClass.Is(class) {
		return ""
	}
	return fmt.Sprintf("Expected error to be of class %q but it had %q instead!  (Full message: %s)", class.String(), spaceClass.String(), err.Error())
}
Exemple #2
0
// GetErrorBody will return the user-visible error message given an error.
// The message will be determined by errors.GetMessage() unless the error class
// has an error body overridden by OverrideErrorBody.
func GetErrorBody(err error) string {
	rv := errors.GetData(err, errorBody)
	message, ok := rv.(string)
	if !ok {
		return errors.GetMessage(err)
	}
	class := errors.GetClass(err)
	if class == nil {
		return message
	}
	return fmt.Sprintf("%s: %s", class.String(), message)
}
Exemple #3
0
// Finish records a successful task completion. You must pass a pointer to
// the named error return value (or nil if there isn't one) and the result
// of recover() out of the method that was deferred for this to work right.
// Finish will re-panic any recovered panics (provided it wasn't a nil panic)
// after bookkeeping.
func (c *TaskCtx) Finish(err_ref *error, rec interface{}) {
	duration_nanoseconds := int64(c.ElapsedTime())
	var error_name string
	var err error
	if err_ref != nil {
		err = *err_ref
	}
	if rec != nil {
		var ok bool
		err, ok = rec.(error)
		if !ok || err == nil {
			err = errors.PanicError.New("%v", rec)
		}
	}
	if err != nil {
		error_name = errors.GetClass(err).String()
		max_len := Config.MaxErrorLength
		if len(error_name) > max_len {
			error_name = error_name[:max_len]
		}
		error_name = SanitizeName(error_name)
	}

	// we keep granularity on the order microseconds, which should keep
	// sum_squared useful
	duration_microseconds := int64(duration_nanoseconds /
		microsecondInNanoseconds)

	c.monitor.mtx.Lock()
	c.monitor.current -= 1
	c.monitor.total_completed += 1
	delete(c.monitor.running, c)
	if err != nil {
		c.monitor.errors[error_name] += 1
		if rec != nil {
			c.monitor.panics += 1
		}
		c.monitor.error_timing.Add(duration_microseconds)
	} else {
		c.monitor.success_timing.Add(duration_microseconds)
		c.monitor.success += 1
	}
	c.monitor.mtx.Unlock()
	c.monitor.total_timing.Add(duration_microseconds)

	// doh, we didn't actually want to stop the panic codepath.
	// we have to repanic. Oh and great, panics can be nil. Welp!
	if rec != nil {
		panic(rec)
	}
}
Exemple #4
0
func (f *FuncStats) end(err error, panicked bool, duration time.Duration) {
	atomic.AddInt64(&f.current, -1)
	f.parentsAndMutex.Lock()
	if panicked {
		f.panics -= 1
		f.failureTimes.Insert(duration)
		f.parentsAndMutex.Unlock()
		return
	}
	if err == nil {
		f.successTimes.Insert(duration)
		f.parentsAndMutex.Unlock()
		return
	}
	f.failureTimes.Insert(duration)
	f.errors[errors.GetClass(err).String()] += 1
	f.parentsAndMutex.Unlock()
}
Exemple #5
0
/*
	'actual' should be a `func()`; 'expected' should be an `*errors.ErrorClass`;
	we'll run the function, and check that it panics, and that the error is under the umbrella of the error class.
*/
func ShouldPanicWith(actual interface{}, expected ...interface{}) string {
	fn, ok := actual.(func())
	if !ok {
		return fmt.Sprintf("You must provide a `func()` as the first argument to this assertion; got `%T`", actual)
	}

	var errClass *errors.ErrorClass
	switch len(expected) {
	case 0:
		return "You must provide a spacemonkey `ErrorClass` as the expectation parameter to this assertion."
	case 1:
		cls, ok := expected[0].(*errors.ErrorClass)
		if !ok {
			return "You must provide a spacemonkey `ErrorClass` as the expectation parameter to this assertion."
		}
		errClass = cls
	default:
		return "You must provide one parameter as an expectation to this assertion."
	}

	var caught error
	try.Do(
		fn,
	).CatchAll(func(err error) {
		caught = err
	}).Done()

	if caught == nil {
		return fmt.Sprintf("Expected error to be of class %q but no error was raised!", errClass.String())
	}
	spaceClass := errors.GetClass(caught)
	if spaceClass.Is(errClass) {
		return ""
	}
	return fmt.Sprintf("Expected error to be of class %q but it had %q instead!  (Full message: %s)", errClass.String(), spaceClass.String(), caught.Error())
}