[libgee] Split SortedMap/SortedSet into bi-directional and uni-directional parts



commit 499974fd675ccfd94047f48ed970cf6535e7b111
Author: Maciej Piechotka <uzytkownik2 gmail com>
Date:   Wed Mar 28 00:29:05 2012 +0200

    Split SortedMap/SortedSet into bi-directional and uni-directional parts

 gee/Makefile.am                 |    6 +
 gee/abstractbidirsortedmap.vala |   53 +++++
 gee/abstractbidirsortedset.vala |   53 +++++
 gee/abstractsortedset.vala      |   11 +-
 gee/bidirsortedmap.vala         |   45 ++++
 gee/bidirsortedset.vala         |   46 ++++
 gee/readonlybidirsortedmap.vala |   71 +++++++
 gee/readonlybidirsortedset.vala |   71 +++++++
 gee/readonlysortedmap.vala      |   29 ---
 gee/readonlysortedset.vala      |   33 +---
 gee/sortedmap.vala              |   12 +-
 gee/sortedset.vala              |   10 +-
 gee/treemap.vala                |  130 +++++-------
 gee/treeset.vala                |    8 +-
 tests/Makefile.am               |    2 +
 tests/testbidirsortedmap.vala   |  430 +++++++++++++++++++++++++++++++++++++++
 tests/testbidirsortedset.vala   |  275 +++++++++++++++++++++++++
 tests/testsortedmap.vala        |  298 ++-------------------------
 tests/testsortedset.vala        |  173 +---------------
 tests/testtreemap.vala          |    2 +-
 tests/testtreeset.vala          |    2 +-
 21 files changed, 1158 insertions(+), 602 deletions(-)
---
diff --git a/gee/Makefile.am b/gee/Makefile.am
index 1da2b39..be270bf 100644
--- a/gee/Makefile.am
+++ b/gee/Makefile.am
@@ -7,6 +7,8 @@ lib_LTLIBRARIES = \
 libgee_0_8_la_SOURCES = \
 	assemblyinfo.vala \
 	abstractbidirlist.vala \
+	abstractbidirsortedset.vala \
+	abstractbidirsortedmap.vala \
 	abstractcollection.vala \
 	abstractlist.vala \
 	abstractmap.vala \
@@ -22,6 +24,8 @@ libgee_0_8_la_SOURCES = \
 	bidirlist.vala \
 	bidirlistiterator.vala \
 	bidirmapiterator.vala \
+	bidirsortedset.vala \
+	bidirsortedmap.vala \
 	collection.vala \
 	comparable.vala \
 	concurrentlist.vala \
@@ -46,6 +50,8 @@ libgee_0_8_la_SOURCES = \
 	priorityqueue.vala \
 	queue.vala \
 	readonlybidirlist.vala \
+	readonlybidirsortedset.vala \
+	readonlybidirsortedmap.vala \
 	readonlycollection.vala \
 	readonlylist.vala \
 	readonlymap.vala \
diff --git a/gee/abstractbidirsortedmap.vala b/gee/abstractbidirsortedmap.vala
new file mode 100644
index 0000000..d399d1a
--- /dev/null
+++ b/gee/abstractbidirsortedmap.vala
@@ -0,0 +1,53 @@
+/* abstractbidirsortedmap.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+/**
+ * Skeletal implementation of the { link BidirSortedSet} interface.
+ *
+ * Contains common code shared by all set implementations.
+ *
+ * @see TreeSet
+ */
+public abstract class Gee.AbstractBidirSortedMap<K,V> : Gee.AbstractSortedMap<K,V>, BidirSortedMap<K,V> {
+	/**
+	 * { inheritDoc}
+	 */
+	public abstract BidirMapIterator<K,V> bidir_map_iterator ();
+
+	private weak BidirSortedMap<K,V> _read_only_view;
+
+	/**
+	 * { inheritDoc}
+	 */
+	public virtual new BidirSortedMap<K,V> read_only_view {
+		owned get {
+			BidirSortedMap<K,V> instance = _read_only_view;
+			if (_read_only_view == null) {
+				instance = new ReadOnlyBidirSortedMap<K,V> (this);
+				_read_only_view = instance;
+				instance.add_weak_pointer ((void**) (&_read_only_view));
+			}
+			return instance;
+		}
+	}
+}
+
diff --git a/gee/abstractbidirsortedset.vala b/gee/abstractbidirsortedset.vala
new file mode 100644
index 0000000..5ea426d
--- /dev/null
+++ b/gee/abstractbidirsortedset.vala
@@ -0,0 +1,53 @@
+/* abstractbidirsortedset.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+/**
+ * Skeletal implementation of the { link BidirSortedSet} interface.
+ *
+ * Contains common code shared by all set implementations.
+ *
+ * @see TreeSet
+ */
+public abstract class Gee.AbstractBidirSortedSet<G> : Gee.AbstractSortedSet<G>, BidirSortedSet<G> {
+	/**
+	 * { inheritDoc}
+	 */
+	public abstract BidirIterator<G> bidir_iterator ();
+
+	private weak BidirSortedSet<G> _read_only_view;
+
+	/**
+	 * { inheritDoc}
+	 */
+	public virtual new BidirSortedSet<G> read_only_view {
+		owned get {
+			BidirSortedSet<G> instance = _read_only_view;
+			if (_read_only_view == null) {
+				instance = new ReadOnlyBidirSortedSet<G> (this);
+				_read_only_view = instance;
+				instance.add_weak_pointer ((void**) (&_read_only_view));
+			}
+			return instance;
+		}
+	}
+}
+
diff --git a/gee/abstractsortedset.vala b/gee/abstractsortedset.vala
index 7663d72..44c3b89 100644
--- a/gee/abstractsortedset.vala
+++ b/gee/abstractsortedset.vala
@@ -41,12 +41,7 @@ public abstract class Gee.AbstractSortedSet<G> : Gee.AbstractSet<G>, SortedSet<G
 	/**
 	 * { inheritDoc}
 	 */
-	public abstract BidirIterator<G> bidir_iterator ();
-
-	/**
-	 * { inheritDoc}
-	 */
-	public abstract BidirIterator<G>? iterator_at (G element);
+	public abstract Iterator<G>? iterator_at (G element);
 
 	/**
 	 * { inheritDoc}
@@ -82,9 +77,9 @@ public abstract class Gee.AbstractSortedSet<G> : Gee.AbstractSet<G>, SortedSet<G
 	 * { inheritDoc}
 	 */
 	public abstract SortedSet<G> sub_set (G from, G to);
-	
+
 	private weak SortedSet<G> _read_only_view;
-	
+
 	/**
 	 * { inheritDoc}
 	 */
diff --git a/gee/bidirsortedmap.vala b/gee/bidirsortedmap.vala
new file mode 100644
index 0000000..67c1e8f
--- /dev/null
+++ b/gee/bidirsortedmap.vala
@@ -0,0 +1,45 @@
+/* bidirsortedmap.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+public interface Gee.BidirSortedMap<K,V> : SortedMap<K,V> {
+	/**
+	 * Returns a bi-directional iterator for this map.
+	 *
+	 * @return a bi-directional map iterator
+	 */
+	public abstract BidirMapIterator<K,V> bidir_map_iterator ();
+
+	/**
+	 * The read-only view of this set.
+	 */
+	public abstract new BidirSortedMap<K,V> read_only_view { owned get; }
+
+	/**
+	 * Returns an immutable empty sorted set.
+	 *
+	 * @return an immutable empty sorted set
+	 */
+	public static BidirSortedMap<K,V> empty<K,V> () {
+		return new TreeMap<K,V> ().read_only_view;
+	}
+}
+
diff --git a/gee/bidirsortedset.vala b/gee/bidirsortedset.vala
new file mode 100644
index 0000000..d068b25
--- /dev/null
+++ b/gee/bidirsortedset.vala
@@ -0,0 +1,46 @@
+/* sortedset.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+public interface Gee.BidirSortedSet<G> : SortedSet<G> {
+	/**
+	 * Returns a { link BidirIterator} that can be used for bi-directional
+	 * iteration over this sorted set.
+	 *
+	 * @return a { link BidirIterator} over this sorted set
+	 */
+	public abstract BidirIterator<G> bidir_iterator ();
+
+	/**
+	 * The read-only view of this set.
+	 */
+	public abstract new BidirSortedSet<G> read_only_view { owned get; }
+
+	/**
+	 * Returns an immutable empty sorted set.
+	 *
+	 * @return an immutable empty sorted set
+	 */
+	public static BidirSortedSet<G> empty<G> () {
+		return new TreeSet<G> ().read_only_view;
+	}
+}
+
diff --git a/gee/readonlybidirsortedmap.vala b/gee/readonlybidirsortedmap.vala
new file mode 100644
index 0000000..95c0327
--- /dev/null
+++ b/gee/readonlybidirsortedmap.vala
@@ -0,0 +1,71 @@
+/* readonlybidirsortedmap.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+/**
+ * Read-only view for { link BidirSortedMap} collections.
+ *
+ * This class decorates any class which implements the { link BidirSortedMap}
+ * interface by making it read only. Any method which normally modify data will
+ * throw an error.
+ *
+ * @see BidirSortedMap
+ */
+internal class Gee.ReadOnlyBidirSortedMap<K,V> : ReadOnlySortedMap<K,V>, BidirSortedMap<K,V> {
+	/**
+	 * Constructs a read-only map that mirrors the content of the specified map.
+	 *
+	 * @param set the set to decorate.
+	 */
+	public ReadOnlyBidirSortedMap (BidirSortedMap<K,V> map) {
+		base (map);
+	}
+
+	/**
+	 * { inheritDoc}
+	 */
+	public Gee.BidirMapIterator<K,V> bidir_map_iterator () {
+		return new BidirMapIterator<K,V> ((_map as BidirSortedMap<K,V>).bidir_map_iterator ());
+	}
+
+	protected class BidirMapIterator<K,V> : Gee.ReadOnlyMap.MapIterator<K,V>, Gee.BidirMapIterator<K,V> {
+		public BidirMapIterator (Gee.BidirMapIterator<K,V> iterator) {
+			base (iterator);
+		}
+
+		public bool first () {
+			return (_iter as Gee.BidirMapIterator<K,V>).first ();
+		}
+
+		public bool previous () {
+			return (_iter as Gee.BidirMapIterator<K,V>).previous ();
+		}
+
+		public bool has_previous () {
+			return (_iter as Gee.BidirMapIterator<K,V>).has_previous ();
+		}
+
+		public bool last () {
+			return (_iter as Gee.BidirMapIterator<K,V>).last ();
+		}
+	}
+}
+
diff --git a/gee/readonlybidirsortedset.vala b/gee/readonlybidirsortedset.vala
new file mode 100644
index 0000000..460ebbe
--- /dev/null
+++ b/gee/readonlybidirsortedset.vala
@@ -0,0 +1,71 @@
+/* readonlybidirsortedset.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+/**
+ * Read-only view for { link BidirSortedSet} collections.
+ *
+ * This class decorates any class which implements the { link BidirSortedSet}
+ * interface by making it read only. Any method which normally modify data will
+ * throw an error.
+ *
+ * @see BidirSortedSet
+ */
+internal class Gee.ReadOnlyBidirSortedSet<G> : ReadOnlySortedSet<G>, BidirSortedSet<G> {
+	/**
+	 * Constructs a read-only set that mirrors the content of the specified set.
+	 *
+	 * @param set the set to decorate.
+	 */
+	public ReadOnlyBidirSortedSet (BidirSortedSet<G> set) {
+		base (set);
+	}
+
+	/**
+	 * { inheritDoc}
+	 */
+	public Gee.BidirIterator<G> bidir_iterator () {
+		return new BidirIterator<G> ((_collection as BidirSortedSet<G>).bidir_iterator ());
+	}
+
+	protected class BidirIterator<G> : Gee.ReadOnlyCollection.Iterator<G>, Gee.BidirIterator<G> {
+		public BidirIterator (Gee.BidirIterator<G> iterator) {
+			base (iterator);
+		}
+
+		public bool first () {
+			return (_iter as Gee.BidirIterator<G>).first ();
+		}
+
+		public bool previous () {
+			return (_iter as Gee.BidirIterator<G>).previous ();
+		}
+
+		public bool has_previous () {
+			return (_iter as Gee.BidirIterator<G>).has_previous ();
+		}
+
+		public bool last () {
+			return (_iter as Gee.BidirIterator<G>).last ();
+		}
+	}
+}
+
diff --git a/gee/readonlysortedmap.vala b/gee/readonlysortedmap.vala
index bf25da9..56d7fb6 100644
--- a/gee/readonlysortedmap.vala
+++ b/gee/readonlysortedmap.vala
@@ -77,34 +77,5 @@ internal class Gee.ReadOnlySortedMap<K,V> : ReadOnlyMap<K,V>, SortedMap<K,V> {
 			return (_map as SortedMap<K,V>).ascending_entries.read_only_view;
 		}
 	}
-
-	/**
-	 * { inheritDoc}
-	 */
-	public Gee.BidirMapIterator<K,V> bidir_map_iterator () {
-		return new BidirMapIterator<K,V> ((_map as SortedMap<K,V>).bidir_map_iterator ());
-	}
-
-	protected class BidirMapIterator<K,V> : Gee.ReadOnlyMap.MapIterator<K,V>, Gee.BidirMapIterator<K,V> {
-		public BidirMapIterator (Gee.BidirMapIterator<K,V> iterator) {
-			base (iterator);
-		}
-
-		public bool first () {
-			return (_iter as Gee.BidirMapIterator<K,V>).first ();
-		}
-
-		public bool previous () {
-			return (_iter as Gee.BidirMapIterator<K,V>).previous ();
-		}
-
-		public bool has_previous () {
-			return (_iter as Gee.BidirMapIterator<K,V>).has_previous ();
-		}
-
-		public bool last () {
-			return (_iter as Gee.BidirMapIterator<K,V>).last ();
-		}
-	}
 }
 
diff --git a/gee/readonlysortedset.vala b/gee/readonlysortedset.vala
index 54d1786..de60b4c 100644
--- a/gee/readonlysortedset.vala
+++ b/gee/readonlysortedset.vala
@@ -57,16 +57,9 @@ internal class Gee.ReadOnlySortedSet<G> : ReadOnlySet<G>, SortedSet<G> {
 	/**
 	 * { inheritDoc}
 	 */
-	public Gee.BidirIterator<G> bidir_iterator () {
-		return new BidirIterator<G> ((_collection as SortedSet<G>).bidir_iterator ());
-	}
-
-	/**
-	 * { inheritDoc}
-	 */
-	public Gee.BidirIterator<G>? iterator_at (G element) {
+	public Gee.Iterator<G>? iterator_at (G element) {
 		var iter = (_collection as SortedSet<G>).iterator_at (element);
-		return (iter != null) ? new BidirIterator<G> (iter) : null;
+		return (iter != null) ? new Iterator<G> (iter) : null;
 	}
 
 	/**
@@ -126,27 +119,5 @@ internal class Gee.ReadOnlySortedSet<G> : ReadOnlySet<G>, SortedSet<G> {
 			return this;
 		}
 	}
-
-	protected class BidirIterator<G> : Gee.ReadOnlyCollection.Iterator<G>, Gee.BidirIterator<G> {
-		public BidirIterator (Gee.BidirIterator<G> iterator) {
-			base (iterator);
-		}
-
-		public bool first () {
-			return (_iter as Gee.BidirIterator<G>).first ();
-		}
-
-		public bool previous () {
-			return (_iter as Gee.BidirIterator<G>).previous ();
-		}
-
-		public bool has_previous () {
-			return (_iter as Gee.BidirIterator<G>).has_previous ();
-		}
-
-		public bool last () {
-			return (_iter as Gee.BidirIterator<G>).last ();
-		}
-	}
 }
 
diff --git a/gee/sortedmap.vala b/gee/sortedmap.vala
index 8693a91..ef5904e 100644
--- a/gee/sortedmap.vala
+++ b/gee/sortedmap.vala
@@ -25,10 +25,12 @@ public interface Gee.SortedMap<K,V> : Gee.Map<K,V> {
 	 * Returns map containing pairs with key strictly lower the the argument.
 	 */
 	public abstract SortedMap<K,V> head_map (K before);
+
 	/**
 	 * Returns map containing pairs with key equal or larger then the argument.
 	 */
 	public abstract SortedMap<K,V> tail_map (K after);
+
 	/**
 	 * Returns right-open map (i.e. containing all pair which key is strictly
 	 * lower then the second argument and equal or bigger then the first one).
@@ -36,21 +38,17 @@ public interface Gee.SortedMap<K,V> : Gee.Map<K,V> {
 	 * Null as one parameter means that it should include all from this side.
 	 */
 	public abstract SortedMap<K,V> sub_map (K before, K after);
+
 	/**
 	 * Returns the keys in ascending order.
 	 */
 	public abstract SortedSet<K> ascending_keys { owned get; }
+
 	/**
 	 * Returns the entries in ascending order.
 	 */
 	public abstract SortedSet<Map.Entry<K,V>> ascending_entries { owned get; }
-	/**
-	 * Returns a bi-directional iterator for this map.
-	 *
-	 * @return a bi-directional map iterator
-	 */
-	public abstract BidirMapIterator<K,V> bidir_map_iterator ();
-	
+
 	/**
 	 * The read-only view this map.
 	 */
diff --git a/gee/sortedset.vala b/gee/sortedset.vala
index e5d86af..5acd50d 100644
--- a/gee/sortedset.vala
+++ b/gee/sortedset.vala
@@ -40,14 +40,6 @@ public interface Gee.SortedSet<G> : Gee.Set<G> {
 	public abstract G last ();
 
 	/**
-	 * Returns a { link BidirIterator} that can be used for bi-directional
-	 * iteration over this sorted set.
-	 *
-	 * @return a { link BidirIterator} over this sorted set
-	 */
-	public abstract BidirIterator<G> bidir_iterator ();
-
-	/**
 	 * Returns a { link BidirIterator} initialy pointed at the specified
 	 * element.
 	 *
@@ -56,7 +48,7 @@ public interface Gee.SortedSet<G> : Gee.Set<G> {
 	 * @return        a { link BidirIterator} over this sorted set, or null if
 	 *                the specified element is not in this set
 	 */
-	public abstract BidirIterator<G>? iterator_at (G element);
+	public abstract Iterator<G>? iterator_at (G element);
 
 	/**
 	 * Returns the element which is strictly lower than the specified element.
diff --git a/gee/treemap.vala b/gee/treemap.vala
index 508e8a9..8bc869e 100644
--- a/gee/treemap.vala
+++ b/gee/treemap.vala
@@ -31,7 +31,7 @@ using GLib;
  *
  * @see HashMap
  */
-public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
+public class Gee.TreeMap<K,V> : Gee.AbstractBidirSortedMap<K,V> {
 	/**
 	 * { inheritDoc}
 	 */
@@ -745,7 +745,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 		BOUNDED
 	}
 
-	private class SubMap<K,V> : AbstractSortedMap<K,V> {
+	private class SubMap<K,V> : AbstractBidirSortedMap<K,V> {
 		public override int size { get { return keys.size; } }
 		public override bool is_empty { get { return keys.is_empty; } }
 
@@ -874,7 +874,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 		private Range<K,V> range;
 	}
 
-	private class KeySet<K,V> : AbstractSet<K>, SortedSet<K> {
+	private class KeySet<K,V> : AbstractBidirSortedSet<K> {
 		private TreeMap<K,V> _map;
 
 		public KeySet (TreeMap<K,V> map) {
@@ -909,61 +909,57 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return _map.has_key (key);
 		}
 
-		public K first () {
+		public override K first () {
 			assert (_map.first != null);
 			return _map.first.key;
 		}
 
-		public K last () {
+		public override K last () {
 			assert (_map.last != null);
 			return _map.last.key;
 		}
 
-		public BidirIterator<K> bidir_iterator () {
+		public override BidirIterator<K> bidir_iterator () {
 			return new KeyIterator<K,V> (_map);
 		}
 
-		public SortedSet<K> head_set (K before) {
+		public override SortedSet<K> head_set (K before) {
 			return new SubKeySet<K,V> (_map, new Range<K,V>.head (_map, before));
 		}
 
-		public SortedSet<K> tail_set (K after) {
+		public override SortedSet<K> tail_set (K after) {
 			return new SubKeySet<K,V> (_map, new Range<K,V>.tail (_map, after));
 		}
 
-		public SortedSet<K> sub_set (K after, K before) {
+		public override SortedSet<K> sub_set (K after, K before) {
 			return new SubKeySet<K,V> (_map, new Range<K,V> (_map, after, before));
 		}
 
-		public BidirIterator<K>? iterator_at (K item) {
+		public override Iterator<K>? iterator_at (K item) {
 			weak Node<K,V>? node = _map.find_node (item);
 			if (node == null)
 				return null;
 			return new KeyIterator<K,V>.pointing (_map, node);
 		}
 
-		public K? lower (K item) {
+		public override K? lower (K item) {
 			return _map.lift_null_key (_map.find_lower (item));
 		}
 
-		public K? higher (K item) {
+		public override K? higher (K item) {
 			return _map.lift_null_key (_map.find_higher (item));
 		}
 
-		public K? floor (K item) {
+		public override K? floor (K item) {
 			return _map.lift_null_key (_map.find_floor (item));
 		}
 
-		public K? ceil (K item) {
+		public override K? ceil (K item) {
 			return _map.lift_null_key (_map.find_ceil (item));
 		}
-
-		public new SortedSet<K> read_only_view {
-			owned get { return this; }
-		}
 	}
 
-	private class SubKeySet<K,V> : AbstractSet<K>, SortedSet<K> {
+	private class SubKeySet<K,V> : AbstractBidirSortedSet<K> {
 		public TreeMap<K,V> map { private set; get; }
 		public Range<K,V> range { private set; get; }
 
@@ -1010,35 +1006,35 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return range.in_range(key) && map.has_key (key);
 		}
 
-		public BidirIterator<K> bidir_iterator () {
+		public override BidirIterator<K> bidir_iterator () {
 			return new SubKeyIterator<K,V> (map, range);
 		}
 
-		public K first () {
+		public override K first () {
 			weak Node<K,V>? _first = range.first ();
 			assert (_first != null);
 			return _first.key;
 		}
 
-		public K last () {
+		public override K last () {
 			weak Node<K,V>? _last = range.last ();
 			assert (_last != null);
 			return _last.key;
 		}
 
-		public SortedSet<K> head_set (K before) {
+		public override SortedSet<K> head_set (K before) {
 			return new SubKeySet<K,V> (map, range.cut_tail (before));
 		}
 
-		public SortedSet<K> tail_set (K after) {
+		public override SortedSet<K> tail_set (K after) {
 			return new SubKeySet<K,V> (map, range.cut_head (after));
 		}
 
-		public SortedSet<K> sub_set (K after, K before) {
+		public override SortedSet<K> sub_set (K after, K before) {
 			return new SubKeySet<K,V> (map, range.cut (after, before));
 		}
 
-		public BidirIterator<K>? iterator_at (K key) {
+		public override Iterator<K>? iterator_at (K key) {
 			if (!range.in_range (key))
 				return null;
 			weak Node<K,V>? n = map.find_node (key);
@@ -1047,7 +1043,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return new SubKeyIterator<K,V>.pointing (map, range, n);
 		}
 
-		public K? lower (K key) {
+		public override K? lower (K key) {
 			var res = range.compare_range (key);
 			if (res > 0)
 				return last ();
@@ -1055,7 +1051,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return l != null && range.in_range (l) ? l : null;
 		}
 
-		public K? higher (K key) {
+		public override K? higher (K key) {
 			var res = range.compare_range (key);
 			if (res < 0)
 				return first ();
@@ -1063,7 +1059,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return h != null && range.in_range (h) ? h : null;
 		}
 
-		public K? floor (K key) {
+		public override K? floor (K key) {
 			var res = range.compare_range (key);
 			if (res > 0)
 				return last ();
@@ -1071,17 +1067,13 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return l != null && range.in_range (l) ? l : null;
 		}
 
-		public K? ceil (K key) {
+		public override K? ceil (K key) {
 			var res = range.compare_range (key);
 			if (res < 0)
 				return first ();
 			var h = map.lift_null_key (map.find_ceil (key));
 			return h != null && range.in_range (h) ? h : null;
 		}
-
-		public new SortedSet<K> read_only_view {
-			owned get { return this; }
-		}
 	}
 
 	private class ValueCollection<K,V> : AbstractCollection<V> {
@@ -1180,7 +1172,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 		}
 	}
 
-	private class EntrySet<K,V> : AbstractSet<Map.Entry<K, V>>, SortedSet<Map.Entry<K, V>> {
+	private class EntrySet<K,V> : AbstractBidirSortedSet<Map.Entry<K, V>> {
 		private TreeMap<K,V> _map;
 
 		public EntrySet (TreeMap<K,V> map) {
@@ -1215,65 +1207,61 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return _map.has (entry.key, entry.value);
 		}
 
-		public Map.Entry<K, V>/*?*/ first () {
+		public override Map.Entry<K, V>/*?*/ first () {
 			assert (_map.first != null);
 			return Entry.entry_for<K,V> (_map.first);
 		}
 
-		public Map.Entry<K, V>/*?*/ last () {
+		public override Map.Entry<K, V>/*?*/ last () {
 			assert (_map.last != null);
 			return Entry.entry_for<K,V> (_map.last);
 		}
 
-		public BidirIterator<Map.Entry<K, V>> bidir_iterator () {
+		public override BidirIterator<Map.Entry<K, V>> bidir_iterator () {
 			return new EntryIterator<K,V> (_map);
 		}
 
-		public SortedSet<Map.Entry<K, V>> head_set (Map.Entry<K, V> before) {
+		public override SortedSet<Map.Entry<K, V>> head_set (Map.Entry<K, V> before) {
 			return new SubEntrySet<K,V> (_map, new Range<K,V>.head (_map, before.key));
 		}
 
-		public SortedSet<Map.Entry<K, V>> tail_set (Map.Entry<K, V> after) {
+		public override SortedSet<Map.Entry<K, V>> tail_set (Map.Entry<K, V> after) {
 			return new SubEntrySet<K,V> (_map, new Range<K,V>.tail (_map, after.key));
 		}
 
-		public SortedSet<K> sub_set (Map.Entry<K, V> after, Map.Entry<K, V> before) {
+		public override SortedSet<K> sub_set (Map.Entry<K, V> after, Map.Entry<K, V> before) {
 			return new SubEntrySet<K,V> (_map, new Range<K,V> (_map, after.key, before.key));
 		}
 
-		public BidirIterator<Map.Entry<K, V>>? iterator_at (Map.Entry<K, V> item) {
+		public override Iterator<Map.Entry<K, V>>? iterator_at (Map.Entry<K, V> item) {
 			weak Node<K,V>? node = _map.find_node (item.key);
 			if (node == null || !_map.value_equal_func (node.value, item.value))
 				return null;
 			return new EntryIterator<K,V>.pointing (_map, node);
 		}
 
-		public Map.Entry<K, V>/*?*/ lower (Map.Entry<K, V> item) {
+		public override Map.Entry<K, V>/*?*/ lower (Map.Entry<K, V> item) {
 			weak Node<K,V>? l = _map.find_lower (item.key);
 			return l != null ? Entry.entry_for<K,V> (l) : null;
 		}
 
-		public Map.Entry<K, V>/*?*/ higher (Map.Entry<K, V> item) {
+		public override Map.Entry<K, V>/*?*/ higher (Map.Entry<K, V> item) {
 			weak Node<K,V>? l = _map.find_higher (item.key);
 			return l != null ? Entry.entry_for<K,V> (l) : null;
 		}
 
-		public Map.Entry<K, V>/*?*/ floor (Map.Entry<K, V> item) {
+		public override Map.Entry<K, V>/*?*/ floor (Map.Entry<K, V> item) {
 			weak Node<K,V>? l = _map.find_floor (item.key);
 			return l != null ? Entry.entry_for<K,V> (l) : null;
 		}
 
-		public Map.Entry<K, V>/*?*/ ceil (Map.Entry<K, V> item) {
+		public override Map.Entry<K, V>/*?*/ ceil (Map.Entry<K, V> item) {
 			weak Node<K,V>? l = _map.find_ceil (item.key);
 			return l != null ? Entry.entry_for<K,V> (l) : null;
 		}
-
-		public new SortedSet<Map.Entry<K, V>> read_only_view {
-			owned get { return this; }
-		}
 	}
 
-	private class SubEntrySet<K,V> : AbstractSet<Map.Entry<K,V>>, SortedSet<Map.Entry<K,V>> {
+	private class SubEntrySet<K,V> : AbstractBidirSortedSet<Map.Entry<K,V>> {
 		public TreeMap<K,V> map { private set; get; }
 		public Range<K,V> range { private set; get; }
 
@@ -1320,35 +1308,35 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return range.in_range(entry.key) && map.has (entry.key, entry.value);
 		}
 
-		public BidirIterator<K> bidir_iterator () {
+		public override BidirIterator<K> bidir_iterator () {
 			return new SubEntryIterator<K,V> (map, range);
 		}
 
-		public Map.Entry<K,V> first () {
+		public override Map.Entry<K,V> first () {
 			weak Node<K,V>? _first = range.first ();
 			assert (_first != null);
 			return Entry.entry_for<K,V> (_first);
 		}
 
-		public Map.Entry<K,V> last () {
+		public override Map.Entry<K,V> last () {
 			weak Node<K,V>? _last = range.last ();
 			assert (_last != null);
 			return Entry.entry_for<K,V> (_last);
 		}
 
-		public SortedSet<K> head_set (Map.Entry<K,V> before) {
+		public override SortedSet<K> head_set (Map.Entry<K,V> before) {
 			return new SubEntrySet<K,V> (map, range.cut_tail (before.key));
 		}
 
-		public SortedSet<K> tail_set (Map.Entry<K,V> after) {
+		public override SortedSet<K> tail_set (Map.Entry<K,V> after) {
 			return new SubEntrySet<K,V> (map, range.cut_head (after.key));
 		}
 
-		public SortedSet<K> sub_set (Map.Entry<K,V> after, Map.Entry<K,V> before) {
+		public override SortedSet<K> sub_set (Map.Entry<K,V> after, Map.Entry<K,V> before) {
 			return new SubEntrySet<K,V> (map, range.cut (after.key, before.key));
 		}
 
-		public BidirIterator<Map.Entry<K,V>>? iterator_at (Map.Entry<K,V> entry) {
+		public override Iterator<Map.Entry<K,V>>? iterator_at (Map.Entry<K,V> entry) {
 			if (!range.in_range (entry.key))
 				return null;
 			weak Node<K,V>? n = map.find_node (entry.key);
@@ -1357,7 +1345,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return new SubEntryIterator<K,V>.pointing (map, range, n);
 		}
 
-		public Map.Entry<K,V>/*?*/ lower (Map.Entry<K,V> entry) {
+		public override Map.Entry<K,V>/*?*/ lower (Map.Entry<K,V> entry) {
 			var res = range.compare_range (entry.key);
 			if (res > 0)
 				return last ();
@@ -1365,7 +1353,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return l != null && range.in_range (l.key) ? Entry.entry_for<K,V> (l) : null;
 		}
 
-		public Map.Entry<K,V>/*?*/ higher (Map.Entry<K,V> entry) {
+		public override Map.Entry<K,V>/*?*/ higher (Map.Entry<K,V> entry) {
 			var res = range.compare_range (entry.key);
 			if (res < 0)
 				return first ();
@@ -1373,7 +1361,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return h != null && range.in_range (h.key) ? Entry.entry_for<K,V> (h) : null;
 		}
 
-		public Map.Entry<K,V>/*?*/ floor (Map.Entry<K,V> entry) {
+		public override Map.Entry<K,V>/*?*/ floor (Map.Entry<K,V> entry) {
 			var res = range.compare_range (entry.key);
 			if (res > 0)
 				return last ();
@@ -1381,27 +1369,23 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return l != null && range.in_range (l.key) ? Entry.entry_for<K,V> (l) : null;
 		}
 
-		public Map.Entry<K,V>/*?*/ ceil (Map.Entry<K,V> entry) {
+		public override Map.Entry<K,V>/*?*/ ceil (Map.Entry<K,V> entry) {
 			var res = range.compare_range (entry.key);
 			if (res < 0)
 				return first ();
 			weak Node<K,V>? h = map.find_ceil (entry.key);
 			return h != null && range.in_range (h.key) ? Entry.entry_for<K,V> (h) : null;
 		}
-
-		public new SortedSet<Map.Entry<K, V>> read_only_view {
-			owned get { return this; }
-		}
 	}
 
 	private class NodeIterator<K, V> : Object {
 		protected TreeMap<K,V> _map;
-		
+
 		// concurrent modification protection
 		protected int stamp;
-		
+
 		protected bool started = false;
-		
+
 		internal weak Node<K, V>? current;
 		protected weak Node<K, V>? _next;
 		protected weak Node<K, V>? _prev;
@@ -1507,13 +1491,13 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			_map.stamp++;
 			assert (stamp == _map.stamp);
 		}
-		
+
 		public virtual bool read_only {
 			get {
 				return true;
 			}
 		}
-		
+
 		public bool valid {
 			get {
 				return current != null;
@@ -1901,7 +1885,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			return Traversable.chop_impl<Map.Entry<K, V>> (this, offset, length);
 		}
 	}
-	
+
 	private class MapIterator<K,V> : NodeIterator<K,V>, Gee.MapIterator<K,V>, BidirMapIterator<K,V> {
 		public MapIterator (TreeMap<K,V> map) {
 			base (map);
@@ -1937,7 +1921,7 @@ public class Gee.TreeMap<K,V> : Gee.AbstractSortedMap<K,V> {
 			}
 		}
 	}
-	
+
 	private class SubMapIterator<K,V> : SubNodeIterator<K,V>, Gee.MapIterator<K,V>, BidirMapIterator<K,V> {
 		public SubMapIterator (TreeMap<K,V> map, Range<K,V> range) {
 			base (map, range);
diff --git a/gee/treeset.vala b/gee/treeset.vala
index 342bc53..8387b1c 100644
--- a/gee/treeset.vala
+++ b/gee/treeset.vala
@@ -32,7 +32,7 @@ using GLib;
  *
  * @see HashSet
  */
-public class Gee.TreeSet<G> : AbstractSortedSet<G> {
+public class Gee.TreeSet<G> : AbstractBidirSortedSet<G> {
 	/**
 	 * { inheritDoc}
 	 */
@@ -410,7 +410,7 @@ public class Gee.TreeSet<G> : AbstractSortedSet<G> {
 	/**
 	 * { inheritDoc}
 	 */
-	public override BidirIterator<G>? iterator_at (G item) {
+	public override Gee.Iterator<G>? iterator_at (G item) {
 		weak Node<G>? node = find_node (item);
 		return node != null ? new Iterator<G>.pointing (this, node) : null;
 	}
@@ -901,7 +901,7 @@ public class Gee.TreeSet<G> : AbstractSortedSet<G> {
 		BOUNDED
 	}
 
-	private class SubSet<G> : AbstractSortedSet<G> {
+	private class SubSet<G> : AbstractBidirSortedSet<G> {
 		public SubSet (TreeSet<G> set, G after, G before) {
 			this.set = set;
 			this.range = new Range<G> (set, after, before);
@@ -993,7 +993,7 @@ public class Gee.TreeSet<G> : AbstractSortedSet<G> {
 			return new SubSet<G>.from_range (set, range.cut (after, before));
 		}
 
-		public override BidirIterator<G>? iterator_at (G item) {
+		public override Gee.Iterator<G>? iterator_at (G item) {
 			if (!range.in_range (item))
 				return null;
 			weak Node<G>? n = set.find_node (item);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 37489ae..105292e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,6 +8,8 @@ tests_SOURCES = \
        testarraylist.vala \
        testarrayqueue.vala \
        testbidirlist.vala \
+       testbidirsortedset.vala \
+       testbidirsortedmap.vala \
        testcase.vala \
        testcollection.vala \
        testconcurrentlist.vala \
diff --git a/tests/testbidirsortedmap.vala b/tests/testbidirsortedmap.vala
new file mode 100644
index 0000000..385d715
--- /dev/null
+++ b/tests/testbidirsortedmap.vala
@@ -0,0 +1,430 @@
+/* testbidirsortedmap.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+using GLib;
+using Gee;
+
+public abstract class BidirSortedMapTests : SortedMapTests {
+	public BidirSortedMapTests(string name) {
+		base (name);
+		add_test ("[SortedMap] bi-directional iterators can go backward",
+		          test_bidir_iterator_can_go_backward);
+		add_test ("[SortedSet] bi-directional iterators can to end",
+		          test_bidir_iterator_last);
+		get_suite ().add_suite (new BidirSubMapTests (this, SortedMapTests.SubMapTests.Type.HEAD).get_suite ());
+		get_suite ().add_suite (new BidirSubMapTests (this, SortedMapTests.SubMapTests.Type.TAIL).get_suite ());
+		get_suite ().add_suite (new BidirSubMapTests (this, SortedMapTests.SubMapTests.Type.SUB).get_suite ());
+		get_suite ().add_suite (new BidirSubMapTests (this, SortedMapTests.SubMapTests.Type.EMPTY).get_suite ());
+	}
+
+	public void test_bidir_iterator_can_go_backward () {
+		var test_sorted_map = test_map as BidirSortedMap<string,string>;
+		var keys = (test_sorted_map.ascending_keys) as BidirSortedSet<string>;
+		var entries = (test_sorted_map.ascending_entries) as BidirSortedSet<Map.Entry<string,string>>;
+
+		var keys_iterator = keys.bidir_iterator ();
+		var entries_iterator = entries.bidir_iterator ();
+		var map_iterator = test_sorted_map.bidir_map_iterator ();
+
+		assert (!keys_iterator.has_previous ());
+		assert (!entries_iterator.has_previous ());
+
+		assert (!map_iterator.has_previous ());
+		assert (!keys_iterator.previous ());
+		assert (!entries_iterator.has_previous ());
+
+		assert (!map_iterator.previous ());
+
+		test_sorted_map.set ("one", "one");
+		test_sorted_map.set ("two", "two");
+		test_sorted_map.set ("three", "three");
+		test_sorted_map.set ("four", "four");
+		test_sorted_map.set ("five", "five");
+		test_sorted_map.set ("six", "six");
+
+		keys_iterator = keys.bidir_iterator ();
+		entries_iterator = entries.bidir_iterator ();
+		map_iterator = test_sorted_map.bidir_map_iterator ();
+
+		assert (keys_iterator.next ());
+		assert (entries_iterator.next ());
+
+		assert (map_iterator.next ());
+		assert (keys_iterator.get () == "five");
+		assert_entry (entries_iterator.get (), "five", "five");
+
+		assert (map_iterator.get_key () == "five");
+		assert (map_iterator.get_value () == "five");
+
+		assert (!keys_iterator.has_previous ());
+		assert (!entries_iterator.has_previous ());
+
+		assert (!map_iterator.has_previous ());
+		assert (keys_iterator.next ());
+		assert (entries_iterator.next ());
+
+		assert (map_iterator.next ());
+		assert (keys_iterator.get () == "four");
+		assert_entry (entries_iterator.get (), "four", "four");
+
+		assert (map_iterator.get_key () == "four");
+		assert (map_iterator.get_value () == "four");
+
+		assert (keys_iterator.has_previous ());
+		assert (entries_iterator.has_previous ());
+
+		assert (map_iterator.has_previous ());
+		assert (keys_iterator.next ());
+		assert (entries_iterator.next ());
+
+		assert (map_iterator.next ());
+		assert (keys_iterator.get () == "one");
+		assert_entry (entries_iterator.get (), "one", "one");
+
+		assert (map_iterator.get_key () == "one");
+		assert (map_iterator.get_value () == "one");
+
+		assert (keys_iterator.has_previous ());
+		assert (entries_iterator.has_previous ());
+
+		assert (map_iterator.has_previous ());
+		assert (keys_iterator.next ());
+		assert (entries_iterator.next ());
+
+		assert (map_iterator.next ());
+		assert (keys_iterator.get () == "six");
+		assert_entry (entries_iterator.get (), "six", "six");
+
+		assert (map_iterator.get_key () == "six");
+		assert (map_iterator.get_value () == "six");
+		assert (keys_iterator.has_previous ());
+
+		assert (entries_iterator.has_previous ());
+		assert (map_iterator.has_previous ());
+		assert (keys_iterator.next ());
+
+		assert (entries_iterator.next ());
+		assert (map_iterator.next ());
+		assert (keys_iterator.get () == "three");
+
+		assert_entry (entries_iterator.get (), "three", "three");
+		assert (map_iterator.get_key () == "three");
+		assert (map_iterator.get_value () == "three");
+
+		assert (keys_iterator.has_previous ());
+		assert (entries_iterator.has_previous ());
+		assert (map_iterator.has_previous ());
+
+		assert (keys_iterator.next ());
+		assert (entries_iterator.next ());
+		assert (map_iterator.next ());
+
+		assert (keys_iterator.get () == "two");
+		assert_entry (entries_iterator.get (), "two", "two");
+		assert (map_iterator.get_key () == "two");
+		assert (map_iterator.get_value () == "two");
+
+		assert (keys_iterator.has_previous ());
+		assert (entries_iterator.has_previous ());
+		assert (map_iterator.has_previous ());
+
+		assert (!keys_iterator.next ());
+		assert (!entries_iterator.next ());
+		assert (!map_iterator.next ());
+
+		assert (keys_iterator.previous ());
+		assert (entries_iterator.previous ());
+		assert (map_iterator.previous ());
+
+		assert (keys_iterator.get () == "three");
+		assert_entry (entries_iterator.get (), "three", "three");
+		assert (map_iterator.get_key () == "three");
+		assert (map_iterator.get_value () == "three");
+
+		assert (keys_iterator.previous ());
+		assert (entries_iterator.previous ());
+		assert (map_iterator.previous ());
+
+		assert (keys_iterator.get () == "six");
+		assert_entry (entries_iterator.get (), "six", "six");
+		assert (map_iterator.get_key () == "six");
+		assert (map_iterator.get_value () == "six");
+
+		assert (keys_iterator.previous ());
+		assert (entries_iterator.previous ());
+		assert (map_iterator.previous ());
+
+		assert (keys_iterator.get () == "one");
+		assert_entry (entries_iterator.get (), "one", "one");
+		assert (map_iterator.get_key () == "one");
+		assert (map_iterator.get_value () == "one");
+
+		assert (keys_iterator.previous ());
+		assert (entries_iterator.previous ());
+		assert (map_iterator.previous ());
+
+		assert (keys_iterator.get () == "four");
+		assert_entry (entries_iterator.get (), "four", "four");
+		assert (map_iterator.get_key () == "four");
+		assert (map_iterator.get_value () == "four");
+
+		assert (keys_iterator.previous ());
+		assert (entries_iterator.previous ());
+		assert (map_iterator.previous ());
+
+		assert (keys_iterator.get () == "five");
+		assert_entry (entries_iterator.get (), "five", "five");
+		assert (map_iterator.get_key () == "five");
+		assert (map_iterator.get_value () == "five");
+
+		assert (!keys_iterator.previous ());
+		assert (!entries_iterator.previous ());
+		assert (!map_iterator.previous ());
+
+		assert (keys_iterator.get () == "five");
+		assert_entry (entries_iterator.get (), "five", "five");
+		assert (map_iterator.get_key () == "five");
+		assert (map_iterator.get_value () == "five");
+	}
+
+	public void test_bidir_iterator_last () {
+		var test_sorted_map = test_map as BidirSortedMap<string,string>;
+		var keys = (test_sorted_map.ascending_keys) as BidirSortedSet<string>;
+		var entries = (test_sorted_map.ascending_entries) as BidirSortedSet<Map.Entry<string,string>>;
+
+		var keys_iterator = keys.bidir_iterator ();
+		var entries_iterator = entries.bidir_iterator ();
+
+		assert (!keys_iterator.last ());
+		assert (!entries_iterator.last ());
+
+		test_sorted_map.set ("one", "one");
+		test_sorted_map.set ("two", "two");
+		test_sorted_map.set ("three", "three");
+		test_sorted_map.set ("four", "four");
+		test_sorted_map.set ("five", "five");
+		test_sorted_map.set ("six", "six");
+
+		keys_iterator = keys.bidir_iterator ();
+		entries_iterator = entries.bidir_iterator ();
+
+		assert (keys_iterator.last ());
+		assert (entries_iterator.last ());
+
+		assert (keys_iterator.get () == "two");
+		assert_entry (entries_iterator.get (), "two", "two");
+	}
+
+
+	public class BidirSubMapTests : Gee.TestCase {
+		private BidirSortedMap<string,string> master;
+		private BidirSortedMap<string,string> submap;
+		private BidirSortedMapTests test;
+		private SortedMapTests.SubMapTests.Type type;
+
+		public BidirSubMapTests (BidirSortedMapTests test, SortedMapTests.SubMapTests.Type type) {
+			base ("%s Subset".printf (type.to_string ()));
+			this.test = test;
+			this.type = type;
+			add_test ("[BidirSortedSet] bi-directional iterator", test_bidir_iterators);
+		}
+
+		public override void set_up () {
+			test.set_up ();
+			master = test.test_map as BidirSortedMap<string,string>;
+			switch (type) {
+			case SortedMapTests.SubMapTests.Type.HEAD:
+				submap = master.head_map ("one") as BidirSortedMap<string,string>; break;
+			case SortedMapTests.SubMapTests.Type.TAIL:
+				submap = master.tail_map ("six") as BidirSortedMap<string,string>; break;
+			case SortedMapTests.SubMapTests.Type.SUB:
+				submap = master.sub_map ("four", "three") as BidirSortedMap<string,string>; break;
+			case SortedMapTests.SubMapTests.Type.EMPTY:
+				submap = master.sub_map ("three", "four") as BidirSortedMap<string,string>; break;
+			default:
+				assert_not_reached ();
+			}
+		}
+
+		public override void tear_down () {
+			test.tear_down ();
+		}
+
+		protected void set_default_values (out string[] contains = null, out string[] not_contains = null) {
+			master.set ("one", "one");
+			master.set ("two", "two");
+			master.set ("three", "three");
+			master.set ("four", "four");
+			master.set ("five", "five");
+			master.set ("six", "six");
+			switch (type) {
+			case SortedMapTests.SubMapTests.Type.HEAD:
+				contains = {"five", "four"};
+				not_contains = {"one", "two", "three", "six"};
+				break;
+			case SortedMapTests.SubMapTests.Type.TAIL:
+				contains = {"six", "three", "two"};
+				not_contains = {"one", "four", "five"};
+				break;
+			case SortedMapTests.SubMapTests.Type.SUB:
+				contains = {"four", "one", "six"};
+				not_contains = {"two", "three", "five"};
+				break;
+			case SortedMapTests.SubMapTests.Type.EMPTY:
+				contains = {};
+				not_contains = {"one", "two", "three", "four", "five", "six"};
+				break;
+			default:
+				assert_not_reached ();
+			}
+		}
+
+		public void test_bidir_iterators () {
+			string[] contains, not_contains;
+
+			var _map_iter = submap.bidir_map_iterator ();
+
+			assert (!_map_iter.has_next ());
+			assert (!_map_iter.next ());
+			assert (!_map_iter.has_previous ());
+			assert (!_map_iter.previous ());
+			
+			set_default_values (out contains, out not_contains);
+			
+			var i = 0;
+			_map_iter = submap.bidir_map_iterator ();
+			while (_map_iter.next ()) {
+				assert (_map_iter.get_key () == contains[i]);
+				assert (_map_iter.get_value () == contains[i]);
+				i++;
+			}
+			assert (i == contains.length);
+			
+			i = 0;
+			foreach (var k in submap.keys)
+				assert (k == contains[i++]);
+			assert (i == contains.length);
+			
+			i = 0;
+			foreach (var e in submap.entries) {
+				MapTests.assert_entry (e, contains[i], contains[i]);
+				i++;
+			}
+			assert (i == contains.length);
+			
+			var keys_iter = ((submap.ascending_keys) as BidirSortedSet<string>).bidir_iterator ();
+			var entries_iter = ((submap.ascending_entries) as BidirSortedSet<Map.Entry<string,string>>).bidir_iterator ();
+			var map_iter = submap.bidir_map_iterator ();
+			if (type != SortedMapTests.SubMapTests.Type.EMPTY) {
+				assert (map_iter.last ());
+				assert (map_iter.get_key () == contains[contains.length - 1]);
+				assert (map_iter.get_value () == contains[contains.length - 1]);
+
+				map_iter = submap.bidir_map_iterator ();
+				assert (map_iter.next ());
+
+				assert (map_iter.get_key () == contains[0]);
+				assert (map_iter.get_value () == contains[0]);
+
+				assert (map_iter.has_next ());
+				assert (map_iter.next ());
+				assert (map_iter.get_key () == contains[1]);
+				assert (map_iter.get_value () == contains[1]);
+
+				assert (map_iter.has_previous ());
+				map_iter.unset ();
+				assert (map_iter.has_previous ());
+				if (type != SortedMapTests.SubMapTests.Type.HEAD)
+					assert (map_iter.has_next ());
+				else
+					assert (!map_iter.has_next ());
+				assert (map_iter.previous ());
+				assert (map_iter.get_key () == contains[0]);
+				assert (map_iter.get_value () == contains[0]);
+				
+				// Repeat for keys
+				master.clear ();
+				set_default_values (out contains, out not_contains);
+				
+				assert (keys_iter.last ());
+				assert (keys_iter.get () == contains[contains.length - 1]);
+				assert (keys_iter.first ());
+
+				assert (keys_iter.get () == contains[0]);
+				assert (keys_iter.has_next ());
+				assert (keys_iter.next ());
+				assert (keys_iter.get () == contains[1]);
+				assert (keys_iter.has_previous ());
+				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
+				                       TestTrapFlags.SILENCE_STDERR)) {
+					keys_iter.remove ();
+					Posix.exit (0);
+				}
+				assert (keys_iter.has_previous ());
+				if (type != SortedMapTests.SubMapTests.Type.HEAD)
+					assert (keys_iter.has_next ());
+				else
+					assert (!keys_iter.has_next ());
+				assert (keys_iter.previous ());
+				assert (keys_iter.get () == contains[0]);
+				
+				// Repeat for entries
+				master.clear ();
+				set_default_values (out contains, out not_contains);
+
+				assert (entries_iter.last ());
+				MapTests.assert_entry (entries_iter.get (), contains[contains.length - 1], contains[contains.length - 1]);
+				assert (entries_iter.first ());
+
+				MapTests.assert_entry (entries_iter.get (), contains[0], contains[0]);
+				assert (entries_iter.has_next ());
+				assert (entries_iter.next ());
+				MapTests.assert_entry (entries_iter.get (), contains[1], contains[1]);
+				assert (entries_iter.has_previous ());
+				entries_iter.remove ();
+				assert (entries_iter.has_previous ());
+				if (type != SortedMapTests.SubMapTests.Type.HEAD)
+					assert (entries_iter.has_next ());
+				else
+					assert (!entries_iter.has_next ());
+				assert (entries_iter.previous ());
+				MapTests.assert_entry (entries_iter.get (), contains[0], contains[0]);
+			} else {
+				assert (!keys_iter.first ());
+				assert (!keys_iter.last ());
+				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
+				                       TestTrapFlags.SILENCE_STDERR)) {
+					keys_iter.remove ();
+					Posix.exit (0);
+				}
+				Test.trap_assert_failed ();
+				assert (!entries_iter.first ());
+				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
+				                       TestTrapFlags.SILENCE_STDERR)) {
+					entries_iter.remove ();
+					Posix.exit (0);
+				}
+				Test.trap_assert_failed ();
+			}
+		}
+	}
+}
+
diff --git a/tests/testbidirsortedset.vala b/tests/testbidirsortedset.vala
new file mode 100644
index 0000000..df5da60
--- /dev/null
+++ b/tests/testbidirsortedset.vala
@@ -0,0 +1,275 @@
+/* testbidirsortedset.vala
+ *
+ * Copyright (C) 2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Maciej Piechotka <uzytkownik2 gmail com>
+ */
+using GLib;
+using Gee;
+
+public abstract class BidirSortedSetTests : SortedSetTests {
+	public BidirSortedSetTests(string name) {
+		base (name);
+		add_test ("[SortedSet] bi-directional iterators can go backward",
+		          test_bidir_iterator_can_go_backward);
+		add_test ("[SortedSet] bi-directional iterators are mutable",
+		          test_mutable_bidir_iterator);
+		add_test ("[SortedSet] bi-directional iterators can to beginning",
+		          test_bidir_iterator_first);
+		add_test ("[SortedSet] bi-directional iterators can to end",
+		          test_bidir_iterator_last);
+		get_suite ().add_suite (new BidirSubSetTests (this, SortedSetTests.SubSetTests.Type.HEAD).get_suite ());
+		get_suite ().add_suite (new BidirSubSetTests (this, SortedSetTests.SubSetTests.Type.TAIL).get_suite ());
+		get_suite ().add_suite (new BidirSubSetTests (this, SortedSetTests.SubSetTests.Type.SUB).get_suite ());
+		get_suite ().add_suite (new BidirSubSetTests (this, SortedSetTests.SubSetTests.Type.EMPTY).get_suite ());
+	}
+
+	public void test_bidir_iterator_can_go_backward () {
+		var test_set = test_collection as BidirSortedSet<string>;
+
+		var iterator = test_set.bidir_iterator ();
+		assert (!iterator.has_previous ());
+
+		assert (test_set.add ("one"));
+		assert (test_set.add ("two"));
+		assert (test_set.add ("three"));
+		assert (test_set.add ("four"));
+		assert (test_set.add ("five"));
+		assert (test_set.add ("six"));
+
+		iterator = test_set.bidir_iterator ();
+		assert (iterator.next ());
+		assert (iterator.get () == "five");
+		assert (!iterator.has_previous ());
+		assert (iterator.next ());
+		assert (iterator.get () == "four");
+		assert (iterator.has_previous ());
+		assert (iterator.next ());
+		assert (iterator.get () == "one");
+		assert (iterator.has_previous ());
+		assert (iterator.next ());
+		assert (iterator.get () == "six");
+		assert (iterator.has_previous ());
+		assert (iterator.next ());
+		assert (iterator.get () == "three");
+		assert (iterator.has_previous ());
+		assert (iterator.next ());
+		assert (iterator.get () == "two");
+		assert (iterator.has_previous ());
+		assert (!iterator.next ());
+		assert (iterator.previous ());
+		assert (iterator.get () == "three");
+		assert (iterator.previous ());
+		assert (iterator.get () == "six");
+		assert (iterator.previous ());
+		assert (iterator.get () == "one");
+		assert (iterator.previous ());
+		assert (iterator.get () == "four");
+		assert (iterator.previous ());
+		assert (iterator.get () == "five");
+		assert (!iterator.previous ());
+		assert (iterator.get () == "five");
+	}
+
+	public void test_bidir_iterator_first () {
+		var test_set = test_collection as BidirSortedSet<string>;
+
+		var iterator = test_set.bidir_iterator ();
+
+		assert (!iterator.first ());
+
+		assert (test_set.add ("one"));
+		assert (test_set.add ("two"));
+		assert (test_set.add ("three"));
+		assert (test_set.add ("four"));
+		assert (test_set.add ("five"));
+		assert (test_set.add ("six"));
+
+		iterator = test_set.bidir_iterator ();
+		assert (iterator.last ());
+		assert (iterator.get () == "two");
+		assert (iterator.first ());
+		assert (iterator.get () == "five");
+	}
+
+	public void test_bidir_iterator_last () {
+		var test_set = test_collection as BidirSortedSet<string>;
+
+		var iterator = test_set.bidir_iterator ();
+
+		assert (!iterator.last ());
+
+		assert (test_set.add ("one"));
+		assert (test_set.add ("two"));
+		assert (test_set.add ("three"));
+		assert (test_set.add ("four"));
+		assert (test_set.add ("five"));
+		assert (test_set.add ("six"));
+
+		iterator = test_set.bidir_iterator ();
+		assert (iterator.last ());
+		assert (iterator.get () == "two");
+	}
+
+	public void test_mutable_bidir_iterator () {
+		var test_set = test_collection as BidirSortedSet<string>;
+
+		var iterator = test_set.bidir_iterator ();
+		assert (!iterator.has_previous ());
+
+		assert (test_set.add ("one"));
+		assert (test_set.add ("two"));
+		assert (test_set.add ("three"));
+		assert (test_set.add ("four"));
+		assert (test_set.add ("five"));
+		assert (test_set.add ("six"));
+
+		iterator = test_set.bidir_iterator ();
+
+		if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
+		                       TestTrapFlags.SILENCE_STDERR)) {
+			iterator.remove ();
+			Posix.exit (0);
+		}
+		Test.trap_assert_failed ();
+
+		assert (iterator.next ());
+		assert (iterator.get () == "five");
+		iterator.remove ();
+		assert (!test_set.contains ("five"));
+		assert (iterator.has_next ());
+		assert (!iterator.has_previous ());
+		if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
+		                       TestTrapFlags.SILENCE_STDERR)) {
+			iterator.get ();
+			Posix.exit (0);
+		}
+		assert (!iterator.previous ());
+
+		assert (iterator.next ());
+		assert (iterator.get () == "four");
+		assert (iterator.next ());
+		assert (iterator.get () == "one");
+		iterator.remove ();
+		assert (!test_set.contains ("one"));
+		assert (iterator.has_next ());
+		assert (iterator.has_previous ());
+		assert (iterator.previous ());
+		assert (iterator.get () == "four");
+	}
+
+	public class BidirSubSetTests : Gee.TestCase {
+		private BidirSortedSet<string> master;
+		private BidirSortedSet<string> subset;
+		private BidirSortedSetTests test;
+		private SortedSetTests.SubSetTests.Type type;
+
+		public BidirSubSetTests(BidirSortedSetTests test, SortedSetTests.SubSetTests.Type type) {
+			base ("%s Subset".printf (type.to_string ()));
+			this.test = test;
+			this.type = type;
+			add_test ("[BidirSortedSet] bi-directional iterator", test_bidir_iterator);
+		}
+
+		public override void set_up () {
+			test.set_up ();
+			master = test.test_collection as BidirSortedSet<string>;
+			switch (type) {
+			case SortedSetTests.SubSetTests.Type.HEAD:
+				subset = master.head_set ("one") as BidirSortedSet<string>; break;
+			case SortedSetTests.SubSetTests.Type.TAIL:
+				subset = master.tail_set ("six") as BidirSortedSet<string>; break;
+			case SortedSetTests.SubSetTests.Type.SUB:
+				subset = master.sub_set ("four", "three") as BidirSortedSet<string>; break;
+			case SortedSetTests.SubSetTests.Type.EMPTY:
+				subset = master.sub_set ("three", "four") as BidirSortedSet<string>; break;
+			default:
+				assert_not_reached ();
+			}
+		}
+
+		public override void tear_down () {
+			test.tear_down ();
+		}
+
+		public void test_bidir_iterator () {
+			assert (master.add ("one"));
+			assert (master.add ("two"));
+			assert (master.add ("three"));
+			assert (master.add ("four"));
+			assert (master.add ("five"));
+			assert (master.add ("six"));
+			assert (master.size == 6);
+
+			string[] contains;
+			switch (type) {
+			case SortedSetTests.SubSetTests.Type.HEAD:
+				contains = {"five", "four"};
+				break;
+			case SortedSetTests.SubSetTests.Type.TAIL:
+				contains = {"six", "three", "two"};
+				break;
+			case SortedSetTests.SubSetTests.Type.SUB:
+				contains = {"four", "one", "six"};
+				break;
+			case SortedSetTests.SubSetTests.Type.EMPTY:
+				contains = {};
+				break;
+			default:
+				assert_not_reached ();
+			}
+
+			uint i = 0;
+			foreach (var e in subset) {
+				assert (e == contains[i++]);
+			}
+			assert (i == contains.length);
+
+
+			var iter = subset.bidir_iterator ();
+			if (type != SortedSetTests.SubSetTests.Type.EMPTY) {
+				assert (iter.last ());
+				assert (iter.get () == contains[contains.length - 1]);
+				assert (iter.first ());
+
+				assert (iter.get () == contains[0]);
+				assert (iter.has_next ());
+				assert (iter.next ());
+				assert (iter.get () == contains[1]);
+				assert (iter.has_previous ());
+				iter.remove ();
+				assert (iter.has_previous ());
+				if (type != SortedSetTests.SubSetTests.Type.HEAD)
+					assert (iter.has_next ());
+				else
+					assert (!iter.has_next ());
+				assert (iter.previous ());
+				assert (iter.get () == contains[0]);
+			} else {
+				assert (!iter.first ());
+				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
+				                       TestTrapFlags.SILENCE_STDERR)) {
+					iter.remove ();
+					Posix.exit (0);
+				}
+				Test.trap_assert_failed ();
+			}
+		}
+	}
+}
+
diff --git a/tests/testsortedmap.vala b/tests/testsortedmap.vala
index 6fcc440..abfbfc8 100644
--- a/tests/testsortedmap.vala
+++ b/tests/testsortedmap.vala
@@ -31,14 +31,10 @@ public abstract class Gee.SortedMapTests : MapTests {
 		add_test ("[SortedMap] higher", test_higher);
 		add_test ("[SortedMap] floor", test_floor);
 		add_test ("[SortedMap] ceil", test_ceil);
-		add_test ("[SortedMap] bi-directional iterators can go backward",
-		          test_bidir_iterator_can_go_backward);
-		add_test ("[SortedSet] bi-directional iterators can to end",
-		          test_bidir_iterator_last);
-		get_suite ().add_suite (new SubMap (this, SubMap.Type.HEAD).get_suite ());
-		get_suite ().add_suite (new SubMap (this, SubMap.Type.TAIL).get_suite ());
-		get_suite ().add_suite (new SubMap (this, SubMap.Type.SUB).get_suite ());
-		get_suite ().add_suite (new SubMap (this, SubMap.Type.EMPTY).get_suite ());
+		get_suite ().add_suite (new SubMapTests (this, SubMapTests.Type.HEAD).get_suite ());
+		get_suite ().add_suite (new SubMapTests (this, SubMapTests.Type.TAIL).get_suite ());
+		get_suite ().add_suite (new SubMapTests (this, SubMapTests.Type.SUB).get_suite ());
+		get_suite ().add_suite (new SubMapTests (this, SubMapTests.Type.EMPTY).get_suite ());
 	}
 
 	public void test_key_ordering () {
@@ -126,7 +122,7 @@ public abstract class Gee.SortedMapTests : MapTests {
 		assert (keys.first () == "eight");
 		/*assert_entry (entries.first (), "eight", "eight");*/
 	}
-	
+
 	public void test_last () {
 		var test_sorted_map = test_map as SortedMap<string,string>;
 		var keys = test_sorted_map.ascending_keys;
@@ -386,205 +382,7 @@ public abstract class Gee.SortedMapTests : MapTests {
 		assert_entry (entries.ceil (entry_for ("s", "six")), "six", "six");
 	}
 
-	public void test_bidir_iterator_can_go_backward () {
-		var test_sorted_map = test_map as SortedMap<string,string>;
-		var keys = test_sorted_map.ascending_keys;
-		var entries = test_sorted_map.ascending_entries;
-
-		var keys_iterator = keys.bidir_iterator ();
-		var entries_iterator = entries.bidir_iterator ();
-		var map_iterator = test_sorted_map.bidir_map_iterator ();
-
-		assert (!keys_iterator.has_previous ());
-		assert (!entries_iterator.has_previous ());
-
-		assert (!map_iterator.has_previous ());
-		assert (!keys_iterator.previous ());
-		assert (!entries_iterator.has_previous ());
-
-		assert (!map_iterator.previous ());
-
-		test_sorted_map.set ("one", "one");
-		test_sorted_map.set ("two", "two");
-		test_sorted_map.set ("three", "three");
-		test_sorted_map.set ("four", "four");
-		test_sorted_map.set ("five", "five");
-		test_sorted_map.set ("six", "six");
-
-		keys_iterator = keys.bidir_iterator ();
-		entries_iterator = entries.bidir_iterator ();
-		map_iterator = test_sorted_map.bidir_map_iterator ();
-
-		assert (keys_iterator.next ());
-		assert (entries_iterator.next ());
-
-		assert (map_iterator.next ());
-		assert (keys_iterator.get () == "five");
-		assert_entry (entries_iterator.get (), "five", "five");
-
-		assert (map_iterator.get_key () == "five");
-		assert (map_iterator.get_value () == "five");
-
-		assert (!keys_iterator.has_previous ());
-		assert (!entries_iterator.has_previous ());
-
-		assert (!map_iterator.has_previous ());
-		assert (keys_iterator.next ());
-		assert (entries_iterator.next ());
-
-		assert (map_iterator.next ());
-		assert (keys_iterator.get () == "four");
-		assert_entry (entries_iterator.get (), "four", "four");
-
-		assert (map_iterator.get_key () == "four");
-		assert (map_iterator.get_value () == "four");
-
-		assert (keys_iterator.has_previous ());
-		assert (entries_iterator.has_previous ());
-
-		assert (map_iterator.has_previous ());
-		assert (keys_iterator.next ());
-		assert (entries_iterator.next ());
-
-		assert (map_iterator.next ());
-		assert (keys_iterator.get () == "one");
-		assert_entry (entries_iterator.get (), "one", "one");
-
-		assert (map_iterator.get_key () == "one");
-		assert (map_iterator.get_value () == "one");
-
-		assert (keys_iterator.has_previous ());
-		assert (entries_iterator.has_previous ());
-
-		assert (map_iterator.has_previous ());
-		assert (keys_iterator.next ());
-		assert (entries_iterator.next ());
-
-		assert (map_iterator.next ());
-		assert (keys_iterator.get () == "six");
-		assert_entry (entries_iterator.get (), "six", "six");
-
-		assert (map_iterator.get_key () == "six");
-		assert (map_iterator.get_value () == "six");
-		assert (keys_iterator.has_previous ());
-
-		assert (entries_iterator.has_previous ());
-		assert (map_iterator.has_previous ());
-		assert (keys_iterator.next ());
-
-		assert (entries_iterator.next ());
-		assert (map_iterator.next ());
-		assert (keys_iterator.get () == "three");
-
-		assert_entry (entries_iterator.get (), "three", "three");
-		assert (map_iterator.get_key () == "three");
-		assert (map_iterator.get_value () == "three");
-
-		assert (keys_iterator.has_previous ());
-		assert (entries_iterator.has_previous ());
-		assert (map_iterator.has_previous ());
-
-		assert (keys_iterator.next ());
-		assert (entries_iterator.next ());
-		assert (map_iterator.next ());
-
-		assert (keys_iterator.get () == "two");
-		assert_entry (entries_iterator.get (), "two", "two");
-		assert (map_iterator.get_key () == "two");
-		assert (map_iterator.get_value () == "two");
-
-		assert (keys_iterator.has_previous ());
-		assert (entries_iterator.has_previous ());
-		assert (map_iterator.has_previous ());
-
-		assert (!keys_iterator.next ());
-		assert (!entries_iterator.next ());
-		assert (!map_iterator.next ());
-
-		assert (keys_iterator.previous ());
-		assert (entries_iterator.previous ());
-		assert (map_iterator.previous ());
-
-		assert (keys_iterator.get () == "three");
-		assert_entry (entries_iterator.get (), "three", "three");
-		assert (map_iterator.get_key () == "three");
-		assert (map_iterator.get_value () == "three");
-
-		assert (keys_iterator.previous ());
-		assert (entries_iterator.previous ());
-		assert (map_iterator.previous ());
-
-		assert (keys_iterator.get () == "six");
-		assert_entry (entries_iterator.get (), "six", "six");
-		assert (map_iterator.get_key () == "six");
-		assert (map_iterator.get_value () == "six");
-
-		assert (keys_iterator.previous ());
-		assert (entries_iterator.previous ());
-		assert (map_iterator.previous ());
-
-		assert (keys_iterator.get () == "one");
-		assert_entry (entries_iterator.get (), "one", "one");
-		assert (map_iterator.get_key () == "one");
-		assert (map_iterator.get_value () == "one");
-
-		assert (keys_iterator.previous ());
-		assert (entries_iterator.previous ());
-		assert (map_iterator.previous ());
-
-		assert (keys_iterator.get () == "four");
-		assert_entry (entries_iterator.get (), "four", "four");
-		assert (map_iterator.get_key () == "four");
-		assert (map_iterator.get_value () == "four");
-
-		assert (keys_iterator.previous ());
-		assert (entries_iterator.previous ());
-		assert (map_iterator.previous ());
-
-		assert (keys_iterator.get () == "five");
-		assert_entry (entries_iterator.get (), "five", "five");
-		assert (map_iterator.get_key () == "five");
-		assert (map_iterator.get_value () == "five");
-
-		assert (!keys_iterator.previous ());
-		assert (!entries_iterator.previous ());
-		assert (!map_iterator.previous ());
-
-		assert (keys_iterator.get () == "five");
-		assert_entry (entries_iterator.get (), "five", "five");
-		assert (map_iterator.get_key () == "five");
-		assert (map_iterator.get_value () == "five");
-	}
-
-	public void test_bidir_iterator_last () {
-		var test_sorted_map = test_map as SortedMap<string,string>;
-		var keys = test_sorted_map.ascending_keys;
-		var entries = test_sorted_map.ascending_entries;
-
-		var keys_iterator = keys.bidir_iterator ();
-		var entries_iterator = entries.bidir_iterator ();
-
-		assert (!keys_iterator.last ());
-		assert (!entries_iterator.last ());
-
-		test_sorted_map.set ("one", "one");
-		test_sorted_map.set ("two", "two");
-		test_sorted_map.set ("three", "three");
-		test_sorted_map.set ("four", "four");
-		test_sorted_map.set ("five", "five");
-		test_sorted_map.set ("six", "six");
-
-		keys_iterator = keys.bidir_iterator ();
-		entries_iterator = entries.bidir_iterator ();
-
-		assert (keys_iterator.last ());
-		assert (entries_iterator.last ());
-
-		assert (keys_iterator.get () == "two");
-		assert_entry (entries_iterator.get (), "two", "two");
-	}
-
-	public class SubMap : Gee.TestCase {
+	public class SubMapTests : Gee.TestCase {
 		private SortedMap<string,string> master;
 		private SortedMap<string,string> submap;
 		private SortedMapTests test;
@@ -605,7 +403,7 @@ public abstract class Gee.SortedMapTests : MapTests {
 		}
 		private Type type;
 		
-		public SubMap (SortedMapTests test, Type type) {
+		public SubMapTests (SortedMapTests test, Type type) {
 			base ("%s Submap".printf (type.to_string ()));
 			this.test = test;
 			this.type = type;
@@ -881,45 +679,36 @@ public abstract class Gee.SortedMapTests : MapTests {
 		public void test_iterators () {
 			string[] contains, not_contains;
 
-			var _map_iter = submap.bidir_map_iterator ();
+			var _map_iter = submap.map_iterator ();
 
 			assert (!_map_iter.has_next ());
 			assert (!_map_iter.next ());
-			assert (!_map_iter.has_previous ());
-			assert (!_map_iter.previous ());
-			
+
 			set_default_values (out contains, out not_contains);
-			
+
 			var i = 0;
-			_map_iter = submap.bidir_map_iterator ();
+			_map_iter = submap.map_iterator ();
 			while (_map_iter.next ()) {
 				assert (_map_iter.get_key () == contains[i]);
 				assert (_map_iter.get_value () == contains[i]);
 				i++;
 			}
 			assert (i == contains.length);
-			
+
 			i = 0;
 			foreach (var k in submap.keys)
 				assert (k == contains[i++]);
 			assert (i == contains.length);
-			
+
 			i = 0;
 			foreach (var e in submap.entries) {
 				MapTests.assert_entry (e, contains[i], contains[i]);
 				i++;
 			}
 			assert (i == contains.length);
-			
-			var keys_iter = submap.ascending_keys.bidir_iterator ();
-			var entries_iter = submap.ascending_entries.bidir_iterator ();
-			var map_iter = submap.bidir_map_iterator ();
-			if (type != Type.EMPTY) {
-				assert (map_iter.last ());
-				assert (map_iter.get_key () == contains[contains.length - 1]);
-				assert (map_iter.get_value () == contains[contains.length - 1]);
 
-				map_iter = submap.bidir_map_iterator ();
+			if (type != Type.EMPTY) {
+				var map_iter = submap.map_iterator ();
 				assert (map_iter.next ());
 
 				assert (map_iter.get_key () == contains[0]);
@@ -930,80 +719,39 @@ public abstract class Gee.SortedMapTests : MapTests {
 				assert (map_iter.get_key () == contains[1]);
 				assert (map_iter.get_value () == contains[1]);
 
-				assert (map_iter.has_previous ());
-				map_iter.unset ();
-				assert (map_iter.has_previous ());
-				if (type != Type.HEAD)
-					assert (map_iter.has_next ());
-				else
-					assert (!map_iter.has_next ());
-				assert (map_iter.previous ());
-				assert (map_iter.get_key () == contains[0]);
-				assert (map_iter.get_value () == contains[0]);
-				
 				// Repeat for keys
 				master.clear ();
 				set_default_values (out contains, out not_contains);
-				
-				assert (keys_iter.last ());
-				assert (keys_iter.get () == contains[contains.length - 1]);
-				assert (keys_iter.first ());
+				var keys_iter = submap.ascending_keys.iterator ();
+
+				assert (keys_iter.has_next ());
+				assert (keys_iter.next ());
 
 				assert (keys_iter.get () == contains[0]);
 				assert (keys_iter.has_next ());
 				assert (keys_iter.next ());
 				assert (keys_iter.get () == contains[1]);
-				assert (keys_iter.has_previous ());
-				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
-				                       TestTrapFlags.SILENCE_STDERR)) {
-					keys_iter.remove ();
-					Posix.exit (0);
-				}
-				assert (keys_iter.has_previous ());
-				if (type != Type.HEAD)
-					assert (keys_iter.has_next ());
-				else
-					assert (!keys_iter.has_next ());
-				assert (keys_iter.previous ());
-				assert (keys_iter.get () == contains[0]);
 				
 				// Repeat for entries
 				master.clear ();
 				set_default_values (out contains, out not_contains);
+				var entries_iter = submap.ascending_entries.iterator ();
 
-				assert (entries_iter.last ());
-				MapTests.assert_entry (entries_iter.get (), contains[contains.length - 1], contains[contains.length - 1]);
-				assert (entries_iter.first ());
+				assert (entries_iter.has_next ());
+				assert (entries_iter.next ());
 
 				MapTests.assert_entry (entries_iter.get (), contains[0], contains[0]);
 				assert (entries_iter.has_next ());
 				assert (entries_iter.next ());
 				MapTests.assert_entry (entries_iter.get (), contains[1], contains[1]);
-				assert (entries_iter.has_previous ());
-				entries_iter.remove ();
-				assert (entries_iter.has_previous ());
-				if (type != Type.HEAD)
-					assert (entries_iter.has_next ());
-				else
-					assert (!entries_iter.has_next ());
-				assert (entries_iter.previous ());
-				MapTests.assert_entry (entries_iter.get (), contains[0], contains[0]);
 			} else {
-				assert (!keys_iter.first ());
-				assert (!keys_iter.last ());
+				var keys_iter = submap.ascending_keys.iterator ();
 				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
 				                       TestTrapFlags.SILENCE_STDERR)) {
 					keys_iter.remove ();
 					Posix.exit (0);
 				}
 				Test.trap_assert_failed ();
-				assert (!entries_iter.first ());
-				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
-				                       TestTrapFlags.SILENCE_STDERR)) {
-					entries_iter.remove ();
-					Posix.exit (0);
-				}
-				Test.trap_assert_failed ();
 			}
 		}
 		
diff --git a/tests/testsortedset.vala b/tests/testsortedset.vala
index 5371d7c..fdd6e44 100644
--- a/tests/testsortedset.vala
+++ b/tests/testsortedset.vala
@@ -24,7 +24,6 @@ using GLib;
 using Gee;
 
 public abstract class SortedSetTests : SetTests {
-
 	public SortedSetTests (string name) {
 		base (name);
 		add_test ("[SortedSet] first", test_first);
@@ -35,18 +34,10 @@ public abstract class SortedSetTests : SetTests {
 		add_test ("[SortedSet] higher", test_higher);
 		add_test ("[SortedSet] floor", test_floor);
 		add_test ("[SortedSet] ceil", test_ceil);
-		add_test ("[SortedSet] bi-directional iterators can go backward",
-		          test_bidir_iterator_can_go_backward);
-		add_test ("[SortedSet] bi-directional iterators are mutable",
-		          test_mutable_bidir_iterator);
-		add_test ("[SortedSet] bi-directional iterators can to beginning",
-		          test_bidir_iterator_first);
-		add_test ("[SortedSet] bi-directional iterators can to end",
-		          test_bidir_iterator_last);
-		get_suite ().add_suite (new SubSet (this, SubSet.Type.HEAD).get_suite ());
-		get_suite ().add_suite (new SubSet (this, SubSet.Type.TAIL).get_suite ());
-		get_suite ().add_suite (new SubSet (this, SubSet.Type.SUB).get_suite ());
-		get_suite ().add_suite (new SubSet (this, SubSet.Type.EMPTY).get_suite ());
+		get_suite ().add_suite (new SubSetTests (this, SubSetTests.Type.HEAD).get_suite ());
+		get_suite ().add_suite (new SubSetTests (this, SubSetTests.Type.TAIL).get_suite ());
+		get_suite ().add_suite (new SubSetTests (this, SubSetTests.Type.SUB).get_suite ());
+		get_suite ().add_suite (new SubSetTests (this, SubSetTests.Type.EMPTY).get_suite ());
 	}
 
 	public void test_ordering () {
@@ -255,141 +246,7 @@ public abstract class SortedSetTests : SetTests {
 		assert (test_set.ceil ("s") == "six");
 	}
 
-	public void test_bidir_iterator_can_go_backward () {
-		var test_set = test_collection as SortedSet<string>;
-
-		var iterator = test_set.bidir_iterator ();
-		assert (!iterator.has_previous ());
-
-		assert (test_set.add ("one"));
-		assert (test_set.add ("two"));
-		assert (test_set.add ("three"));
-		assert (test_set.add ("four"));
-		assert (test_set.add ("five"));
-		assert (test_set.add ("six"));
-
-		iterator = test_set.bidir_iterator ();
-		assert (iterator.next ());
-		assert (iterator.get () == "five");
-		assert (!iterator.has_previous ());
-		assert (iterator.next ());
-		assert (iterator.get () == "four");
-		assert (iterator.has_previous ());
-		assert (iterator.next ());
-		assert (iterator.get () == "one");
-		assert (iterator.has_previous ());
-		assert (iterator.next ());
-		assert (iterator.get () == "six");
-		assert (iterator.has_previous ());
-		assert (iterator.next ());
-		assert (iterator.get () == "three");
-		assert (iterator.has_previous ());
-		assert (iterator.next ());
-		assert (iterator.get () == "two");
-		assert (iterator.has_previous ());
-		assert (!iterator.next ());
-		assert (iterator.previous ());
-		assert (iterator.get () == "three");
-		assert (iterator.previous ());
-		assert (iterator.get () == "six");
-		assert (iterator.previous ());
-		assert (iterator.get () == "one");
-		assert (iterator.previous ());
-		assert (iterator.get () == "four");
-		assert (iterator.previous ());
-		assert (iterator.get () == "five");
-		assert (!iterator.previous ());
-		assert (iterator.get () == "five");
-	}
-
-	public void test_bidir_iterator_first () {
-		var test_set = test_collection as SortedSet<string>;
-
-		var iterator = test_set.bidir_iterator ();
-
-		assert (!iterator.first ());
-
-		assert (test_set.add ("one"));
-		assert (test_set.add ("two"));
-		assert (test_set.add ("three"));
-		assert (test_set.add ("four"));
-		assert (test_set.add ("five"));
-		assert (test_set.add ("six"));
-
-		iterator = test_set.bidir_iterator ();
-		assert (iterator.last ());
-		assert (iterator.get () == "two");
-		assert (iterator.first ());
-		assert (iterator.get () == "five");
-	}
-
-	public void test_bidir_iterator_last () {
-		var test_set = test_collection as SortedSet<string>;
-
-		var iterator = test_set.bidir_iterator ();
-
-		assert (!iterator.last ());
-
-		assert (test_set.add ("one"));
-		assert (test_set.add ("two"));
-		assert (test_set.add ("three"));
-		assert (test_set.add ("four"));
-		assert (test_set.add ("five"));
-		assert (test_set.add ("six"));
-
-		iterator = test_set.bidir_iterator ();
-		assert (iterator.last ());
-		assert (iterator.get () == "two");
-	}
-
-	public void test_mutable_bidir_iterator () {
-		var test_set = test_collection as SortedSet<string>;
-
-		var iterator = test_set.bidir_iterator ();
-		assert (!iterator.has_previous ());
-
-		assert (test_set.add ("one"));
-		assert (test_set.add ("two"));
-		assert (test_set.add ("three"));
-		assert (test_set.add ("four"));
-		assert (test_set.add ("five"));
-		assert (test_set.add ("six"));
-
-		iterator = test_set.bidir_iterator ();
-
-		if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
-		                       TestTrapFlags.SILENCE_STDERR)) {
-			iterator.remove ();
-			Posix.exit (0);
-		}
-		Test.trap_assert_failed ();
-
-		assert (iterator.next ());
-		assert (iterator.get () == "five");
-		iterator.remove ();
-		assert (!test_set.contains ("five"));
-		assert (iterator.has_next ());
-		assert (!iterator.has_previous ());
-		if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
-		                       TestTrapFlags.SILENCE_STDERR)) {
-			iterator.get ();
-			Posix.exit (0);
-		}
-		assert (!iterator.previous ());
-
-		assert (iterator.next ());
-		assert (iterator.get () == "four");
-		assert (iterator.next ());
-		assert (iterator.get () == "one");
-		iterator.remove ();
-		assert (!test_set.contains ("one"));
-		assert (iterator.has_next ());
-		assert (iterator.has_previous ());
-		assert (iterator.previous ());
-		assert (iterator.get () == "four");
-	}
-
-	public class SubSet : Gee.TestCase {
+	protected class SubSetTests : Gee.TestCase {
 		private SortedSet<string> master;
 		private SortedSet<string> subset;
 		private SortedSetTests test;
@@ -410,7 +267,7 @@ public abstract class SortedSetTests : SetTests {
 		}
 		private Type type;
 
-		public SubSet (SortedSetTests test, Type type) {
+		public SubSetTests (SortedSetTests test, Type type) {
 			base ("%s Subset".printf (type.to_string ()));
 			this.test = test;
 			this.type = type;
@@ -644,27 +501,15 @@ public abstract class SortedSetTests : SetTests {
 			assert (i == contains.length);
 
 
-			var iter = subset.bidir_iterator ();
+			var iter = subset.iterator ();
 			if (type != Type.EMPTY) {
-				assert (iter.last ());
-				assert (iter.get () == contains[contains.length - 1]);
-				assert (iter.first ());
-
+				assert (iter.has_next ());
+				assert (iter.next ());
 				assert (iter.get () == contains[0]);
 				assert (iter.has_next ());
 				assert (iter.next ());
 				assert (iter.get () == contains[1]);
-				assert (iter.has_previous ());
-				iter.remove ();
-				assert (iter.has_previous ());
-				if (type != Type.HEAD)
-					assert (iter.has_next ());
-				else
-					assert (!iter.has_next ());
-				assert (iter.previous ());
-				assert (iter.get () == contains[0]);
 			} else {
-				assert (!iter.first ());
 				if (Test.trap_fork (0, TestTrapFlags.SILENCE_STDOUT |
 				                       TestTrapFlags.SILENCE_STDERR)) {
 					iter.remove ();
diff --git a/tests/testtreemap.vala b/tests/testtreemap.vala
index 6cb7857..6babece 100644
--- a/tests/testtreemap.vala
+++ b/tests/testtreemap.vala
@@ -23,7 +23,7 @@
 
 using Gee;
 
-public class TreeMapTests : SortedMapTests {
+public class TreeMapTests : BidirSortedMapTests {
 
 	public TreeMapTests () {
 		base ("TreeMap");
diff --git a/tests/testtreeset.vala b/tests/testtreeset.vala
index 0a28d7e..e407945 100644
--- a/tests/testtreeset.vala
+++ b/tests/testtreeset.vala
@@ -23,7 +23,7 @@
 
 using Gee;
 
-public class TreeSetTests : SortedSetTests {
+public class TreeSetTests : BidirSortedSetTests {
 
 	public TreeSetTests () {
 		base ("TreeSet");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]