You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2014/02/14 15:09:41 UTC

svn commit: r1568312 - in /wookie/trunk/wookie-services/wookie-redis/src: main/java/org/apache/wookie/services/redis/RedisSharedContextService.java test/java/org/apache/wookie/services/redis/RedisSharedContextServiceTest.java

Author: scottbw
Date: Fri Feb 14 14:09:41 2014
New Revision: 1568312

URL: http://svn.apache.org/r1568312
Log:
Added test cases for Redis shared data service, and updated implementation to fix a few errors, notably failing to release the jedis resource on a couple of logic branches, and catching all nulls and empty strings.

Added:
    wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisSharedContextServiceTest.java
Modified:
    wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java

Modified: wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java
URL: http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java?rev=1568312&r1=1568311&r2=1568312&view=diff
==============================================================================
--- wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java (original)
+++ wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java Fri Feb 14 14:09:41 2014
@@ -124,11 +124,18 @@ public class RedisSharedContextService i
 	@Override
 	public boolean removeSharedData(String apiKey, String widgetId,
 			String contextId, String name) {
+
+		//
+		// If there is no key, return false
+		//
+		if (name == null) return false;
+		if (name.trim().length() == 0) return false;
+
 		//
 		// Get a Jedis from the pool
 		//
 		Jedis jedis = pool.getResource();
-		
+
 		//
 		// get the Redis key for the participant
 		//
@@ -137,26 +144,27 @@ public class RedisSharedContextService i
 		//
 		// if it doesn't exist, return false
 		//
-		if ( this.getSharedData(apiKey, widgetId, contextId, name) == null){
+		if ( !jedis.exists(key)){
+			pool.returnResource(jedis);
 			return false;
 		}
-				
+
 		//
 		// Delete the object
 		//
 		jedis.del(key);
-		
+
 		//
 		// Remove the key from the context list
 		//
 		String context = this.getContextKey(apiKey, widgetId, contextId);
 		jedis.lrem(context, 0, key);
-		
+
 		//
 		// Release Jedis back to the pool
 		//
 		pool.returnResource(jedis);
-		
+
 		//
 		// OK
 		//
@@ -171,6 +179,14 @@ public class RedisSharedContextService i
 		if (data == null) return false;
 		
 		//
+		// If the value is null, and we're not set to append, this is 
+		// actually the same as "remove"
+		//
+		if (data.getDvalue() == null){
+			return this.removeSharedData(apiKey, widgetId, contextId, data.getDkey());
+		}
+		
+		//
 		// Get a Jedis from the pool
 		//
 		Jedis jedis = pool.getResource();
@@ -185,6 +201,7 @@ public class RedisSharedContextService i
 		// If there is no existing tuple, add the key to the list of keys for this token
 		//
 		ISharedData existing = getSharedData(apiKey, widgetId, contextId, data.getDkey());
+		
 		if (existing == null){
 			jedis.lpush(context, key);			
 		} else {
@@ -192,7 +209,7 @@ public class RedisSharedContextService i
 			// if it already exists, and the instruction is to append, prepend the 
 			// existing value to the new value to set
 			//
-			if (append && existing.getDvalue() != null && data.getDvalue() != null){
+			if (append){
 				data.setDvalue(existing.getDvalue() + data.getDvalue());
 			}
 		}
@@ -295,10 +312,13 @@ public class RedisSharedContextService i
 
 	private boolean addParticipant(String apiKey, String widgetId,
 			String contextId, IParticipant participant) {
+		
 		//
-		// Check if there is an object to add
+		// A participant must have an id at least
 		//
-		if (participant == null) return false;
+		if (participant.getParticipantId() == null || participant.getParticipantId().trim().length() == 0){
+			return false;
+		}
 		
 		//
 		// Get a Jedis from the pool
@@ -341,7 +361,7 @@ public class RedisSharedContextService i
 	@Override
 	public void removeParticipant(String apiKey, String widgetId,
 			String contextId, IParticipant participant) {
-		removeParticipant(apiKey, widgetId, contextId, participant.getParticipantId());
+		if (participant != null) removeParticipant(apiKey, widgetId, contextId, participant.getParticipantId());
 	}
 
 	@Override
@@ -349,6 +369,12 @@ public class RedisSharedContextService i
 			String contextId, String participantId) {
 		
 		//
+		// Check participant id is valid
+		//
+		if (participantId == null) return false;
+		if (participantId.trim().length() == 0) return false;
+		
+		//
 		// Get a Jedis from the pool
 		//
 		Jedis jedis = pool.getResource();
@@ -357,11 +383,12 @@ public class RedisSharedContextService i
 		// get the Redis key for the participant
 		//
 		String key = this.getParticipantKey(apiKey, widgetId, contextId, participantId);
-		
+				
 		//
 		// if it doesn't exist, return false
 		//
-		if ( this.getParticipant(apiKey, widgetId, contextId, participantId) == null){
+		if (!jedis.exists(key)){
+			pool.returnResource(jedis);
 			return false;
 		}
 				
@@ -426,7 +453,7 @@ public class RedisSharedContextService i
 	@Override
 	public IParticipant getHost(String apiKey, String widgetId, String contextId) {
 		IParticipant[] hosts = getHosts(apiKey, widgetId, contextId);
-		if (hosts == null || hosts.length == 0) return null;
+		if (hosts.length == 0) return null;
 		return hosts[0];
 	}
 
@@ -443,7 +470,7 @@ public class RedisSharedContextService i
 		// Iterate over participants and add them if they have a host role
 		//
 		for (IParticipant participant: this.getParticipants(apiKey, widgetId, contextId)){
-			if (participant.getRole().equals(IParticipant.HOST_ROLE)){
+			if (participant.getRole() != null && participant.getRole().equals(IParticipant.HOST_ROLE)){
 				hosts.add(participant);
 			}
 		}
@@ -483,18 +510,25 @@ public class RedisSharedContextService i
 		json.put("role", participant.getRole());
 		return json.toString();
 	}
-	
+
 	private ISharedData rehydrateData(String input){
 		if (input == null) return null;
+		DefaultSharedDataImpl data;
 		JSONObject json = new JSONObject(input);
-		DefaultSharedDataImpl data = new DefaultSharedDataImpl(json.getString("name"), json.getString("value"));
+		String value = json.getString("value");
+		String name = json.getString("name");
+		data = new DefaultSharedDataImpl(name,value);
 		return data;
 	}
-	
+
 	private IParticipant rehydrateParticipant(String input){
 		if (input == null) return null;
 		JSONObject json = new JSONObject(input);
-		DefaultParticipantImpl participant = new DefaultParticipantImpl(json.getString("id"), json.getString("name"), json.getString("thumbnail"), json.getString("role"));
+		String id = json.getString("id");
+		String name = json.has("name") ? json.getString("name"): null;
+		String thumbnail = json.has("thumbnail") ? json.getString("thumbnail"): null;
+		String role =  json.has("role") ? json.getString("role") : null;
+		DefaultParticipantImpl participant = new DefaultParticipantImpl(id, name, thumbnail, role);
 		return participant;
 	}
 }

Added: wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisSharedContextServiceTest.java
URL: http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisSharedContextServiceTest.java?rev=1568312&view=auto
==============================================================================
--- wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisSharedContextServiceTest.java (added)
+++ wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisSharedContextServiceTest.java Fri Feb 14 14:09:41 2014
@@ -0,0 +1,349 @@
+package org.apache.wookie.services.redis;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.wookie.beans.IParticipant;
+import org.apache.wookie.beans.ISharedData;
+import org.apache.wookie.services.impl.DefaultParticipantImpl;
+import org.apache.wookie.services.impl.DefaultSharedDataImpl;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import redis.clients.jedis.Jedis;
+import uk.co.datumedge.redislauncher.LocalRedisServer;
+import uk.co.datumedge.redislauncher.RedisServer;
+
+public class RedisSharedContextServiceTest {
+	
+	private static RedisServer redisServer;
+	private static RedisSharedContextService svc;
+	
+	private static final String API_KEY = "testapikey";
+	private static final String CONTEXT_ID = "23";
+	private static final String WIDGET_ID = "http://test.widget/";
+	
+	@BeforeClass
+	public static void setup() throws IOException, InterruptedException{
+		//
+		// Set the path to the Redis executable so we can start a test instance
+		//
+		Properties props = System.getProperties();
+		props.setProperty("redislauncher.command", "/usr/local/bin/redis-server");
+		redisServer = LocalRedisServer.newInstance();
+		redisServer.start();
+
+		svc = new RedisSharedContextService();
+		Jedis jedis = new Jedis("localhost");
+		jedis.flushDB();
+	}
+	
+	@AfterClass
+	public static void tearDown() throws IOException, InterruptedException{
+		svc = null;
+		redisServer.stop();
+	}
+
+	@After
+	public void cleanUp(){
+		svc.removeSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name");
+		assertNull(svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name"));
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertNull(svc.getParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice"));
+	}
+	
+	@Test
+	public void setAndGet(){
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name", "test-value", false);
+		ISharedData data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name");
+		assertEquals("test-value", data.getDvalue());
+	}
+	
+	@Test
+	public void setAndGetObject(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID,input, false);
+		
+		ISharedData data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name");
+		assertEquals("test-value", data.getDvalue());
+	}
+	
+	@Test
+	public void setAppendAndGetObject(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, input, false);
+		ISharedData data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name");
+		assertEquals("test-value", data.getDvalue());
+		
+		//
+		// Append
+		//
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name", "-append", true);
+		ISharedData out = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name");
+		assertEquals("test-value-append", out.getDvalue());
+	}
+	
+	@Test
+	public void setAndGetObjectFromArray(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID,input, false);
+		
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals("test-value", data[0].getDvalue());
+	}
+	
+	@Test
+	public void removeNonexistant(){
+		boolean out = svc.removeSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "rubbish");
+		assertFalse(out);
+	}
+	
+	@Test
+	public void removeEmptyString(){
+		boolean out = svc.removeSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "");
+		assertFalse(out);
+	}
+	
+	@Test
+	public void setNull(){
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, null, false);
+		assertFalse(out);
+		
+	}
+	
+	@Test
+	public void appendNullToNull(){
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, null, true);
+		assertFalse(out);
+	}
+	
+	
+	@Test
+	public void appendDataToNull(){
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name", "append", true);
+		assertTrue(out);
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals("append", data[0].getDvalue());
+	}
+	
+	@Test
+	public void appendWithNull(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID,input, false);
+		
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, null, true);
+		assertFalse(out);
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals("test-value", data[0].getDvalue());
+	}
+	
+	@Test
+	public void appendWithNullValue(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID,input, false);
+		
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name", null, true);
+		assertTrue(out);
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(0, data.length);
+	}
+	
+	@Test
+	public void append(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID,input, false);
+		
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name", "-append", true);
+		assertTrue(out);
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals("test-value-append", data[0].getDvalue());
+	}
+	
+	@Test
+	public void overwrite(){
+		ISharedData input = new DefaultSharedDataImpl("test-name", "test-value");
+		svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID,input, false);
+		
+		boolean out = svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-name", "new-value", false);
+		assertTrue(out);
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals("new-value", data[0].getDvalue());
+		
+
+	}
+	
+	@Test
+	public void removeNull(){
+		assertFalse(svc.removeSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, null));
+	}
+	
+	@Test
+	public void addGetParticipant(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url"));
+		IParticipant participant = svc.getParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("Alice", participant.getParticipantDisplayName());
+		assertEquals("http://some.url", participant.getParticipantThumbnailUrl());
+	}
+	
+	@Test
+	public void addGetParticipants(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url"));
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob", "Bob", "http://some.url"));
+
+		IParticipant[] participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(2, participants.length);
+		
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob");
+		participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, participants.length);
+	}
+	
+	@Test
+	public void addGetHosts(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url", IParticipant.HOST_ROLE));
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob", "Bob", "http://some.url"));
+
+		IParticipant[] participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(2, participants.length);
+		
+		IParticipant[] hosts = svc.getHosts(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, hosts.length);
+		assertEquals("alice", hosts[0].getParticipantId());
+		
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob");
+		participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, participants.length);
+	}
+
+	@Test
+	public void addGetHost(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url", IParticipant.HOST_ROLE));
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob", "Bob", "http://some.url"));
+
+		IParticipant[] participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(2, participants.length);
+		
+		IParticipant host = svc.getHost(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals("alice", host.getParticipantId());
+		
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob");
+		participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, participants.length);
+	}
+	
+	@Test
+	public void getHostNull(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob", "Bob", "http://some.url", "Beekeeper"));
+		IParticipant[] participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, participants.length);
+		IParticipant host = svc.getHost(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertNull(host);
+		
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob");
+	}
+	
+	@Test
+	public void removeByObject(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url", IParticipant.HOST_ROLE));
+		IParticipant participant = svc.getParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals(1, svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID).length);
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, participant);
+		assertEquals(0, svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID).length);
+	}
+	
+	@Test
+	public void addGetViewer(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url", IParticipant.HOST_ROLE));
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob", "Bob", "http://some.url"));
+
+		
+		IParticipant viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "bob");
+		assertEquals("bob", viewer.getParticipantId());
+		
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "bob");
+	}
+	
+	@Test
+	public void addGetIncompleteViewer(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", null, IParticipant.HOST_ROLE));
+
+		
+		IParticipant viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+		assertNull(viewer.getParticipantThumbnailUrl());		
+	}
+	
+	@Test
+	public void addIncompleteParticipant(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", null,null,null));
+
+
+		IParticipant viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+		assertNull(viewer.getParticipantThumbnailUrl());	
+		assertNull(viewer.getParticipantDisplayName());	
+	}
+	
+	@Test
+	public void addParticipantNoId(){
+		assertFalse(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, null, "don",null,null));
+		assertFalse(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "", "carol",null,null));
+	}
+	
+	@Test
+	public void mixedDataAndParticipants(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", null, IParticipant.HOST_ROLE));
+		assertTrue(svc.updateSharedData(API_KEY, WIDGET_ID, CONTEXT_ID, "test-data", "test-value", false));
+		IParticipant[] participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, participants.length);
+		ISharedData[] data = svc.getSharedData(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, data.length);
+	}
+	
+	@Test
+	public void overwriteParticipant(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alice", "http://some.url", IParticipant.HOST_ROLE));
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", "Alicia", "http://some.url", IParticipant.HOST_ROLE));
+		IParticipant[] participants = svc.getParticipants(API_KEY, WIDGET_ID, CONTEXT_ID);
+		assertEquals(1, participants.length);		
+		assertEquals("Alicia", participants[0].getParticipantDisplayName());
+	}
+
+	@Test
+	public void removeNullParticipant(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", null,null,null));
+		IParticipant viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+		assertFalse(svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, ""));
+		viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+	}
+	
+	@Test
+	public void removeNullParticipantObject(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", null,null,null));
+		IParticipant viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+		IParticipant remove = null;
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, remove);
+		viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+	}
+	
+	@Test
+	public void removeNullParticipantId(){
+		assertTrue(svc.addParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, "alice", null,null,null));
+		IParticipant viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+		IParticipant remove = new DefaultParticipantImpl(null, null, null, null);
+		svc.removeParticipant(API_KEY, WIDGET_ID, CONTEXT_ID, remove);
+		viewer = svc.getViewer(API_KEY, WIDGET_ID, CONTEXT_ID, "alice");
+		assertEquals("alice", viewer.getParticipantId());
+	}
+	
+	
+}