diff --git a/testcases/datastructures/AVLTree.scala b/testcases/datastructures/AVLTree.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9c880c0bf81ceb2878c034e002ed3cf6cde2b34f
--- /dev/null
+++ b/testcases/datastructures/AVLTree.scala
@@ -0,0 +1,213 @@
+/* Copyright 2009-2013 EPFL, Lausanne 
+ *
+ * Author: Manos (modified by Ravi)
+ * Date: 20.11.2013
+ **/
+
+import leon.Utils._
+
+object AVLTree  {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(left : Tree, value : Int, right: Tree, rank : Int) extends Tree
+
+  sealed abstract class OptionInt
+  case class None() extends OptionInt
+  case class Some(i:Int) extends OptionInt
+
+
+  def smallerOption(o1:OptionInt,o2:OptionInt) : Boolean  = {
+    (o1,o2) match {
+      case (Some(i1), Some(i2)) => i1 < i2
+      case (_,_) => true
+    }
+  }
+
+  def minOption(o1:OptionInt,o2:OptionInt) : OptionInt = (
+    (o1,o2) match {
+      case (Some(i1), Some(i2)) => Some(if (i1<=i2) i1 else i2)
+      case (Some(_), _) => o1
+      case (_, Some(_)) => o2
+      case _ => None()
+    }
+  )
+  
+  def maxOption(o1:OptionInt,o2:OptionInt) : OptionInt = (
+    (o1,o2) match {
+      case (Some(i1), Some(i2)) => Some(if (i1>=i2) i1 else i2)
+      case (Some(_), _) => o1
+      case (_, Some(_)) => o2
+      case _ => None()
+    }
+  )
+
+  def min(i1:Int, i2:Int) : Int = if (i1<=i2) i1 else i2
+  def max(i1:Int, i2:Int) : Int = if (i1>=i2) i1 else i2
+
+  def rank(t: Tree) : Int = {
+    t match {
+      case Leaf() => 0
+      case Node(_,_,_,rk) => rk
+    }
+  }
+
+  def size(t: Tree): Int = {
+    (t match {
+      case Leaf() => 0
+      case Node(l, _, r,_) => size(l) + 1 + size(r)
+    })
+  } ensuring (_ >= 0)
+  
+  def height(t: Tree): Int = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r, _) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  } ensuring(_ >= 0)
+
+  def treeMax(t:Tree) : OptionInt = {
+    t match {
+      case Leaf()      => None()
+      case Node(l,v,r,_) => maxOption(Some(v), maxOption (treeMax(l), treeMax(r)))
+    }
+  }
+
+  def treeMin(t:Tree) : OptionInt = {
+    t match {
+      case Leaf()      => None()
+      case Node(l,v,r,_) => minOption(Some(v), minOption (treeMin(l), treeMin(r)))
+    }
+  }
+
+  
+  def isBST(t:Tree) : Boolean = {
+    t match {
+      case Leaf() => true
+      case Node(l,v,r,_) => 
+        if (isBST(l) && isBST(r)) {
+          smallerOption(Some(v),bstMin(r)) && 
+          smallerOption(bstMax(l),Some(v))
+        }
+        else false 
+    }
+  }
+
+  def rankHeight(t: Tree) : Boolean = t match {
+    case Leaf() => true 
+    case Node(l,_,r,rk) => rankHeight(l) && rankHeight(r) && rk == height(t)
+  }
+  
+  def balanceFactor(t : Tree) : Int = {
+    t match{
+      case Leaf() => 0
+      case Node(l, _, r, _) => rank(l) - rank(r)
+    }
+  } 
+
+  def isAVL(t:Tree) : Boolean = {    
+    t match {
+        case Leaf() => true        
+        case Node(l,_,r,rk) =>  isAVL(l) && isAVL(r) && balanceFactor(t) >= -1 && balanceFactor(t) <= 1 && rankHeight(t) //isBST(t) && 
+      }    
+  } 
+
+ def bstMax(t:Tree) : OptionInt = {
+    require(isBST(t))
+    t match {
+      case Leaf() => None() 
+      case Node(_,v,Leaf(),_) => Some(v) 
+      case Node(_,_,r,_)      => bstMax(r)
+    }
+  } ensuring (res => res == treeMax(t))
+
+  def bstMin(t:Tree) : OptionInt = {
+    require(isBST(t))
+    t match {
+      case Leaf() => None()
+      case Node(Leaf(),v,_,_) => Some(v) 
+      case Node(l, _ ,_ ,_) => bstMin(l)
+    }
+  } ensuring (res => res == treeMin(t))
+  
+  def offByOne(t : Tree) : Boolean = {
+    t match {
+      case Leaf() => true
+      case Node(l,_,r,_) => isAVL(l) && isAVL(r) && balanceFactor(t) >= -2 && balanceFactor(t) <= 2 
+    }
+  }
+ 
+  def unbalancedInsert(t: Tree, e : Int) : Tree = {
+    require(isAVL(t))
+    t match {
+      case Leaf() => Node(Leaf(), e, Leaf(), 1)
+      case Node(l,v,r,h) => 
+             if (e == v) t
+        else if (e <  v){
+          val newl = avlInsert(l,e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        } 
+        else {
+          val newr = avlInsert(r,e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }            
+    }
+  } 
+                    
+  def avlInsert(t: Tree, e : Int) : Tree = {    
+    require(isAVL(t))
+    
+    balance(unbalancedInsert(t,e))
+    
+  } ensuring(res => isAVL(res) && rank(res) >= rank(t) && rank(res) <= rank(t) + 1 && size(res) <= size(t) + 1)
+     
+  def balance(t:Tree) : Tree = {
+    require(rankHeight(t) && offByOne(t)) //isBST(t) && 
+    t match {
+      case Leaf() => Leaf() // impossible...
+      case Node(l, v, r, h) => 
+        val bfactor = balanceFactor(t)
+        // at this point, the tree is unbalanced
+        if(bfactor > 1 ) { // left-heavy
+          val newL = 
+            if (balanceFactor(l) < 0) { // l is right heavy
+              rotateLeft(l)
+            }
+            else l
+          rotateRight(Node(newL,v,r, max(rank(newL), rank(r)) + 1))
+        }
+        else if(bfactor < -1) {
+          val newR = 
+            if (balanceFactor(r) > 0) { // r is left heavy
+              rotateRight(r)
+            }
+            else r
+          rotateLeft(Node(l,v,newR, max(rank(newR), rank(l)) + 1))
+        } else t        
+      } 
+  } ensuring(isAVL(_))
+
+  def rotateRight(t:Tree) = {    
+    t match {
+      case Node(Node(ll, vl, rl, _),v,r, _) =>
+        
+        val hr = max(rank(rl),rank(r)) + 1        
+        Node(ll, vl, Node(rl,v,r,hr), max(rank(ll),hr) + 1)
+        
+      case _ => t // this should not happen
+  } }
+   
+ 
+  def rotateLeft(t:Tree) =  {    
+    t match {
+      case Node(l, v, Node(lr,vr,rr,_), _) => 
+                
+        val hl = max(rank(l),rank(lr)) + 1        
+        Node(Node(l,v,lr,hl), vr, rr, max(hl, rank(rr)) + 1)
+      case _ => t // this should not happen
+  } } 
+}
+