text: package assertion
  
  import (
  	"fmt"
  	"reflect"
  
  	"github.com/onsi/gomega/types"
  )
  
  type Assertion struct {
  	actualInput interface{}
  	failWrapper *types.GomegaFailWrapper
  	offset      int
  	extra       []interface{}
  }
  
  func New(actualInput interface{}, failWrapper *types.GomegaFailWrapper, offset int, extra ...interface{}) *Assertion {
  	return &Assertion{
  		actualInput: actualInput,
  		failWrapper: failWrapper,
  		offset:      offset,
  		extra:       extra,
  	}
  }
  
  func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  	assertion.failWrapper.TWithHelper.Helper()
  	return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
  }
  
  func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  	assertion.failWrapper.TWithHelper.Helper()
  	return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
  }
  
  func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  	assertion.failWrapper.TWithHelper.Helper()
  	return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...)
  }
  
  func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  	assertion.failWrapper.TWithHelper.Helper()
  	return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
  }
  
  func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool {
  	assertion.failWrapper.TWithHelper.Helper()
  	return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...)
  }
  
  func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string {
  	switch len(optionalDescription) {
  	case 0:
  		return ""
  	case 1:
  		if describe, ok := optionalDescription[0].(func() string); ok {
  			return describe() + "\n"
  		}
  	}
  	return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n"
  }
  
  func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool {
  	matches, err := matcher.Match(assertion.actualInput)
  	assertion.failWrapper.TWithHelper.Helper()
  	if err != nil {
  		description := assertion.buildDescription(optionalDescription...)
  		assertion.failWrapper.Fail(description+err.Error(), 2+assertion.offset)
  		return false
  	}
  	if matches != desiredMatch {
  		var message string
  		if desiredMatch {
  			message = matcher.FailureMessage(assertion.actualInput)
  		} else {
  			message = matcher.NegatedFailureMessage(assertion.actualInput)
  		}
  		description := assertion.buildDescription(optionalDescription...)
  		assertion.failWrapper.Fail(description+message, 2+assertion.offset)
  		return false
  	}
  
  	return true
  }
  
  func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool {
  	success, message := vetExtras(assertion.extra)
  	if success {
  		return true
  	}
  
  	description := assertion.buildDescription(optionalDescription...)
  	assertion.failWrapper.TWithHelper.Helper()
  	assertion.failWrapper.Fail(description+message, 2+assertion.offset)
  	return false
  }
  
  func vetExtras(extras []interface{}) (bool, string) {
  	for i, extra := range extras {
  		if extra != nil {
  			zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface()
  			if !reflect.DeepEqual(zeroValue, extra) {
  				message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra)
  				return false, message
  			}
  		}
  	}
  	return true, ""
  }
  