You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2006/08/25 01:53:28 UTC

svn commit: r434575 - in /geronimo/xbean/branches/colossus/xbean-naming/src: main/java/org/apache/xbean/naming/context/ test/java/org/apache/xbean/naming/context/

Author: dain
Date: Thu Aug 24 16:53:28 2006
New Revision: 434575

URL: http://svn.apache.org/viewvc?rev=434575&view=rev
Log:
Added exception handling tests for bind, unbind, rebind, rename, createSubcontext and destroySubContext.
Fixed all bugs found by the above tests.

Modified:
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractFederatedContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java
    geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/WritableContextTest.java

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java?rev=434575&r1=434574&r2=434575&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java Thu Aug 24 16:53:28 2006
@@ -183,7 +183,12 @@
     }
 
     protected Context lookupFinalContext(Name name) throws NamingException {
-        Object value = lookup(name.getPrefix(name.size() - 1));
+        Object value = null;
+        try {
+            value = lookup(name.getPrefix(name.size() - 1));
+        } catch (NamingException e) {
+            throw new NotContextException("The intermediate context " + name.get(name.size() - 1) + " does not exist");
+        }
 
         if (value == null) {
             throw new NotContextException("The intermediate context " + name.get(name.size() - 1) + " does not exist");
@@ -353,9 +358,10 @@
      * Removes the binding from the context.  The name will not contain a path and the value will not
      * be a nested context although it may be a foreign context.
      * @param name name under which the value should be bound
+     * @param removeNotEmptyContext
      * @throws NamingException if a problem occurs during the bind such as a value already being bound
      */
-    protected abstract boolean removeBinding(String name) throws NamingException;
+    protected abstract boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException;
 
     protected void removeDeepBinding(Name name, boolean pruneEmptyContexts) throws NamingException {
         if (name == null) throw new NullPointerException("name is null");
@@ -364,7 +370,7 @@
         }
 
         if (name.size() == 1) {
-            removeBinding(name.get(0));
+            removeBinding(name.get(0), false);
             return;
         }
 
@@ -388,7 +394,7 @@
                 }
 
                 // update targets
-                if (isEmpty(currentContext)) {
+                if (getSize(currentContext) > 1) {
                     targetContext = currentContext;
                     targetName = part;
                 }
@@ -397,7 +403,7 @@
                 // Is this the last element in the name?
                 if (i == name.size() - 1) {
                     // we're at the end... unbind value
-                    unbind(targetContext, targetName);
+                    unbind(targetContext, targetName, true);
 
                     // all done... this is redundant but makes the code more readable
                     break;
@@ -406,7 +412,7 @@
                     if (currentValue == null) {
                         // path not found we are done, but first prune the empty contexts
                         if (targetContext != currentContext) {
-                            unbind(targetContext, targetName);
+                            unbind(targetContext, targetName, false);
                         }
                         break;
                     } else {
@@ -423,17 +429,30 @@
         }
     }
 
-    private static boolean isEmpty(Context context) throws NamingException {
+    protected static boolean isEmpty(Context context) throws NamingException {
         if (context instanceof AbstractContext) {
             AbstractContext abstractContext = (AbstractContext) context;
             Map currentBindings = abstractContext.getBindings();
-            return currentBindings.size() > 1;
+            return currentBindings.isEmpty();
         } else {
             NamingEnumeration namingEnumeration = context.list("");
             return namingEnumeration.hasMore();
         }
     }
 
+    protected static int getSize(Context context) throws NamingException {
+        if (context instanceof AbstractContext) {
+            AbstractContext abstractContext = (AbstractContext) context;
+            Map currentBindings = abstractContext.getBindings();
+            return currentBindings.size();
+        } else {
+            NamingEnumeration namingEnumeration = context.list("");
+            int size = 0;
+            while (namingEnumeration.hasMore()) size++;
+            return size;
+        }
+    }
+
     /**
      * Unbinds any value bound to the specified name within the specified context.  If the specified context is an
      * AbstractContext and is a nested context, this method will call the direct removeBinding method, otherwise it
@@ -441,12 +460,13 @@
      *
      * @param context the context to remove the binding from
      * @param name the binding name
+     * @param removeNotEmptyContext
      * @throws NamingException if a problem occurs while unbinding
      */
-    private void unbind(Context context, String name) throws NamingException {
+    private void unbind(Context context, String name, boolean removeNotEmptyContext) throws NamingException {
         if (context == this || (context instanceof AbstractContext && isNestedSubcontext(context))) {
             AbstractContext abstractContext = (AbstractContext) context;
-            abstractContext.removeBinding(name);
+            abstractContext.removeBinding(name, removeNotEmptyContext);
         } else {
             context.unbind(name);
         }
@@ -651,7 +671,7 @@
         if (oldName == null || newName == null) {
             throw new NullPointerException("name is null");
         } else if (oldName.isEmpty() || newName.isEmpty()) {
-            throw new InvalidNameException("Name cannot be empty");
+            throw new NameAlreadyBoundException("Name cannot be empty");
         }
         this.bind(newName, this.lookup(oldName));
         this.unbind(oldName);
@@ -800,7 +820,7 @@
         if (!modifiable) throw new OperationNotSupportedException("Context is read only");
         if (name == null) throw new NullPointerException("name is null");
         if (name.isEmpty()) {
-            throw new InvalidNameException("Cannot create a subcontext if the name is empty");
+            throw new NameAlreadyBoundException("Cannot create a subcontext if the name is empty");
         }
         Context abstractContext = createNestedSubcontext(name.toString(), Collections.EMPTY_MAP);
         addDeepBinding(name, abstractContext, false, false);

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractFederatedContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractFederatedContext.java?rev=434575&r1=434574&r2=434575&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractFederatedContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractFederatedContext.java Thu Aug 24 16:53:28 2006
@@ -96,7 +96,7 @@
         return false;
     }
 
-    protected boolean removeBinding(String name) throws NamingException {
+    protected boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException {
         return contextFederation.removeBinding(name);
     }
 

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java?rev=434575&r1=434574&r2=434575&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java Thu Aug 24 16:53:28 2006
@@ -97,7 +97,7 @@
         throw new OperationNotSupportedException("Context is immutable");
     }
 
-    protected final boolean removeBinding(String name) throws NamingException {
+    protected final boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException {
         throw new OperationNotSupportedException("Context is immutable");
     }
 
@@ -150,7 +150,7 @@
             throw new OperationNotSupportedException("Context is immutable");
         }
 
-        protected final boolean removeBinding(String name) throws NamingException {
+        protected final boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException {
             throw new OperationNotSupportedException("Context is immutable");
         }
 

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java?rev=434575&r1=434574&r2=434575&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java Thu Aug 24 16:53:28 2006
@@ -23,6 +23,8 @@
 
 import javax.naming.Context;
 import javax.naming.NamingException;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.ContextNotEmptyException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -76,15 +78,18 @@
             return true;
         }
 
-        addBinding(bindingsRef, name, value);
+        addBinding(bindingsRef, name, value, rebind);
         return true;
     }
 
-    protected void addBinding(AtomicReference bindingsRef, String name, Object value) throws NamingException {
+    protected void addBinding(AtomicReference bindingsRef, String name, Object value, boolean rebind) throws NamingException {
         writeLock.lock();
         try {
             Map bindings = (Map) bindingsRef.get();
 
+            if (!rebind && bindings.containsKey(name)) {
+                throw new NameAlreadyBoundException(name);
+            }
             if (cacheReferences) {
                 value = CachingReference.wrapReference(getNameInNamespace(name), value);
             }
@@ -112,15 +117,15 @@
         return newIndex;
     }
 
-    protected boolean removeBinding(String name) throws NamingException {
-        if (super.removeBinding(name)) {
+    protected boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException {
+        if (super.removeBinding(name, removeNotEmptyContext)) {
             return true;
         }
-        removeBinding(bindingsRef, name);
+        removeBinding(bindingsRef, name, removeNotEmptyContext);
         return true;
     }
 
-    private boolean removeBinding(AtomicReference bindingsRef, String name) {
+    private boolean removeBinding(AtomicReference bindingsRef, String name, boolean removeNotEmptyContext) throws NamingException {
         writeLock.lock();
         try {
             Map bindings = (Map) bindingsRef.get();
@@ -130,7 +135,10 @@
             }
 
             Map newBindings = new HashMap(bindings);
-            newBindings.remove(name);
+            Object oldValue = newBindings.remove(name);
+            if (!removeNotEmptyContext && oldValue instanceof Context && !isEmpty((Context)oldValue)) {
+                throw new ContextNotEmptyException(name);
+            }
             bindingsRef.set(newBindings);
 
             Map newIndex = removeFromIndex(name);
@@ -225,15 +233,15 @@
                 return true;
             }
 
-            WritableContext.this.addBinding(bindingsRef, name, value);
+            WritableContext.this.addBinding(bindingsRef, name, value, rebind);
             return true;
         }
 
-        protected boolean removeBinding(String name) throws NamingException {
-            if (WritableContext.this.removeBinding(bindingsRef, name)) {
+        protected boolean removeBinding(String name, boolean removeNotEmptyContext) throws NamingException {
+            if (WritableContext.this.removeBinding(bindingsRef, name, false)) {
                 return true;
             }
-            return super.removeBinding(name);
+            return super.removeBinding(name, false);
         }
     }
 }

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java?rev=434575&r1=434574&r2=434575&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java Thu Aug 24 16:53:28 2006
@@ -381,7 +381,7 @@
         context.rename(nameString, newNameString);
         assertSame(value, context.lookup(newNameString));
         assertNoBinding(context, nameString);
-        context.unbind(nameString);
+        context.unbind(newNameString);
 
         assertNoBinding(context, nameString);
 
@@ -390,7 +390,7 @@
         context.rename(name, newName);
         assertSame(value, context.lookup(newName));
         assertNoBinding(context, name);
-        context.unbind(name);
+        context.unbind(newName);
 
         assertNoBinding(context, name);
 

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/WritableContextTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/WritableContextTest.java?rev=434575&r1=434574&r2=434575&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/WritableContextTest.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/WritableContextTest.java Thu Aug 24 16:53:28 2006
@@ -20,6 +20,9 @@
 import javax.naming.Name;
 import javax.naming.NameNotFoundException;
 import javax.naming.NotContextException;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.InvalidNameException;
+import javax.naming.ContextNotEmptyException;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -77,42 +80,48 @@
             fail("Expected NameNotFoundException");
         } catch (NameNotFoundException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.lookup(parse("a/b/c/d/e/NoSuchValue"));
             fail("Expected NameNotFoundException");
         } catch (NameNotFoundException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // lookup a non-existing value of a non-exisitng context
         //
         try {
             context.list("a/b/NoSuchContext/NoSuchContext");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.list(parse("a/b/NoSuchContext/NoSuchContext"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // lookup null
         //
         try {
             context.lookup((String)null);
-            fail("Expected NotContextException");
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.lookup((Name)null);
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
-
+        assertEq(bindings, context);
     }
 
     public void testLookupLinkExceptions() throws Exception{
@@ -124,42 +133,48 @@
             fail("Expected NameNotFoundException");
         } catch (NameNotFoundException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.lookupLink(parse("a/b/c/d/e/NoSuchValue"));
             fail("Expected NameNotFoundException");
         } catch (NameNotFoundException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // lookupLink a non-existing value of a non-exisitng context
         //
         try {
             context.list("a/b/NoSuchContext/NoSuchContext");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.list(parse("a/b/NoSuchContext/NoSuchContext"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // lookupLink null
         //
         try {
             context.lookupLink((String)null);
-            fail("Expected NotContextException");
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.lookupLink((Name)null);
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
-
+        assertEq(bindings, context);
     }
 
     public void testListExceptions() throws Exception{
@@ -168,60 +183,68 @@
         //
         try {
             context.list("a/b/c/d/e/NoSuchContext");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.list(parse("a/b/c/d/e/NoSuchContext"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // list a non-existing subcontext of a non-exisitng context
         //
         try {
             context.list("a/b/NoSuchContext/NoSuchContext");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.list(parse("a/b/NoSuchContext/NoSuchContext"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // list a binding that is a value instead of a context
         //
         try {
             context.list("a/b/c/d/e/three");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.list(parse("a/b/c/d/e/three"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // list null
         //
         try {
             context.list((String)null);
-            fail("Expected NotContextException");
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.list((Name)null);
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
-
+        assertEq(bindings, context);
     }
 
     public void testListBindingsExceptions() throws Exception{
@@ -230,60 +253,68 @@
         //
         try {
             context.listBindings("a/b/c/d/e/NoSuchContext");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.listBindings(parse("a/b/c/d/e/NoSuchContext"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // listBindings a non-existing subcontext of a non-exisitng context
         //
         try {
             context.listBindings("a/b/NoSuchContext/NoSuchContext");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.listBindings(parse("a/b/NoSuchContext/NoSuchContext"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // listBindings a binding that is a value instead of a context
         //
         try {
             context.listBindings("a/b/c/d/e/three");
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.listBindings(parse("a/b/c/d/e/three"));
-            fail("Expected NameNotFoundException");
+            fail("Expected NotContextException");
         } catch (NotContextException expected) {
         }
+        assertEq(bindings, context);
 
         //
         // listBindings null
         //
         try {
             context.listBindings((String)null);
-            fail("Expected NotContextException");
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
+        assertEq(bindings, context);
 
         try {
             context.listBindings((Name)null);
+            fail("Expected NullPointerException");
         } catch (NullPointerException expected) {
         }
-
+        assertEq(bindings, context);
     }
 
     public void testBind() throws Exception {
@@ -300,6 +331,76 @@
         assertEq(bindings, context);
     }
 
+    public void testBindExceptions() throws Exception{
+        //
+        // bind over existing value of an exisitng context
+        //
+        try {
+            context.bind("a/b/c/d/e/three", "value");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.bind(parse("a/b/c/d/e/three"), "value");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // bind over root context
+        //
+        try {
+            context.bind("", "value");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.bind(parse(""), "value");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // bind to non-existing context
+        //
+        try {
+            context.bind("a/b/NoSuchContext/name", "value");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.bind(parse("a/b/NoSuchContext/name"), "value");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // bind null
+        //
+        try {
+            context.bind((String)null, "value");
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.bind((Name)null, "value");
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+    }
+
     public void testUnbind() throws Exception {
         // unbind(String)
         bindings.remove("a/b/c/d/e/three");
@@ -314,6 +415,76 @@
         assertEq(bindings, context);
     }
 
+    public void testUnbindExceptions() throws Exception{
+        //
+        // unbind non empty context
+        //
+        try {
+            context.unbind("a/b/c");
+            fail("Expected ContextNotEmptyException");
+        } catch (ContextNotEmptyException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.unbind(parse("a/b/c"));
+            fail("Expected ContextNotEmptyException");
+        } catch (ContextNotEmptyException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // unbind root context
+        //
+        try {
+            context.unbind("");
+            fail("Expected InvalidNameException");
+        } catch (InvalidNameException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.unbind(parse(""));
+            fail("Expected InvalidNameException");
+        } catch (InvalidNameException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // unbind non-existing context
+        //
+        try {
+            context.unbind("a/b/NoSuchContext/name");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.unbind(parse("a/b/NoSuchContext/name"));
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // unbind null
+        //
+        try {
+            context.unbind((String)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.unbind((Name)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+    }
+
     public void testRebind() throws Exception {
         // rebind(String)
         bindings.put("a/b/c/d/e/three", new Integer(33));
@@ -326,6 +497,71 @@
         context.rebind(parse("a/b/c/d/e/three"), new Integer(33333));
 
         assertEq(bindings, context);
+
+        // rebind(String) - New Value
+        bindings.put("a/b/c/d/e/forty-two", new Integer(42));
+        context.rebind("a/b/c/d/e/forty-two", new Integer(42));
+
+        assertEq(bindings, context);
+
+        // rebind(Name) - New Value
+        bindings.put("a/b/c/d/e/forty-four", new Integer(44));
+        context.rebind(parse("a/b/c/d/e/forty-four"), new Integer(44));
+
+        assertEq(bindings, context);
+    }
+
+    public void testRebindExceptions() throws Exception{
+        //
+        // rebind over root context
+        //
+        try {
+            context.rebind("", "value");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rebind(parse(""), "value");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // rebind to non-existing context
+        //
+        try {
+            context.rebind("a/b/NoSuchContext/name", "value");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rebind(parse("a/b/NoSuchContext/name"), "value");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // rebind null
+        //
+        try {
+            context.rebind((String)null, "value");
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rebind((Name)null, "value");
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
     }
 
     public void testRename() throws Exception {
@@ -344,6 +580,105 @@
         assertEq(bindings, context);
     }
 
+    public void testRenameExceptions() throws Exception{
+        //
+        // rename over existing value of an exisitng context
+        //
+        try {
+            context.rename("a/b/c/d/e/one", "a/b/c/d/e/three");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename(parse("a/b/c/d/e/one"), parse("a/b/c/d/e/three"));
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // rename over root context
+        //
+        try {
+            context.rename("a/b/c/d/e/one", "");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename(parse("a/b/c/d/e/one"), parse(""));
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // rename to non-existing context
+        //
+        try {
+            context.rename("a/b/c/d/e/one", "a/b/NoSuchContext/name");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename(parse("a/b/c/d/e/one"), parse("a/b/NoSuchContext/name"));
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // rename null
+        //
+        try {
+            context.rename(null, "SOME_NAME");
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename(null, parse("SOME_NAME"));
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename("SOME_NAME", null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename(null, parse("SOME_NAME"));
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename((String)null, (String)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.rename((Name)null, (Name)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+
+        assertEq(bindings, context);
+    }
+
     public void testCreateSubcontext() throws Exception {
         // createSubcontext(String)
         bindings.put("a/b/c/d/e/f/foo", "bar");
@@ -360,6 +695,93 @@
         assertEq(bindings, context);
     }
 
+    public void testCreateSubcontextExceptions() throws Exception{
+        //
+        // createSubcontext over existing value of an exisitng context
+        //
+        try {
+            context.createSubcontext("a/b/c/d/e/three");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.createSubcontext(parse("a/b/c/d/e/three"));
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // createSubcontext over existing context
+        //
+        try {
+            context.createSubcontext("a/b/c");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.createSubcontext(parse("a/b/c"));
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // createSubcontext over root context
+        //
+        try {
+            context.createSubcontext("");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.createSubcontext(parse(""));
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // createSubcontext in a non-existing context
+        //
+        try {
+            context.createSubcontext("a/b/NoSuchContext/name");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.createSubcontext(parse("a/b/NoSuchContext/name"));
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // createSubcontext null
+        //
+        try {
+            context.createSubcontext((String)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.createSubcontext((Name)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+    }
+
     public void testDestroySubcontext() throws Exception {
         // destroySubcontext(String)
         bindings.put("a/b/c/d/e/f/foo", "bar");
@@ -383,6 +805,93 @@
         context.unbind(parse("a/b/c/d/e/f2/foo"));
         context.destroySubcontext(parse("a/b/c/d/e/f2"));
 
+        assertEq(bindings, context);
+    }
+
+    public void testDestroySubcontextExceptions() throws Exception{
+        //
+        // destroySubcontext a value (not a context)
+        //
+        try {
+            context.createSubcontext("a/b/c/d/e/three");
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.createSubcontext(parse("a/b/c/d/e/three"));
+            fail("Expected NameAlreadyBoundException");
+        } catch (NameAlreadyBoundException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // destroySubcontext non empty context
+        //
+        try {
+            context.destroySubcontext("a/b/c");
+            fail("Expected ContextNotEmptyException");
+        } catch (ContextNotEmptyException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.destroySubcontext(parse("a/b/c"));
+            fail("Expected ContextNotEmptyException");
+        } catch (ContextNotEmptyException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // destroySubcontext root context
+        //
+        try {
+            context.destroySubcontext("");
+            fail("Expected InvalidNameException");
+        } catch (InvalidNameException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.destroySubcontext(parse(""));
+            fail("Expected InvalidNameException");
+        } catch (InvalidNameException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // destroySubcontext non-existing context
+        //
+        try {
+            context.destroySubcontext("a/b/NoSuchContext/name");
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.destroySubcontext(parse("a/b/NoSuchContext/name"));
+            fail("Expected NotContextException");
+        } catch (NotContextException expected) {
+        }
+        assertEq(bindings, context);
+
+        //
+        // destroySubcontext null
+        //
+        try {
+            context.destroySubcontext((String)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
+        assertEq(bindings, context);
+
+        try {
+            context.destroySubcontext((Name)null);
+            fail("Expected NullPointerException");
+        } catch (NullPointerException expected) {
+        }
         assertEq(bindings, context);
     }
 }