                  movements (gen/vector (gen-next key-len))] ;; TODO use gen-movement once Treeterator supports seek
                 (run-trie-tree-prop min-keys key-len actions movements)))
 
+(defn run-self-join-prop [min-keys key-len actions movements]
+  (let [tree (apply-to-tree (tree min-keys key-len) actions)
+        iterator-results (apply-to-iterator (iterator tree) movements)
+        iterator-a (trieterator (iterator tree))
+        iterator-b (trieterator (iterator tree))
+        join-results (apply-to-iterator
+                      (treeterator (join #js [iterator-a iterator-b] key-len #js [(into-array (range key-len)) (into-array (range key-len))]))
+                      movements)]
+    (= iterator-results join-results)))
+
+(defn self-join-prop [key-len]
+  (prop/for-all [min-keys gen/s-pos-int
+                 actions (gen/vector (gen-action key-len))
+                 movements (gen/vector (gen-next key-len))] ;; TODO use gen-movement once Treeterator supports seek
+                (run-self-join-prop min-keys key-len actions movements)))
+
+(run-trie-tree-prop 1 3 [[:assoc! #js [-86 90 "-9"] #js [-77 20 -16]] [:assoc! #js [-64 90 -44] #js [7 -8 -47]]] [[:next]])
+
 (comment
   (dc/quick-check 1000 (least-prop 1))
   (dc/quick-check 1000 (least-prop 2))

  (assert (> num-vars 0))
  (dotimes [i (alength iterators)]
    (let [iterator-vars (aget iterator->vars i)]
      (assert (== (alength iterator-vars) (.key-len (aget iterators i))))
      (dotimes [j (alength iterator-vars)]
        (assert (< (aget iterator-vars j) num-vars)))))
  (let [var->iterators #js []

  ;; cljs.core.pr_str(cemerick.double_check.quick_check(1000, aurora.btree.intersection_prop))
  (dc/quick-check 10000 (trie-tree-prop 1))
  (dc/quick-check 10000 (trie-tree-prop 2))
  (dc/quick-check 10000 (trie-tree-prop 3))
  (dc/quick-check 100 (self-join-prop 1))
  (dc/quick-check 100 (self-join-prop 2))
  (dc/quick-check 100 (self-join-prop 3))


  (defn f []
