You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/12/05 21:29:09 UTC

svn commit: r1210612 [2/2] - in /felix/trunk/http/whiteboard/src: main/java/org/apache/felix/http/whiteboard/ main/java/org/apache/felix/http/whiteboard/internal/ main/java/org/apache/felix/http/whiteboard/internal/manager/ main/java/org/apache/felix/h...

Added: felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerTest.java?rev=1210612&view=auto
==============================================================================
--- felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerTest.java (added)
+++ felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerTest.java Mon Dec  5 20:29:08 2011
@@ -0,0 +1,876 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.http.whiteboard.internal.manager;
+
+import static org.mockito.Mockito.when;
+
+import java.util.Dictionary;
+
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.collections.BidiMap;
+import org.apache.commons.collections.bidimap.DualHashBidiMap;
+import org.apache.felix.http.api.ExtHttpService;
+import org.apache.felix.http.whiteboard.HttpWhiteboardConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ExtenderManagerTest
+{
+
+    private static final String SAMPLE_CONTEXT_ID = "some.context.id";
+
+    private static final long BUNDLE_1_ID = 1L;
+
+    private static final long BUNDLE_2_ID = 2L;
+
+    private static final String SERVLET_1_ALIAS = "/servet1";
+
+    private static final String SERVLET_1_1_ALIAS = "/servet1_1";
+
+    private static final String SERVLET_2_ALIAS = "/servet2";
+
+    private MockExtHttpService httpService;
+
+    @Mock
+    private HttpContext sampleContext;
+
+    @Mock
+    private Bundle bundle1;
+
+    @Mock
+    private Bundle bundle2;
+
+    @Mock
+    private ExtServlet servlet1;
+
+    @Mock
+    private ExtServlet servlet1_1;
+
+    @Mock
+    private ExtServlet servlet2;
+
+    @Mock
+    private ExtFilter filter1;
+
+    @Mock
+    private ExtFilter filter1_1;
+
+
+    @Mock
+    private ExtFilter filter2;
+
+    @Mock
+    private ServiceReference servlet1Reference;
+
+    @Mock
+    private ServiceReference servlet1_1Reference;
+
+    @Mock
+    private ServiceReference servlet2Reference;
+
+    @Mock
+    private ServiceReference filter1Reference;
+
+    @Mock
+    private ServiceReference filter1_1Reference;
+
+    @Mock
+    private ServiceReference filter2Reference;
+
+    @Mock
+    private ServiceReference httpContextReference;
+
+    @Before
+    public void setup()
+    {
+        when(bundle1.getBundleId()).thenReturn(BUNDLE_1_ID);
+        when(bundle2.getBundleId()).thenReturn(BUNDLE_2_ID);
+        when(httpContextReference.getBundle()).thenReturn(bundle1);
+
+        when(servlet1Reference.getBundle()).thenReturn(bundle1);
+        when(servlet1Reference.getPropertyKeys()).thenReturn(new String[0]);
+        when(servlet1Reference.getProperty(HttpWhiteboardConstants.ALIAS)).thenReturn(SERVLET_1_ALIAS);
+
+        when(servlet1_1Reference.getBundle()).thenReturn(bundle1);
+        when(servlet1_1Reference.getPropertyKeys()).thenReturn(new String[0]);
+        when(servlet1_1Reference.getProperty(HttpWhiteboardConstants.ALIAS)).thenReturn(SERVLET_1_1_ALIAS);
+
+        when(servlet2Reference.getBundle()).thenReturn(bundle2);
+        when(servlet2Reference.getPropertyKeys()).thenReturn(new String[0]);
+        when(servlet2Reference.getProperty(HttpWhiteboardConstants.ALIAS)).thenReturn(SERVLET_2_ALIAS);
+        when(servlet2Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+
+        when(filter1Reference.getBundle()).thenReturn(bundle1);
+        when(filter1Reference.getPropertyKeys()).thenReturn(new String[0]);
+        when(filter1Reference.getProperty(HttpWhiteboardConstants.PATTERN)).thenReturn(SERVLET_1_ALIAS);
+
+        when(filter1_1Reference.getBundle()).thenReturn(bundle1);
+        when(filter1_1Reference.getPropertyKeys()).thenReturn(new String[0]);
+        when(filter1_1Reference.getProperty(HttpWhiteboardConstants.PATTERN)).thenReturn(SERVLET_1_1_ALIAS);
+
+        when(filter2Reference.getBundle()).thenReturn(bundle2);
+        when(filter2Reference.getPropertyKeys()).thenReturn(new String[0]);
+        when(filter2Reference.getProperty(HttpWhiteboardConstants.PATTERN)).thenReturn(SERVLET_2_ALIAS);
+        when(filter2Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+
+        this.httpService = new MockExtHttpService();
+    }
+
+    @After
+    public void tearDown()
+    {
+        this.httpService = null;
+    }
+
+    @Test
+    public void test_no_servlets_no_filters()
+    {
+        ExtenderManager em = new ExtenderManager();
+
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        em.setHttpService(null);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertTrue(em.getMappings().isEmpty());
+    }
+
+    @Test
+    public void test_servlet_per_bundle()
+    {
+        ExtenderManager em = new ExtenderManager();
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // setup a context without context ID
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        em.remove(sampleContext);
+
+        // set up a context with context ID and not shared
+        final String id = HttpContextManagerTest.createId(bundle1, SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // register servlet1 from bundle1
+        when(servlet1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(servlet1, servlet1Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, servlet1.getHttpContext());
+
+        // register servlet2 from bundle2
+        em.add(servlet2, servlet2Reference);
+
+        TestCase.assertEquals(2, em.getMappings().size());
+        TestCase.assertSame(servlet2, ((ServletMapping) em.getMappings().get(servlet2Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertNull(this.httpService.getServlets().get(SERVLET_2_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(servlet2Reference)));
+
+        // unregister servlet2
+        em.remove(servlet2Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister servlet1
+        em.remove(servlet1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().get(id).getMappings().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_servlet_shared()
+    {
+        ExtenderManager em = new ExtenderManager();
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // set up a context with context ID and shared
+        final String id = HttpContextManagerTest.createId(SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_SHARED)).thenReturn("true");
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // register servlet1 from bundle1
+        when(servlet1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(servlet1, servlet1Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, servlet1.getHttpContext());
+
+        // register servlet2 from bundle2
+        em.add(servlet2, servlet2Reference);
+
+        TestCase.assertEquals(2, em.getMappings().size());
+        TestCase.assertSame(servlet2, ((ServletMapping) em.getMappings().get(servlet2Reference)).getServlet());
+        TestCase.assertEquals(2, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(2, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet2, this.httpService.getServlets().get(SERVLET_2_ALIAS));
+        TestCase.assertEquals(0, em.getOrphanMappings().size());
+        TestCase.assertSame(sampleContext, servlet2.getHttpContext());
+
+        // unregister servlet2
+        em.remove(servlet2Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister servlet1
+        em.remove(servlet1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().get(id).getMappings().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_servlet_no_context_id()
+    {
+        ExtenderManager em = new ExtenderManager();
+        final String id1 = HttpContextManagerTest.createId(bundle1, null);
+        final String id2 = HttpContextManagerTest.createId(bundle2, null);
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+
+        // register servlet1 from bundle1
+        em.add(servlet1, servlet1Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id1).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(DefaultHttpContext.class, servlet1.getHttpContext().getClass());
+
+        // register servlet2 from bundle2
+        when(servlet2Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn("");
+        em.add(servlet2, servlet2Reference);
+
+        TestCase.assertEquals(2, em.getMappings().size());
+        TestCase.assertSame(servlet2, ((ServletMapping) em.getMappings().get(servlet2Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id2).getMappings().size());
+        TestCase.assertEquals(2, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet2, this.httpService.getServlets().get(SERVLET_2_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(DefaultHttpContext.class, servlet2.getHttpContext().getClass());
+
+        // different HttpContext instances per servlet/per bundle
+        TestCase.assertNotSame(servlet1.getHttpContext(), servlet2.getHttpContext());
+
+        // register servlet 1_1 from bundle 1
+        em.add(servlet1_1, servlet1_1Reference);
+
+        TestCase.assertEquals(3, em.getMappings().size());
+        TestCase.assertSame(servlet1_1, ((ServletMapping) em.getMappings().get(servlet1_1Reference)).getServlet());
+        TestCase.assertEquals(2, em.getHttpContexts().get(id1).getMappings().size());
+        TestCase.assertEquals(3, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1_1, this.httpService.getServlets().get(SERVLET_1_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(DefaultHttpContext.class, servlet1_1.getHttpContext().getClass());
+
+        // same HttpContext instances per servlet in same bundle
+        TestCase.assertSame(servlet1.getHttpContext(), servlet1_1.getHttpContext());
+    }
+
+    @Test
+    public void test_servlet_before_context_per_bundle()
+    {
+        ExtenderManager em = new ExtenderManager();
+        final String id = HttpContextManagerTest.createId(bundle1, SAMPLE_CONTEXT_ID);
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // register servlet1 from bundle1
+        when(servlet1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(servlet1, servlet1Reference);
+
+        // servlet not registered with HttpService yet
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertNull(this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(servlet1Reference)));
+
+        // set up a context with context ID and not shared
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // servlet registered with HttpService
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, servlet1.getHttpContext());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertNull(this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(servlet1Reference)));
+
+        // unregister servlet1
+        em.remove(servlet1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_servlet_before_context_shared()
+    {
+        ExtenderManager em = new ExtenderManager();
+        final String id = HttpContextManagerTest.createId(SAMPLE_CONTEXT_ID);
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // register servlet1 from bundle1
+        when(servlet1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(servlet1, servlet1Reference);
+
+        // servlet not registered with HttpService yet
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertNull(this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(servlet1Reference)));
+
+        // set up a context with context ID and not shared
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_SHARED)).thenReturn(true);
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // servlet registered with HttpService
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet1, this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, servlet1.getHttpContext());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(servlet1, ((ServletMapping) em.getMappings().get(servlet1Reference)).getServlet());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertNull(this.httpService.getServlets().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(servlet1Reference)));
+
+        // unregister servlet1
+        em.remove(servlet1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_filter_per_bundle()
+    {
+        ExtenderManager em = new ExtenderManager();
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // setup a context without context ID
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        em.remove(sampleContext);
+
+        // set up a context with context ID and not shared
+        final String id = HttpContextManagerTest.createId(bundle1, SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // register filter1 from bundle1
+        when(filter1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(filter1, filter1Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, filter1.getHttpContext());
+
+        // register filter2 from bundle2
+        em.add(filter2, filter2Reference);
+
+        TestCase.assertEquals(2, em.getMappings().size());
+        TestCase.assertSame(filter2, ((FilterMapping) em.getMappings().get(filter2Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertNull(this.httpService.getFilters().get(SERVLET_2_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(filter2Reference)));
+
+        // unregister filter2
+        em.remove(filter2Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister filter1
+        em.remove(filter1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().get(id).getMappings().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_filter_shared()
+    {
+        ExtenderManager em = new ExtenderManager();
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // set up a context with context ID and shared
+        final String id = HttpContextManagerTest.createId(SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_SHARED)).thenReturn("true");
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // register filter1 from bundle1
+        when(filter1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(filter1, filter1Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, filter1.getHttpContext());
+
+        // register filter2 from bundle2
+        em.add(filter2, filter2Reference);
+
+        TestCase.assertEquals(2, em.getMappings().size());
+        TestCase.assertSame(filter2, ((FilterMapping) em.getMappings().get(filter2Reference)).getFilter());
+        TestCase.assertEquals(2, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(2, this.httpService.getFilters().size());
+        TestCase.assertSame(filter2, this.httpService.getFilters().get(SERVLET_2_ALIAS));
+        TestCase.assertEquals(0, em.getOrphanMappings().size());
+        TestCase.assertSame(sampleContext, filter2.getHttpContext());
+
+        // unregister filter2
+        em.remove(filter2Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister filter1
+        em.remove(filter1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().get(id).getMappings().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_filter_no_context_id()
+    {
+        ExtenderManager em = new ExtenderManager();
+        final String id1 = HttpContextManagerTest.createId(bundle1, null);
+        final String id2 = HttpContextManagerTest.createId(bundle2, null);
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+
+        // register filter1 from bundle1
+        em.add(filter1, filter1Reference);
+
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id1).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(DefaultHttpContext.class, filter1.getHttpContext().getClass());
+
+        // register filter2 from bundle2
+        when(filter2Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn("");
+        em.add(filter2, filter2Reference);
+
+        TestCase.assertEquals(2, em.getMappings().size());
+        TestCase.assertSame(filter2, ((FilterMapping) em.getMappings().get(filter2Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id2).getMappings().size());
+        TestCase.assertEquals(2, this.httpService.getFilters().size());
+        TestCase.assertSame(filter2, this.httpService.getFilters().get(SERVLET_2_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(DefaultHttpContext.class, filter2.getHttpContext().getClass());
+
+        // different HttpContext instances per servlet/per bundle
+        TestCase.assertNotSame(filter1.getHttpContext(), filter2.getHttpContext());
+
+        // register servlet 1_1 from bundle 1
+        em.add(filter1_1, filter1_1Reference);
+
+        TestCase.assertEquals(3, em.getMappings().size());
+        TestCase.assertSame(filter1_1, ((FilterMapping) em.getMappings().get(filter1_1Reference)).getFilter());
+        TestCase.assertEquals(2, em.getHttpContexts().get(id1).getMappings().size());
+        TestCase.assertEquals(3, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1_1, this.httpService.getFilters().get(SERVLET_1_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(DefaultHttpContext.class, filter1_1.getHttpContext().getClass());
+
+        // same HttpContext instances per servlet in same bundle
+        TestCase.assertSame(filter1.getHttpContext(), filter1_1.getHttpContext());
+    }
+
+    @Test
+    public void test_filter_before_context_per_bundle()
+    {
+        ExtenderManager em = new ExtenderManager();
+        final String id = HttpContextManagerTest.createId(bundle1, SAMPLE_CONTEXT_ID);
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // register filter1 from bundle1
+        when(filter1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(filter1, filter1Reference);
+
+        // servlet not registered with HttpService yet
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertNull(this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(filter1Reference)));
+
+        // set up a context with context ID and not shared
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // servlet registered with HttpService
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, filter1.getHttpContext());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertNull(this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(filter1Reference)));
+
+        // unregister filter1
+        em.remove(filter1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_filter_before_context_shared()
+    {
+        ExtenderManager em = new ExtenderManager();
+        final String id = HttpContextManagerTest.createId(SAMPLE_CONTEXT_ID);
+
+        // prepare with http service
+        em.setHttpService(this.httpService);
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        // register filter1 from bundle1
+        when(filter1Reference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        em.add(filter1, filter1Reference);
+
+        // servlet not registered with HttpService yet
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertNull(this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(filter1Reference)));
+
+        // set up a context with context ID and not shared
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_ID)).thenReturn(SAMPLE_CONTEXT_ID);
+        when(httpContextReference.getProperty(HttpWhiteboardConstants.CONTEXT_SHARED)).thenReturn(true);
+        em.add(sampleContext, httpContextReference);
+        TestCase.assertEquals(1, em.getHttpContexts().size());
+
+        // servlet registered with HttpService
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(1, em.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter1, this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+        TestCase.assertSame(sampleContext, filter1.getHttpContext());
+
+        // unregister context
+        em.remove(sampleContext);
+        TestCase.assertEquals(1, em.getMappings().size());
+        TestCase.assertSame(filter1, ((FilterMapping) em.getMappings().get(filter1Reference)).getFilter());
+        TestCase.assertEquals(0, em.getHttpContexts().size());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertNull(this.httpService.getFilters().get(SERVLET_1_ALIAS));
+        TestCase.assertEquals(1, em.getOrphanMappings().size());
+        TestCase.assertEquals(1, em.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(em.getOrphanMappings().get(SAMPLE_CONTEXT_ID)
+            .contains(em.getMappings().get(filter1Reference)));
+
+        // unregister filter1
+        em.remove(filter1Reference);
+        TestCase.assertTrue(em.getMappings().isEmpty());
+        TestCase.assertTrue(em.getHttpContexts().isEmpty());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+        TestCase.assertTrue(em.getOrphanMappings().isEmpty());
+    }
+
+    static interface ExtFilter extends Filter
+    {
+        HttpContext getHttpContext();
+    }
+
+    static interface ExtServlet extends Servlet
+    {
+        HttpContext getHttpContext();
+    }
+
+    static final class MockExtHttpService implements ExtHttpService
+    {
+
+        private final BidiMap /* <String, Servlet> */servlets = new DualHashBidiMap();
+        private final BidiMap /* <String, Filter> */filters = new DualHashBidiMap();
+
+        /**
+         * @return BidiMap<String, Servlet>
+         */
+        public BidiMap getServlets()
+        {
+            return servlets;
+        }
+
+        /**
+         * @return BidiMap<String, Filter>
+         */
+        public BidiMap getFilters()
+        {
+            return filters;
+        }
+
+        public void registerServlet(String alias, Servlet servlet, @SuppressWarnings("rawtypes") Dictionary initparams,
+            HttpContext context)
+
+        {
+            // always expect a non-null HttpContext here !!
+            TestCase.assertNotNull(context);
+
+            this.servlets.put(alias, servlet);
+
+            // make HttpContext available
+            when(((ExtServlet) servlet).getHttpContext()).thenReturn(context);
+        }
+
+        public void registerResources(String alias, String name, HttpContext context)
+        {
+            // not used here
+        }
+
+        public void unregister(String alias)
+        {
+            Object servlet = this.servlets.remove(alias);
+            if (servlet instanceof ExtServlet)
+            {
+                when(((ExtServlet) servlet).getHttpContext()).thenReturn(null);
+            }
+        }
+
+        public HttpContext createDefaultHttpContext()
+        {
+            // not used here
+            return null;
+        }
+
+        public void registerFilter(Filter filter, String pattern, @SuppressWarnings("rawtypes") Dictionary initParams,
+            int ranking, HttpContext context)
+        {
+            // always expect a non-null HttpContext here !!
+            TestCase.assertNotNull(context);
+
+            this.filters.put(pattern, filter);
+
+            // make HttpContext available
+            when(((ExtFilter) filter).getHttpContext()).thenReturn(context);
+        }
+
+        public void unregisterFilter(Filter filter)
+        {
+            this.filters.removeValue(filter);
+            when(((ExtFilter) filter).getHttpContext()).thenReturn(null);
+        }
+
+        public void unregisterServlet(Servlet servlet)
+        {
+            this.servlets.removeValue(servlet);
+            when(((ExtServlet) servlet).getHttpContext()).thenReturn(null);
+        }
+    }
+}
\ No newline at end of file

Added: felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/FilterMappingTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/FilterMappingTest.java?rev=1210612&view=auto
==============================================================================
--- felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/FilterMappingTest.java (added)
+++ felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/FilterMappingTest.java Mon Dec  5 20:29:08 2011
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.http.whiteboard.internal.manager;
+
+import static org.mockito.Mockito.when;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FilterMappingTest
+{
+
+    private static final String SAMPLE_CONTEXT_ID = "some.context.id";
+
+    private static final long BUNDLE_ID = 1L;
+
+    private static final String FILTER_PATTERN = "/sample/*";
+
+    private static final int FILTER_RANKING = 1234;
+
+    @Mock
+    private HttpContext sampleContext;
+
+    @Mock
+    private Bundle bundle;
+
+    @Mock
+    private ExtenderManagerTest.ExtFilter filter;
+
+    private ExtenderManagerTest.MockExtHttpService httpService;
+
+    @Before
+    public void setup()
+    {
+        when(bundle.getBundleId()).thenReturn(BUNDLE_ID);
+
+        this.httpService = new ExtenderManagerTest.MockExtHttpService();
+    }
+
+    @After
+    public void tearDown()
+    {
+        this.httpService = null;
+    }
+
+    @Test
+    public void test_with_context()
+    {
+        FilterMapping fm = new FilterMapping(bundle, filter, FILTER_PATTERN, FILTER_RANKING);
+        TestCase.assertSame(bundle, fm.getBundle());
+        TestCase.assertSame(filter, fm.getFilter());
+        TestCase.assertEquals(FILTER_PATTERN, fm.getPattern());
+        TestCase.assertEquals(FILTER_RANKING, fm.getRanking());
+
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertNotNull(fm.getInitParams());
+        TestCase.assertTrue(fm.getInitParams().isEmpty());
+        TestCase.assertFalse(fm.isRegistered());
+
+        fm.setContext(sampleContext);
+        TestCase.assertSame(sampleContext, fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        fm.register(this.httpService);
+        TestCase.assertSame(sampleContext, fm.getContext());
+        TestCase.assertTrue(fm.isRegistered());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter, this.httpService.getFilters().get(FILTER_PATTERN));
+        TestCase.assertSame(sampleContext, filter.getHttpContext());
+
+        fm.unregister(this.httpService);
+        TestCase.assertSame(sampleContext, fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+
+        fm.setContext(null);
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+    }
+
+    @Test
+    public void test_context_delayed()
+    {
+        FilterMapping fm = new FilterMapping(bundle, filter, FILTER_PATTERN, FILTER_RANKING);
+        TestCase.assertSame(bundle, fm.getBundle());
+        TestCase.assertSame(filter, fm.getFilter());
+        TestCase.assertEquals(FILTER_PATTERN, fm.getPattern());
+        TestCase.assertEquals(FILTER_RANKING, fm.getRanking());
+
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertNotNull(fm.getInitParams());
+        TestCase.assertTrue(fm.getInitParams().isEmpty());
+        TestCase.assertFalse(fm.isRegistered());
+
+        fm.register(this.httpService);
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        fm.unregister(httpService);
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        fm.setContext(sampleContext);
+        TestCase.assertSame(sampleContext, fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+    }
+
+    @Test
+    public void test_unset_context()
+    {
+        FilterMapping fm = new FilterMapping(bundle, filter, FILTER_PATTERN, FILTER_RANKING);
+        TestCase.assertSame(bundle, fm.getBundle());
+        TestCase.assertSame(filter, fm.getFilter());
+        TestCase.assertEquals(FILTER_PATTERN, fm.getPattern());
+        TestCase.assertEquals(FILTER_RANKING, fm.getRanking());
+
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertNotNull(fm.getInitParams());
+        TestCase.assertTrue(fm.getInitParams().isEmpty());
+        TestCase.assertFalse(fm.isRegistered());
+
+        fm.setContext(sampleContext);
+        TestCase.assertSame(sampleContext, fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertTrue(this.httpService.getFilters().isEmpty());
+
+        fm.register(this.httpService);
+        TestCase.assertSame(sampleContext, fm.getContext());
+        TestCase.assertTrue(fm.isRegistered());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter, this.httpService.getFilters().get(FILTER_PATTERN));
+        TestCase.assertSame(sampleContext, filter.getHttpContext());
+
+        // does not unregister yet
+        fm.setContext(null);
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertTrue(fm.isRegistered());
+        TestCase.assertEquals(1, this.httpService.getFilters().size());
+        TestCase.assertSame(filter, this.httpService.getFilters().get(FILTER_PATTERN));
+        TestCase.assertSame(sampleContext, filter.getHttpContext());
+
+        fm.unregister(this.httpService);
+        TestCase.assertNull(fm.getContext());
+        TestCase.assertFalse(fm.isRegistered());
+        TestCase.assertEquals(0, this.httpService.getFilters().size());
+    }
+}

Added: felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManagerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManagerTest.java?rev=1210612&view=auto
==============================================================================
--- felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManagerTest.java (added)
+++ felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManagerTest.java Mon Dec  5 20:29:08 2011
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.http.whiteboard.internal.manager;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.http.whiteboard.internal.manager.HttpContextManager.HttpContextHolder;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class HttpContextManagerTest
+{
+
+    private static final String SAMPLE_CONTEXT_ID = "some.context.id";
+
+    private static final long BUNDLE_1_ID = 1L;
+
+    private static final String BUNDLE_1_ALIAS = "/bundle1";
+
+    private static final long BUNDLE_2_ID = 2L;
+
+    private static final String BUNDLE_2_ALIAS = "/bundle2";
+
+    @Mock
+    private HttpContext sampleContext;
+
+    @Mock
+    private Bundle bundle1;
+
+    @Mock
+    private Bundle bundle2;
+
+    @Before
+    public void setup()
+    {
+        when(bundle1.getBundleId()).thenReturn(BUNDLE_1_ID);
+        when(bundle2.getBundleId()).thenReturn(BUNDLE_2_ID);
+    }
+
+    @Test
+    public void test_HttpContextHolder()
+    {
+        TestCase.assertNotNull(sampleContext);
+
+        final HttpContextHolder h1 = new HttpContextHolder(sampleContext);
+        TestCase.assertSame(sampleContext, h1.getContext());
+        TestCase.assertTrue(h1.getMappings().isEmpty());
+
+        ServletMapping sm = new ServletMapping(bundle1, null, "");
+        h1.addMapping(sm);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertEquals(1, h1.getMappings().size());
+        TestCase.assertTrue(h1.getMappings().contains(sm));
+
+        h1.removeMapping(sm);
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertTrue(h1.getMappings().isEmpty());
+    }
+
+    @Test
+    public void test_add_remove_HttpContext_per_Bundle()
+    {
+        final HttpContextManager hcm = new HttpContextManager();
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+
+        Collection<AbstractMapping> mappings = hcm.addHttpContext(bundle1, SAMPLE_CONTEXT_ID, sampleContext);
+        TestCase.assertNotNull(mappings);
+        TestCase.assertTrue(mappings.isEmpty());
+
+        String holderId = createId(bundle1, SAMPLE_CONTEXT_ID);
+        Map<String, HttpContextHolder> holders = hcm.getHttpContexts();
+        TestCase.assertEquals(1, holders.size());
+        TestCase.assertSame(sampleContext, holders.get(holderId).getContext());
+        TestCase.assertEquals(mappings, holders.get(holderId).getMappings());
+
+        Collection<AbstractMapping> removedMappings = hcm.removeHttpContext(sampleContext);
+        TestCase.assertNotNull(removedMappings);
+        TestCase.assertTrue(removedMappings.isEmpty());
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+    }
+
+    @Test
+    public void test_add_remove_HttpContext_shared()
+    {
+        final HttpContextManager hcm = new HttpContextManager();
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+
+        Collection<AbstractMapping> mappings = hcm.addHttpContext(null, SAMPLE_CONTEXT_ID, sampleContext);
+        TestCase.assertNotNull(mappings);
+        TestCase.assertTrue(mappings.isEmpty());
+
+        String holderId = createId(SAMPLE_CONTEXT_ID);
+        Map<String, HttpContextHolder> holders = hcm.getHttpContexts();
+        TestCase.assertEquals(1, holders.size());
+        TestCase.assertSame(sampleContext, holders.get(holderId).getContext());
+        TestCase.assertEquals(mappings, holders.get(holderId).getMappings());
+
+        Collection<AbstractMapping> removedMappings = hcm.removeHttpContext(sampleContext);
+        TestCase.assertNotNull(removedMappings);
+        TestCase.assertTrue(removedMappings.isEmpty());
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+    }
+
+    @Test
+    public void test_get_unget_HttpContext_per_bundle_same_bundle()
+    {
+        final HttpContextManager hcm = new HttpContextManager();
+        final String id = createId(bundle1, SAMPLE_CONTEXT_ID);
+        hcm.addHttpContext(bundle1, SAMPLE_CONTEXT_ID, sampleContext);
+
+        // Servlet 1 gets the context
+        final ServletMapping bundle1Servlet = new ServletMapping(bundle1, null, BUNDLE_1_ALIAS);
+        HttpContext ctx1 = hcm.getHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        TestCase.assertNotNull(ctx1);
+        TestCase.assertSame(ctx1, bundle1Servlet.getContext());
+        TestCase.assertSame(sampleContext, ctx1);
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().contains(bundle1Servlet));
+        Map<String, Set<AbstractMapping>> orphans1 = hcm.getOrphanMappings();
+        TestCase.assertTrue(orphans1.isEmpty());
+
+        // unregister servlet again --> all references clear
+        hcm.ungetHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        TestCase.assertNull(bundle1Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().isEmpty());
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+
+        // register servlet, unregister context --> orphan
+        hcm.getHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        hcm.removeHttpContext(sampleContext);
+        TestCase.assertNull(bundle1Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+        TestCase.assertEquals(1, hcm.getOrphanMappings().size());
+        TestCase.assertEquals(1, hcm.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(hcm.getOrphanMappings().get(SAMPLE_CONTEXT_ID).contains(bundle1Servlet));
+
+        // cleanup
+        hcm.ungetHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        TestCase.assertNull(bundle1Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+    }
+
+    public void test_get_unget_HttpContext_per_bundle_other_bundle()
+    {
+        final HttpContextManager hcm = new HttpContextManager();
+
+        final String id1 = createId(bundle1, SAMPLE_CONTEXT_ID);
+        hcm.addHttpContext(bundle1, SAMPLE_CONTEXT_ID, sampleContext);
+
+        // Servlet 2 is an orphan
+        final ServletMapping bundle2Servlet = new ServletMapping(bundle2, null, BUNDLE_2_ALIAS);
+        HttpContext ctx2 = hcm.getHttpContext(bundle2, SAMPLE_CONTEXT_ID, bundle2Servlet);
+        TestCase.assertNull(ctx2);
+        TestCase.assertNull(bundle2Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id1).getMappings().isEmpty());
+        Map<String, Set<AbstractMapping>> orphans2 = hcm.getOrphanMappings();
+        TestCase.assertEquals(1, orphans2.size());
+        TestCase.assertEquals(1, orphans2.get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(orphans2.get(SAMPLE_CONTEXT_ID).contains(bundle2Servlet));
+
+        // unregister unused context for bundle1
+        hcm.removeHttpContext(sampleContext);
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+
+        // register context for bundle2
+        final String id2 = createId(bundle1, SAMPLE_CONTEXT_ID);
+        hcm.addHttpContext(bundle2, SAMPLE_CONTEXT_ID, sampleContext);
+        TestCase.assertEquals(1, hcm.getHttpContexts().size());
+        TestCase.assertSame(sampleContext, hcm.getHttpContexts().get(id2).getContext());
+
+        TestCase.assertSame(sampleContext, bundle2Servlet.getContext());
+        TestCase.assertEquals(1, hcm.getHttpContexts().get(id2).getMappings().size());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id2).getMappings().contains(bundle2Servlet));
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+
+        // cleanup
+        hcm.ungetHttpContext(bundle2, SAMPLE_CONTEXT_ID, bundle2Servlet);
+        TestCase.assertNull(bundle2Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id2).getMappings().isEmpty());
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_get_unget_HttpContext_shared()
+    {
+        final HttpContextManager hcm = new HttpContextManager();
+        final String id = createId(SAMPLE_CONTEXT_ID);
+        hcm.addHttpContext(null, SAMPLE_CONTEXT_ID, sampleContext);
+
+        // Servlet 1 gets the context
+        final ServletMapping bundle1Servlet = new ServletMapping(bundle1, null, BUNDLE_1_ALIAS);
+        HttpContext ctx1 = hcm.getHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        TestCase.assertNotNull(ctx1);
+        TestCase.assertSame(ctx1, bundle1Servlet.getContext());
+        TestCase.assertSame(sampleContext, ctx1);
+        TestCase.assertEquals(1, hcm.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().contains(bundle1Servlet));
+        Map<String, Set<AbstractMapping>> orphans1 = hcm.getOrphanMappings();
+        TestCase.assertTrue(orphans1.isEmpty());
+
+        // unregister serlvet 1 --> all references clear
+        hcm.ungetHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        TestCase.assertNull(bundle1Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().isEmpty());
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+
+        // Servlet 2 gets the context
+        final ServletMapping bundle2Servlet = new ServletMapping(bundle2, null, BUNDLE_2_ALIAS);
+        HttpContext ctx2 = hcm.getHttpContext(bundle2, SAMPLE_CONTEXT_ID, bundle2Servlet);
+        TestCase.assertNotNull(ctx2);
+        TestCase.assertSame(ctx2, bundle2Servlet.getContext());
+        TestCase.assertSame(sampleContext, ctx2);
+        TestCase.assertEquals(1, hcm.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().contains(bundle2Servlet));
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+
+        // register Servlet 1 again --> gets context
+        hcm.getHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        HttpContext ctx3 = hcm.getHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        TestCase.assertNotNull(ctx3);
+        TestCase.assertSame(ctx3, bundle1Servlet.getContext());
+        TestCase.assertSame(sampleContext, ctx3);
+        TestCase.assertEquals(2, hcm.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().contains(bundle1Servlet));
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+
+        // unregister context --> all references clear
+        hcm.removeHttpContext(sampleContext);
+        TestCase.assertNull(bundle1Servlet.getContext());
+        TestCase.assertNull(bundle2Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+        TestCase.assertEquals(1, hcm.getOrphanMappings().size());
+        TestCase.assertEquals(2, hcm.getOrphanMappings().get(SAMPLE_CONTEXT_ID).size());
+        TestCase.assertTrue(hcm.getOrphanMappings().get(SAMPLE_CONTEXT_ID).contains(bundle1Servlet));
+        TestCase.assertTrue(hcm.getOrphanMappings().get(SAMPLE_CONTEXT_ID).contains(bundle2Servlet));
+
+        // register context --> servlets 1, 2 get context
+        hcm.addHttpContext(null, SAMPLE_CONTEXT_ID, sampleContext);
+        TestCase.assertSame(sampleContext, bundle1Servlet.getContext());
+        TestCase.assertSame(sampleContext, bundle2Servlet.getContext());
+        TestCase.assertEquals(2, hcm.getHttpContexts().get(id).getMappings().size());
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().contains(bundle1Servlet));
+        TestCase.assertTrue(hcm.getHttpContexts().get(id).getMappings().contains(bundle2Servlet));
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+
+        // cleanup
+        hcm.removeHttpContext(sampleContext);
+        hcm.ungetHttpContext(bundle1, SAMPLE_CONTEXT_ID, bundle1Servlet);
+        hcm.ungetHttpContext(bundle2, SAMPLE_CONTEXT_ID, bundle2Servlet);
+        TestCase.assertNull(bundle1Servlet.getContext());
+        TestCase.assertNull(bundle2Servlet.getContext());
+        TestCase.assertTrue(hcm.getHttpContexts().isEmpty());
+        TestCase.assertTrue(hcm.getOrphanMappings().isEmpty());
+    }
+
+    @Test
+    public void test_createId_Bundle_String()
+    {
+        TestCase.assertEquals(BUNDLE_1_ID + "-", createId(bundle1, null));
+        TestCase.assertEquals(BUNDLE_1_ID + "-", createId(bundle1, ""));
+        TestCase.assertEquals(BUNDLE_1_ID + "-" + SAMPLE_CONTEXT_ID, createId(bundle1, SAMPLE_CONTEXT_ID));
+    }
+
+    @Test
+    public void test_createId_String()
+    {
+        TestCase.assertEquals("shared-", createId(null));
+        TestCase.assertEquals("shared-", createId(""));
+        TestCase.assertEquals("shared-" + SAMPLE_CONTEXT_ID, createId(SAMPLE_CONTEXT_ID));
+    }
+
+    static String createId(String contextId)
+    {
+        try
+        {
+            Method m = HttpContextManager.class.getDeclaredMethod("createId", String.class);
+            m.setAccessible(true);
+            return (String) m.invoke(null, contextId);
+        }
+        catch (Throwable t)
+        {
+            TestCase.fail(t.toString());
+            return null; // compiler satisfaction
+        }
+    }
+
+    static String createId(Bundle bundle, String contextId)
+    {
+        try
+        {
+            Method m = HttpContextManager.class.getDeclaredMethod("createId", Bundle.class, String.class);
+            m.setAccessible(true);
+            return (String) m.invoke(null, bundle, contextId);
+        }
+        catch (Throwable t)
+        {
+            TestCase.fail(t.toString());
+            return null; // compiler satisfaction
+        }
+    }
+}

Added: felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ServletMappingTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ServletMappingTest.java?rev=1210612&view=auto
==============================================================================
--- felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ServletMappingTest.java (added)
+++ felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ServletMappingTest.java Mon Dec  5 20:29:08 2011
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.http.whiteboard.internal.manager;
+
+import static org.mockito.Mockito.when;
+
+import junit.framework.TestCase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ServletMappingTest
+{
+
+    private static final String SAMPLE_CONTEXT_ID = "some.context.id";
+
+    private static final long BUNDLE_ID = 1L;
+
+    private static final String SERVLET_ALIAS = "/bundle";
+
+    @Mock
+    private HttpContext sampleContext;
+
+    @Mock
+    private Bundle bundle;
+
+    @Mock
+    private ExtenderManagerTest.ExtServlet servlet;
+
+    private ExtenderManagerTest.MockExtHttpService httpService;
+
+    @Before
+    public void setup()
+    {
+        when(bundle.getBundleId()).thenReturn(BUNDLE_ID);
+
+        this.httpService = new ExtenderManagerTest.MockExtHttpService();
+    }
+
+    @After
+    public void tearDown()
+    {
+        this.httpService = null;
+    }
+
+    @Test
+    public void test_with_context()
+    {
+        ServletMapping sm = new ServletMapping(bundle, servlet, SERVLET_ALIAS);
+        TestCase.assertSame(bundle, sm.getBundle());
+        TestCase.assertSame(servlet, sm.getServlet());
+        TestCase.assertEquals(SERVLET_ALIAS, sm.getAlias());
+
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertNotNull(sm.getInitParams());
+        TestCase.assertTrue(sm.getInitParams().isEmpty());
+        TestCase.assertFalse(sm.isRegistered());
+
+        sm.setContext(sampleContext);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+
+        sm.register(this.httpService);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertTrue(sm.isRegistered());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet, this.httpService.getServlets().get(SERVLET_ALIAS));
+        TestCase.assertSame(sampleContext, servlet.getHttpContext());
+
+        sm.unregister(this.httpService);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+
+        sm.setContext(null);
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+    }
+
+    @Test
+    public void test_context_delayed()
+    {
+        ServletMapping sm = new ServletMapping(bundle, servlet, SERVLET_ALIAS);
+        TestCase.assertSame(bundle, sm.getBundle());
+        TestCase.assertSame(servlet, sm.getServlet());
+        TestCase.assertEquals(SERVLET_ALIAS, sm.getAlias());
+
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertNotNull(sm.getInitParams());
+        TestCase.assertTrue(sm.getInitParams().isEmpty());
+        TestCase.assertFalse(sm.isRegistered());
+
+        sm.register(this.httpService);
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+
+        sm.unregister(httpService);
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+
+        sm.setContext(sampleContext);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+    }
+
+    @Test
+    public void test_unset_context()
+    {
+        ServletMapping sm = new ServletMapping(bundle, servlet, SERVLET_ALIAS);
+        TestCase.assertSame(bundle, sm.getBundle());
+        TestCase.assertSame(servlet, sm.getServlet());
+        TestCase.assertEquals(SERVLET_ALIAS, sm.getAlias());
+
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertNotNull(sm.getInitParams());
+        TestCase.assertTrue(sm.getInitParams().isEmpty());
+        TestCase.assertFalse(sm.isRegistered());
+
+        sm.setContext(sampleContext);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertTrue(this.httpService.getServlets().isEmpty());
+
+        sm.register(this.httpService);
+        TestCase.assertSame(sampleContext, sm.getContext());
+        TestCase.assertTrue(sm.isRegistered());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet, this.httpService.getServlets().get(SERVLET_ALIAS));
+        TestCase.assertSame(sampleContext, servlet.getHttpContext());
+
+        // does not unregister yet
+        sm.setContext(null);
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertTrue(sm.isRegistered());
+        TestCase.assertEquals(1, this.httpService.getServlets().size());
+        TestCase.assertSame(servlet, this.httpService.getServlets().get(SERVLET_ALIAS));
+        TestCase.assertSame(sampleContext, servlet.getHttpContext());
+
+        sm.unregister(this.httpService);
+        TestCase.assertNull(sm.getContext());
+        TestCase.assertFalse(sm.isRegistered());
+        TestCase.assertEquals(0, this.httpService.getServlets().size());
+    }
+}