(ns record-instance-equality-test
  (:require [clojure.test :refer :all]))

;;; Set up protocal and records
(defprotocol FooBar (clone [this]) (switch [this]))
(defrecord Foo [])
(defrecord Bar [])
(extend-type Foo FooBar (clone [this] (map->Foo this)) (switch [this] (map->Bar this)))
(extend-type Bar FooBar (clone [this] (map->Bar this)) (switch [this] (map->Foo this)))

;;; define test
(deftest run
  (let [;; Create 4 (.equal) instances of Bar, all works as expected
        foo0              (->Foo)
        bar0              (->Bar)
        bar1              (->Bar)
        bar-switch-foo0   (switch foo0)
        bar-clone-bar0    (clone bar0)

        ;; Create 4 (.equal) instances of Bar with an added field, unexpected results
        x-foo0            (map->Foo {:field "xtra"})
        x-bar0            (map->Bar {:field "xtra"})
        x-bar1            (map->Bar {:field "xtra"})
        bar-switch-x-foo0 (switch x-foo0)
        bar-clone-x-bar0  (clone x-bar0)]
    
    (is (= bar0 bar1))                                  ; gets expected true
    (is (= bar0 bar-switch-foo0))                       ; gets expected true
    (is (= bar0 bar-clone-bar0))                        ; gets expected true
    (is (= x-bar0 x-bar1))                              ; gets expected true
    (is (= x-bar0 bar-switch-x-foo0))                   ; gets UNEXPECTED
    (is (= x-bar0 bar-clone-x-bar0))                    ; gets UNEXPECTED
    (is (= bar-switch-x-foo0 bar-clone-x-bar0))         ; gets UNEXPECTED
    (is (.equals x-bar0 bar-switch-x-foo0))             ; gets expected true
    (is (.equals x-bar0 bar-clone-x-bar0))              ; gets expected true
    (is (.equals bar-switch-x-foo0 bar-clone-x-bar0)))) ; gets expected true

