| package assertions |
| |
| import "reflect" |
| |
| type equalityMethodSpecification struct { |
| a interface{} |
| b interface{} |
| |
| aType reflect.Type |
| bType reflect.Type |
| |
| equalMethod reflect.Value |
| } |
| |
| func newEqualityMethodSpecification(a, b interface{}) *equalityMethodSpecification { |
| return &equalityMethodSpecification{ |
| a: a, |
| b: b, |
| } |
| } |
| |
| func (this *equalityMethodSpecification) IsSatisfied() bool { |
| if !this.bothAreSameType() { |
| return false |
| } |
| if !this.typeHasEqualMethod() { |
| return false |
| } |
| if !this.equalMethodReceivesSameTypeForComparison() { |
| return false |
| } |
| if !this.equalMethodReturnsBool() { |
| return false |
| } |
| return true |
| } |
| |
| func (this *equalityMethodSpecification) bothAreSameType() bool { |
| this.aType = reflect.TypeOf(this.a) |
| if this.aType == nil { |
| return false |
| } |
| if this.aType.Kind() == reflect.Ptr { |
| this.aType = this.aType.Elem() |
| } |
| this.bType = reflect.TypeOf(this.b) |
| return this.aType == this.bType |
| } |
| func (this *equalityMethodSpecification) typeHasEqualMethod() bool { |
| aInstance := reflect.ValueOf(this.a) |
| this.equalMethod = aInstance.MethodByName("Equal") |
| return this.equalMethod != reflect.Value{} |
| } |
| |
| func (this *equalityMethodSpecification) equalMethodReceivesSameTypeForComparison() bool { |
| signature := this.equalMethod.Type() |
| return signature.NumIn() == 1 && signature.In(0) == this.aType |
| } |
| |
| func (this *equalityMethodSpecification) equalMethodReturnsBool() bool { |
| signature := this.equalMethod.Type() |
| return signature.NumOut() == 1 && signature.Out(0) == reflect.TypeOf(true) |
| } |
| |
| func (this *equalityMethodSpecification) AreEqual() bool { |
| a := reflect.ValueOf(this.a) |
| b := reflect.ValueOf(this.b) |
| return areEqual(a, b) && areEqual(b, a) |
| } |
| func areEqual(receiver reflect.Value, argument reflect.Value) bool { |
| equalMethod := receiver.MethodByName("Equal") |
| argumentList := []reflect.Value{argument} |
| result := equalMethod.Call(argumentList) |
| return result[0].Bool() |
| } |