Merge pull request #133 from tjarratt/be-identical-to-matcher

Add BeIdenticalTo matcher
diff --git a/matchers.go b/matchers.go
index afb7720..12d2b96 100644
--- a/matchers.go
+++ b/matchers.go
@@ -26,6 +26,15 @@
 	}
 }
 
+//BeIdenticalTo uses the == operator to compare actual with expected.
+//BeIdenticalTo is strict about types when performing comparisons.
+//It is an error for both actual and expected to be nil.  Use BeNil() instead.
+func BeIdenticalTo(expected interface{}) types.GomegaMatcher {
+	return &matchers.BeIdenticalToMatcher{
+		Expected: expected,
+	}
+}
+
 //BeNil succeeds if actual is nil
 func BeNil() types.GomegaMatcher {
 	return &matchers.BeNilMatcher{}
diff --git a/matchers/be_identical_to.go b/matchers/be_identical_to.go
new file mode 100644
index 0000000..fdcda4d
--- /dev/null
+++ b/matchers/be_identical_to.go
@@ -0,0 +1,37 @@
+package matchers
+
+import (
+	"fmt"
+	"runtime"
+
+	"github.com/onsi/gomega/format"
+)
+
+type BeIdenticalToMatcher struct {
+	Expected interface{}
+}
+
+func (matcher *BeIdenticalToMatcher) Match(actual interface{}) (success bool, matchErr error) {
+	if actual == nil && matcher.Expected == nil {
+		return false, fmt.Errorf("Refusing to compare <nil> to <nil>.\nBe explicit and use BeNil() instead.  This is to avoid mistakes where both sides of an assertion are erroneously uninitialized.")
+	}
+
+	defer func() {
+		if r := recover(); r != nil {
+			if _, ok := r.(runtime.Error); ok {
+				success = false
+				matchErr = nil
+			}
+		}
+	}()
+
+	return actual == matcher.Expected, nil
+}
+
+func (matcher *BeIdenticalToMatcher) FailureMessage(actual interface{}) string {
+	return format.Message(actual, "to be identical to", matcher.Expected)
+}
+
+func (matcher *BeIdenticalToMatcher) NegatedFailureMessage(actual interface{}) string {
+	return format.Message(actual, "not to be identical to", matcher.Expected)
+}
diff --git a/matchers/be_identical_to_test.go b/matchers/be_identical_to_test.go
new file mode 100644
index 0000000..8b90a1a
--- /dev/null
+++ b/matchers/be_identical_to_test.go
@@ -0,0 +1,61 @@
+package matchers_test
+
+import (
+	"errors"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	. "github.com/onsi/gomega/matchers"
+)
+
+var _ = Describe("BeIdenticalTo", func() {
+	Context("when asserting that nil equals nil", func() {
+		It("should error", func() {
+			success, err := (&BeIdenticalToMatcher{Expected: nil}).Match(nil)
+
+			Ω(success).Should(BeFalse())
+			Ω(err).Should(HaveOccurred())
+		})
+	})
+
+	It("should treat the same pointer to a struct as identical", func() {
+		mySpecialStruct := myCustomType{}
+		Ω(&mySpecialStruct).Should(BeIdenticalTo(&mySpecialStruct))
+		Ω(&myCustomType{}).ShouldNot(BeIdenticalTo(&mySpecialStruct))
+	})
+
+	It("should be strict about types", func() {
+		Ω(5).ShouldNot(BeIdenticalTo("5"))
+		Ω(5).ShouldNot(BeIdenticalTo(5.0))
+		Ω(5).ShouldNot(BeIdenticalTo(3))
+	})
+
+	It("should treat primtives as identical", func() {
+		Ω("5").Should(BeIdenticalTo("5"))
+		Ω("5").ShouldNot(BeIdenticalTo("55"))
+
+		Ω(5.55).Should(BeIdenticalTo(5.55))
+		Ω(5.55).ShouldNot(BeIdenticalTo(6.66))
+
+		Ω(5).Should(BeIdenticalTo(5))
+		Ω(5).ShouldNot(BeIdenticalTo(55))
+	})
+
+	It("should treat the same pointers to a slice as identical", func() {
+		mySlice := []int{1, 2}
+		Ω(&mySlice).Should(BeIdenticalTo(&mySlice))
+		Ω(&mySlice).ShouldNot(BeIdenticalTo(&[]int{1, 2}))
+	})
+
+	It("should treat the same pointers to a map as identical", func() {
+		myMap := map[string]string{"a": "b", "c": "d"}
+		Ω(&myMap).Should(BeIdenticalTo(&myMap))
+		Ω(myMap).ShouldNot(BeIdenticalTo(map[string]string{"a": "b", "c": "d"}))
+	})
+
+	It("should treat the same pointers to an error as identical", func() {
+		myError := errors.New("foo")
+		Ω(&myError).Should(BeIdenticalTo(&myError))
+		Ω(errors.New("foo")).ShouldNot(BeIdenticalTo(errors.New("bar")))
+	})
+})