/** * Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET * (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije * informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE * COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp., * INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM * ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC)) * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.societies.useragent.feedback; import junit.framework.Assert; import junit.framework.TestCase; import org.mockito.Matchers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.comm.xmpp.exceptions.CommunicationException; import org.societies.api.comm.xmpp.exceptions.XMPPError; import org.societies.api.comm.xmpp.interfaces.ICommManager; import org.societies.api.comm.xmpp.pubsub.PubsubClient; import org.societies.api.identity.IIdentity; import org.societies.api.identity.IIdentityManager; import org.societies.api.identity.Requestor; import org.societies.api.identity.util.RequestorUtils; import org.societies.api.internal.schema.useragent.feedback.NegotiationDetailsBean; import org.societies.api.internal.schema.useragent.feedback.UserFeedbackAccessControlEvent; import org.societies.api.internal.schema.useragent.feedback.UserFeedbackPrivacyNegotiationEvent; import org.societies.api.internal.useragent.feedback.IUserFeedbackResponseEventListener; import org.societies.api.internal.useragent.model.ExpProposalContent; import org.societies.api.internal.useragent.model.ExpProposalType; import org.societies.api.internal.useragent.model.ImpProposalContent; import org.societies.api.internal.useragent.model.ImpProposalType; import org.societies.api.osgi.event.EventTypes; import org.societies.api.schema.identity.RequestorBean; import org.societies.api.schema.privacytrust.privacy.model.privacypolicy.*; import org.societies.api.schema.useragent.feedback.ExpFeedbackResultBean; import org.societies.api.schema.useragent.feedback.FeedbackMethodType; import org.societies.api.schema.useragent.feedback.ImpFeedbackResultBean; import org.societies.api.schema.useragent.feedback.UserFeedbackBean; import org.societies.useragent.api.feedback.IPrivacyPolicyNegotiationHistoryRepository; import org.societies.useragent.api.feedback.IUserFeedbackHistoryRepository; import org.societies.useragent.api.model.UserFeedbackEventTopics; import java.math.BigInteger; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import static org.mockito.Mockito.*; public class TestUserFeedback extends TestCase { private static final Logger log = LoggerFactory.getLogger(TestUserFeedback.class); public static final int SYNC_RESPONSE_DELAY = 1000; private class EventCallback<T> implements IUserFeedbackResponseEventListener<T> { private boolean responseRx = false; private T result = null; @Override public void responseReceived(T result) { log.debug("Callback called"); this.result = result; responseRx = true; } public boolean isResponseRx() { return responseRx; } public T getResult() { return result; } } private UserFeedback userFeedback; // autowired vars private ICommManager mockCommManager; private PubsubClient mockPubSubClient; private IUserFeedbackHistoryRepository mockUserFeedbackHistoryRepository; private IPrivacyPolicyNegotiationHistoryRepository mockPrivacyPolicyNegotiationHistoryRepository; // private vars private IIdentityManager mockIdentityManager; @Override public void setUp() throws Exception { log.debug("setUp()"); mockCommManager = mock(ICommManager.class); mockPubSubClient = mock(PubsubClient.class); mockUserFeedbackHistoryRepository = mock(UserFeedbackHistoryRepository.class); mockPrivacyPolicyNegotiationHistoryRepository = mock(PrivacyPolicyNegotiationHistoryRepository.class); mockIdentityManager = mock(IIdentityManager.class); userFeedback = new UserFeedback(); userFeedback.setCommsMgr(mockCommManager); userFeedback.setPubsub(mockPubSubClient); userFeedback.setUserFeedbackHistoryRepository(mockUserFeedbackHistoryRepository); userFeedback.setPrivacyPolicyNegotiationHistoryRepository(mockPrivacyPolicyNegotiationHistoryRepository); when(mockCommManager.getIdManager()).thenReturn(mockIdentityManager); when(mockUserFeedbackHistoryRepository.listIncomplete()).thenReturn(new ArrayList<UserFeedbackBean>());// just an empty list when(mockPrivacyPolicyNegotiationHistoryRepository.listIncomplete()).thenReturn(new ArrayList<UserFeedbackPrivacyNegotiationEvent>());// just an empty list userFeedback.initialiseUserFeedback(); } public void testGetExplicitFB_sync_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ExpProposalContent content = new ExpProposalContent( "Test proposal", new String[]{"Yes", "No"} ); String expectedResult = "Yes"; final String requestId = UUID.randomUUID().toString(); final ExpFeedbackResultBean resultBean = new ExpFeedbackResultBean(); resultBean.setFeedback(new ArrayList<String>()); resultBean.getFeedback().add(expectedResult); resultBean.setRequestId(requestId); log.debug("Preparing response thread"); new Thread(new Runnable() { @Override public void run() { log.debug("Waiting " + SYNC_RESPONSE_DELAY + "ms to send mock pub sub response"); try { Thread.sleep(SYNC_RESPONSE_DELAY); } catch (InterruptedException e) { log.error("Error delaying mock pubsub event", e); } log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); } }).start(); log.debug("Requesting EXP (AckNack) user feedback"); Future<List<String>> result = userFeedback.getExplicitFB(requestId, ExpProposalType.ACKNACK, content); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertNotNull("Expected Future to contain result", result.get()); Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetExplicitFB_async_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ExpProposalContent content = new ExpProposalContent( "Test proposal", new String[]{"Yes", "No"} ); String expectedResult = "Yes"; final String requestId = UUID.randomUUID().toString(); final ExpFeedbackResultBean resultBean = new ExpFeedbackResultBean(); resultBean.setFeedback(new ArrayList<String>()); resultBean.getFeedback().add(expectedResult); resultBean.setRequestId(requestId); log.debug("Requesting EXP (AckNack) user feedback"); Future<List<String>> result = userFeedback.getExplicitFBAsync(requestId, ExpProposalType.ACKNACK, content, null); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertNull("Expected Future to be empty", result.get()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertNotNull("Expected Future to contain result", result.get()); Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetExplicitFB_callback_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ExpProposalContent content = new ExpProposalContent( "Test proposal", new String[]{"Yes", "No"} ); String expectedResult = "Yes"; final String requestId = UUID.randomUUID().toString(); final ExpFeedbackResultBean resultBean = new ExpFeedbackResultBean(); resultBean.setFeedback(new ArrayList<String>()); resultBean.getFeedback().add(expectedResult); resultBean.setRequestId(requestId); EventCallback<List<String>> callback = new EventCallback<List<String>>(); log.debug("Requesting EXP (AckNack) user feedback"); userFeedback.getExplicitFBAsync(requestId, ExpProposalType.ACKNACK, content, callback); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertFalse(callback.isResponseRx()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertTrue(callback.isResponseRx()); Assert.assertNotNull("Expected callback to contain result", callback.getResult()); Assert.assertEquals("Expected result bean to contain 1 item", 1, callback.getResult().size()); Assert.assertEquals("Expected result bean to contain correct result", expectedResult, callback.getResult().get(0)); } public void testGetExplicitFB_callback_ignoresWrongResponses() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ExpProposalContent content = new ExpProposalContent( "Test proposal", new String[]{"Yes", "No"} ); String expectedResult = "Yes"; final String requestId = UUID.randomUUID().toString(); final String wrongID = UUID.randomUUID().toString(); final ExpFeedbackResultBean resultBean = new ExpFeedbackResultBean(); resultBean.setFeedback(new ArrayList<String>()); resultBean.getFeedback().add(expectedResult); resultBean.setRequestId(requestId); EventCallback<List<String>> callback = new EventCallback<List<String>>(); log.debug("Requesting EXP (AckNack) user feedback"); userFeedback.getExplicitFBAsync(requestId, ExpProposalType.ACKNACK, content, callback); log.debug("Method returned"); log.debug("Sending wrong pubsub responses"); resultBean.setRequestId(wrongID); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, wrongID, resultBean); Assert.assertFalse(callback.isResponseRx()); resultBean.setRequestId(requestId); try { userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); log.debug("Sending correct mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); Assert.assertTrue(callback.isResponseRx()); } public void testGetImplicitFB_sync_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ImpProposalContent content = new ImpProposalContent( "Test proposal", 30000 ); final String requestId = UUID.randomUUID().toString(); final ImpFeedbackResultBean resultBean = new ImpFeedbackResultBean(); resultBean.setAccepted(true); resultBean.setRequestId(requestId); log.debug("Preparing response thread"); new Thread(new Runnable() { @Override public void run() { log.debug("Waiting " + SYNC_RESPONSE_DELAY + "ms to send mock pub sub response"); try { Thread.sleep(SYNC_RESPONSE_DELAY); } catch (InterruptedException e) { log.error("Error delaying mock pubsub event", e); } log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); } }).start(); log.debug("Requesting IMP (Timed Abort) user feedback"); Future<Boolean> result = userFeedback.getImplicitFB(requestId, ImpProposalType.TIMED_ABORT, content); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertNotNull("Expected Future to contain result", result.get()); Assert.assertEquals("Expected result bean to contain correct result", Boolean.TRUE, result.get()); } public void testGetImplicitFB_async_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ImpProposalContent content = new ImpProposalContent( "Test proposal", 30000 ); final String requestId = UUID.randomUUID().toString(); final ImpFeedbackResultBean resultBean = new ImpFeedbackResultBean(); resultBean.setAccepted(true); resultBean.setRequestId(requestId); log.debug("Requesting IMP (Timed Abort) user feedback"); Future<Boolean> result = userFeedback.getImplicitFBAsync(requestId, ImpProposalType.TIMED_ABORT, content, null); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertNull("Expected Future to be empty", result.get()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertNotNull("Expected Future to contain result", result.get()); Assert.assertEquals("Expected result bean to contain correct result", Boolean.TRUE, result.get()); } public void testGetImplicitFB_callback_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ImpProposalContent content = new ImpProposalContent( "Test proposal", 30000 ); final String requestId = UUID.randomUUID().toString(); final ImpFeedbackResultBean resultBean = new ImpFeedbackResultBean(); resultBean.setAccepted(true); resultBean.setRequestId(requestId); EventCallback<Boolean> callback = new EventCallback<Boolean>(); log.debug("Requesting IMP (Timed Abort) user feedback"); userFeedback.getImplicitFBAsync(requestId, ImpProposalType.TIMED_ABORT, content, callback); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertFalse(callback.isResponseRx()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertTrue(callback.isResponseRx()); Assert.assertNotNull("Expected callback to contain result", callback.getResult()); Assert.assertEquals("Expected result bean to contain correct result", Boolean.TRUE, callback.getResult()); } public void testGetImplicitFB_callback_ignoresWrongResponses() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ImpProposalContent content = new ImpProposalContent( "Test proposal", 30000 ); final String requestId = UUID.randomUUID().toString(); final String wrongID = UUID.randomUUID().toString(); final ImpFeedbackResultBean resultBean = new ImpFeedbackResultBean(); resultBean.setAccepted(true); resultBean.setRequestId(requestId); EventCallback<Boolean> callback = new EventCallback<Boolean>(); log.debug("Requesting IMP (Timed Abort) user feedback"); userFeedback.getImplicitFBAsync(requestId, ImpProposalType.TIMED_ABORT, content, callback); log.debug("Method returned"); log.debug("Sending wrong pubsub responses"); resultBean.setRequestId(wrongID); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, wrongID, resultBean); Assert.assertFalse(callback.isResponseRx()); resultBean.setRequestId(requestId); try { userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); log.debug("Sending correct mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); Assert.assertTrue(callback.isResponseRx()); } public void testShowNotification_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { ExpProposalContent content = new ExpProposalContent( "Test proposal", new String[]{"Yes", "No"} ); String expectedResult = "Yes"; final String requestId = UUID.randomUUID().toString(); final ExpFeedbackResultBean resultBean = new ExpFeedbackResultBean(); resultBean.setFeedback(new ArrayList<String>()); resultBean.getFeedback().add(expectedResult); resultBean.setRequestId(requestId); log.debug("Preparing response thread"); new Thread(new Runnable() { @Override public void run() { log.debug("Waiting " + SYNC_RESPONSE_DELAY + "ms to send mock pub sub response"); try { Thread.sleep(SYNC_RESPONSE_DELAY); } catch (InterruptedException e) { log.error("Error delaying mock pubsub event", e); } log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); } }).start(); log.debug("Requesting EXP (AckNack) user feedback"); Future<List<String>> result = userFeedback.getExplicitFB(requestId, ExpProposalType.ACKNACK, content); log.debug("Method returned"); // VERIFICATION verify(mockUserFeedbackHistoryRepository).insert(Matchers.any(UserFeedbackBean.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(UserFeedbackEventTopics.REQUEST), Matchers.eq(requestId), Matchers.any(UserFeedbackBean.class)); Assert.assertNotNull("Expected Future to contain result", result.get()); Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetPrivacyNegotiationFB_sync_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { SecureRandom random = new SecureRandom(); final String requestId = UUID.randomUUID().toString(); final int negotiationId = new BigInteger(130, random).intValue(); RequestorBean requestorBean = new RequestorBean(); requestorBean.setRequestorId(requestId); NegotiationDetailsBean negotiationDetails = new NegotiationDetailsBean(); negotiationDetails.setRequestor(requestorBean); negotiationDetails.setNegotiationID(negotiationId); ResponsePolicy responsePolicy = buildResponsePolicy(requestId, requestorBean); final UserFeedbackPrivacyNegotiationEvent resultBean = new UserFeedbackPrivacyNegotiationEvent(); resultBean.setRequestId(requestId); resultBean.setMethod(FeedbackMethodType.GET_EXPLICIT_FB); resultBean.setNegotiationDetails(negotiationDetails); resultBean.setResponsePolicy(responsePolicy); log.debug("Preparing response thread"); new Thread(new Runnable() { @Override public void run() { log.debug("Waiting " + SYNC_RESPONSE_DELAY + "ms to send mock pub sub response"); try { Thread.sleep(SYNC_RESPONSE_DELAY); } catch (InterruptedException e) { log.error("Error delaying mock pubsub event", e); } log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); } }).start(); log.debug("Requesting PPN feedback"); Future<ResponsePolicy> result = userFeedback.getPrivacyNegotiationFB(requestId, responsePolicy, negotiationDetails); log.debug("Method returned"); // VERIFICATION verify(mockPrivacyPolicyNegotiationHistoryRepository).insert(Matchers.any(UserFeedbackPrivacyNegotiationEvent.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(EventTypes.UF_PRIVACY_NEGOTIATION), Matchers.eq(requestId), Matchers.any(UserFeedbackPrivacyNegotiationEvent.class)); Assert.assertNotNull("Expected Future to contain result", result.get()); // Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); // Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetPrivacyNegotiationFB_async_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { SecureRandom random = new SecureRandom(); final String requestId = UUID.randomUUID().toString(); final int negotiationId = new BigInteger(130, random).intValue(); RequestorBean requestorBean = new RequestorBean(); requestorBean.setRequestorId(requestId); NegotiationDetailsBean negotiationDetails = new NegotiationDetailsBean(); negotiationDetails.setRequestor(requestorBean); negotiationDetails.setNegotiationID(negotiationId); ResponsePolicy responsePolicy = buildResponsePolicy(requestId, requestorBean); final UserFeedbackPrivacyNegotiationEvent resultBean = new UserFeedbackPrivacyNegotiationEvent(); resultBean.setRequestId(requestId); resultBean.setMethod(FeedbackMethodType.GET_EXPLICIT_FB); resultBean.setNegotiationDetails(negotiationDetails); resultBean.setResponsePolicy(responsePolicy); log.debug("Requesting PPN feedback"); Future<ResponsePolicy> result = userFeedback.getPrivacyNegotiationFBAsync(requestId, responsePolicy, negotiationDetails, null); log.debug("Method returned"); // VERIFICATION verify(mockPrivacyPolicyNegotiationHistoryRepository).insert(Matchers.any(UserFeedbackPrivacyNegotiationEvent.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(EventTypes.UF_PRIVACY_NEGOTIATION), Matchers.eq(requestId), Matchers.any(UserFeedbackPrivacyNegotiationEvent.class)); Assert.assertNull("Expected Future to be empty", result.get()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertNotNull("Expected Future to contain result", result.get()); // Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); // Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetPrivacyNegotiationFB_callback_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { SecureRandom random = new SecureRandom(); final String requestId = UUID.randomUUID().toString(); final int negotiationId = new BigInteger(130, random).intValue(); RequestorBean requestorBean = new RequestorBean(); requestorBean.setRequestorId(requestId); NegotiationDetailsBean negotiationDetails = new NegotiationDetailsBean(); negotiationDetails.setRequestor(requestorBean); negotiationDetails.setNegotiationID(negotiationId); ResponsePolicy responsePolicy = buildResponsePolicy(requestId, requestorBean); final UserFeedbackPrivacyNegotiationEvent resultBean = new UserFeedbackPrivacyNegotiationEvent(); resultBean.setRequestId(requestId); resultBean.setMethod(FeedbackMethodType.GET_EXPLICIT_FB); resultBean.setNegotiationDetails(negotiationDetails); resultBean.setResponsePolicy(responsePolicy); EventCallback<ResponsePolicy> callback = new EventCallback<ResponsePolicy>(); log.debug("Requesting PPN feedback"); userFeedback.getPrivacyNegotiationFBAsync(requestId, responsePolicy, negotiationDetails, callback); log.debug("Method returned"); // VERIFICATION verify(mockPrivacyPolicyNegotiationHistoryRepository).insert(Matchers.any(UserFeedbackPrivacyNegotiationEvent.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(EventTypes.UF_PRIVACY_NEGOTIATION), Matchers.eq(requestId), Matchers.any(UserFeedbackPrivacyNegotiationEvent.class)); Assert.assertFalse(callback.isResponseRx()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertTrue(callback.isResponseRx()); Assert.assertNotNull("Expected Future to contain result", callback.getResult()); // Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); // Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetPrivacyNegotiationFB_callback_ignoresWrongResponses() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { SecureRandom random = new SecureRandom(); final String requestId = UUID.randomUUID().toString(); final int negotiationId = new BigInteger(130, random).intValue(); final String wrongID = UUID.randomUUID().toString(); RequestorBean requestorBean = new RequestorBean(); requestorBean.setRequestorId(requestId); NegotiationDetailsBean negotiationDetails = new NegotiationDetailsBean(); negotiationDetails.setRequestor(requestorBean); negotiationDetails.setNegotiationID(negotiationId); ResponsePolicy responsePolicy = buildResponsePolicy(requestId, requestorBean); final UserFeedbackPrivacyNegotiationEvent resultBean = new UserFeedbackPrivacyNegotiationEvent(); resultBean.setRequestId(requestId); resultBean.setMethod(FeedbackMethodType.GET_EXPLICIT_FB); resultBean.setNegotiationDetails(negotiationDetails); resultBean.setResponsePolicy(responsePolicy); EventCallback<ResponsePolicy> callback = new EventCallback<ResponsePolicy>(); log.debug("Requesting PPN feedback"); userFeedback.getPrivacyNegotiationFBAsync(requestId, responsePolicy, negotiationDetails, callback); log.debug("Method returned"); log.debug("Sending wrong pubsub responses"); resultBean.setRequestId(wrongID); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, wrongID, resultBean); Assert.assertFalse(callback.isResponseRx()); resultBean.setRequestId(requestId); try { userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); log.debug("Sending correct mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); Assert.assertTrue(callback.isResponseRx()); } public void testGetAccessControlFB_sync_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { final String requestId = UUID.randomUUID().toString(); IIdentity identity = mock(IIdentity.class); Requestor requestor = new Requestor(identity); List<ResponseItem> responseItems = new ArrayList<ResponseItem>(); responseItems.add(buildResponseItem("ab.cd.ef1", "type1")); responseItems.add(buildResponseItem("ab.cd.ef2", "type2")); responseItems.add(buildResponseItem("ab.cd.ef3", "type3")); final UserFeedbackAccessControlEvent resultBean = new UserFeedbackAccessControlEvent(); resultBean.setRequestId(requestId); resultBean.setResponseItems(responseItems); resultBean.setRequestor(RequestorUtils.toRequestorBean(requestor)); log.debug("Preparing response thread"); new Thread(new Runnable() { @Override public void run() { log.debug("Waiting " + SYNC_RESPONSE_DELAY + "ms to send mock pub sub response"); try { Thread.sleep(SYNC_RESPONSE_DELAY); } catch (InterruptedException e) { log.error("Error delaying mock pubsub event", e); } log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); } }).start(); log.debug("Requesting Access Control user feedback"); Future<List<ResponseItem>> result = userFeedback.getAccessControlFB(requestId, requestor, responseItems); log.debug("Method returned"); // VERIFICATION // verify(mockUserFeedbackHistoryRepository).insert(any(UserFeedbackAccessControlEvent.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(EventTypes.UF_PRIVACY_ACCESS_CONTROL), Matchers.eq(requestId), Matchers.any(UserFeedbackAccessControlEvent.class)); Assert.assertNotNull("Expected Future to contain result", result.get()); // Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); // Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetAccessControlFB_async_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { final String requestId = UUID.randomUUID().toString(); IIdentity identity = mock(IIdentity.class); Requestor requestor = new Requestor(identity); List<ResponseItem> responseItems = new ArrayList<ResponseItem>(); responseItems.add(buildResponseItem("ab.cd.ef1", "type1")); responseItems.add(buildResponseItem("ab.cd.ef2", "type2")); responseItems.add(buildResponseItem("ab.cd.ef3", "type3")); final UserFeedbackAccessControlEvent resultBean = new UserFeedbackAccessControlEvent(); resultBean.setRequestId(requestId); resultBean.setResponseItems(responseItems); resultBean.setRequestor(RequestorUtils.toRequestorBean(requestor)); log.debug("Requesting Access Control user feedback"); Future<List<ResponseItem>> result = userFeedback.getAccessControlFBAsync(requestId, requestor, responseItems, null); log.debug("Method returned"); // VERIFICATION // verify(mockUserFeedbackHistoryRepository).insert(any(UserFeedbackAccessControlEvent.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(EventTypes.UF_PRIVACY_ACCESS_CONTROL), Matchers.eq(requestId), Matchers.any(UserFeedbackAccessControlEvent.class)); Assert.assertNull("Expected Future to be empty", result.get()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertNotNull("Expected Future to contain result", result.get()); // Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); // Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetAccessControlFB_callback_fullSequence() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { final String requestId = UUID.randomUUID().toString(); IIdentity identity = mock(IIdentity.class); Requestor requestor = new Requestor(identity); List<ResponseItem> responseItems = new ArrayList<ResponseItem>(); responseItems.add(buildResponseItem("ab.cd.ef1", "type1")); responseItems.add(buildResponseItem("ab.cd.ef2", "type2")); responseItems.add(buildResponseItem("ab.cd.ef3", "type3")); final UserFeedbackAccessControlEvent resultBean = new UserFeedbackAccessControlEvent(); resultBean.setRequestId(requestId); resultBean.setResponseItems(responseItems); resultBean.setRequestor(RequestorUtils.toRequestorBean(requestor)); EventCallback<List<ResponseItem>> callback = new EventCallback<List<ResponseItem>>(); log.debug("Requesting Access Control user feedback"); userFeedback.getAccessControlFBAsync(requestId, requestor, responseItems, callback); log.debug("Method returned"); // VERIFICATION // verify(mockUserFeedbackHistoryRepository).insert(any(UserFeedbackAccessControlEvent.class)); verify(mockPubSubClient).publisherPublish(Matchers.any(IIdentity.class), Matchers.eq(EventTypes.UF_PRIVACY_ACCESS_CONTROL), Matchers.eq(requestId), Matchers.any(UserFeedbackAccessControlEvent.class)); Assert.assertFalse(callback.isResponseRx()); log.debug("Sending mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); log.debug("Mock pubsub response sent"); Assert.assertTrue(callback.isResponseRx()); Assert.assertNotNull("Expected Future to contain result", callback.getResult()); // Assert.assertEquals("Expected result bean to contain 1 item", 1, result.get().size()); // Assert.assertEquals("Expected result bean to contain correct result", expectedResult, result.get().get(0)); } public void testGetAccessControlFB_callback_ignoresWrongResponses() throws ExecutionException, InterruptedException, CommunicationException, XMPPError { final String requestId = UUID.randomUUID().toString(); final String wrongID = UUID.randomUUID().toString(); IIdentity identity = mock(IIdentity.class); Requestor requestor = new Requestor(identity); List<ResponseItem> responseItems = new ArrayList<ResponseItem>(); responseItems.add(buildResponseItem("ab.cd.ef1", "type1")); responseItems.add(buildResponseItem("ab.cd.ef2", "type2")); responseItems.add(buildResponseItem("ab.cd.ef3", "type3")); final UserFeedbackAccessControlEvent resultBean = new UserFeedbackAccessControlEvent(); resultBean.setRequestId(requestId); resultBean.setResponseItems(responseItems); resultBean.setRequestor(RequestorUtils.toRequestorBean(requestor)); EventCallback<List<ResponseItem>> callback = new EventCallback<List<ResponseItem>>(); log.debug("Requesting Access Control user feedback"); userFeedback.getAccessControlFBAsync(requestId, requestor, responseItems, callback); log.debug("Method returned"); log.debug("Sending wrong pubsub responses"); resultBean.setRequestId(wrongID); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, wrongID, resultBean); Assert.assertFalse(callback.isResponseRx()); resultBean.setRequestId(requestId); try { userFeedback.pubsubEvent(null, UserFeedbackEventTopics.IMPLICIT_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, UserFeedbackEventTopics.EXPLICIT_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); try { userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_NEGOTIATION_RESPONSE, requestId, resultBean); } catch (Exception ex) { // do nothing - this is acceptable behaviour } Assert.assertFalse(callback.isResponseRx()); log.debug("Sending correct mock pubsub response"); userFeedback.pubsubEvent(null, EventTypes.UF_PRIVACY_ACCESS_CONTROL_RESPONSE, requestId, resultBean); Assert.assertTrue(callback.isResponseRx()); } private static ResponsePolicy buildResponsePolicy(String guid, RequestorBean requestorBean) { List<ResponseItem> responseItems = new ArrayList<ResponseItem>(); responseItems.add(buildResponseItem("http://this.is.a.win/", "winning - " + guid)); responseItems.add(buildResponseItem("http://paddy.rules/", "paddy")); responseItems.add(buildResponseItem("http://something.something.something/", "dark side")); ResponsePolicy responsePolicy = new ResponsePolicy(); responsePolicy.setRequestor(requestorBean); responsePolicy.setNegotiationStatus(NegotiationStatus.ONGOING); responsePolicy.setResponseItems(responseItems); return responsePolicy; } private static ResponseItem buildResponseItem(String uri, String dataType) { Action action1 = new Action(); action1.setActionConstant(ActionConstants.CREATE); action1.setOptional(true); Action action2 = new Action(); action2.setActionConstant(ActionConstants.DELETE); action2.setOptional(false); Action action3 = new Action(); action3.setActionConstant(ActionConstants.READ); action3.setOptional(false); Action action4 = new Action(); action4.setActionConstant(ActionConstants.WRITE); action4.setOptional(true); Condition condition1 = new Condition(); condition1.setConditionConstant(ConditionConstants.DATA_RETENTION_IN_HOURS); condition1.setValue("1"); condition1.setOptional(false); Condition condition2 = new Condition(); condition2.setConditionConstant(ConditionConstants.RIGHT_TO_ACCESS_HELD_DATA); condition2.setValue("2"); condition2.setOptional(true); Condition condition3 = new Condition(); condition3.setConditionConstant(ConditionConstants.RIGHT_TO_OPTOUT); condition3.setValue("3"); condition3.setOptional(false); Condition condition4 = new Condition(); condition4.setConditionConstant(ConditionConstants.STORE_IN_SECURE_STORAGE); condition4.setValue("4"); condition4.setOptional(true); Resource resource = new Resource(); resource.setDataIdUri(uri); resource.setDataType(dataType); RequestItem requestItem = new RequestItem(); requestItem.getActions().add(action1); requestItem.getActions().add(action2); requestItem.getActions().add(action3); requestItem.getActions().add(action4); requestItem.getConditions().add(condition1); requestItem.getConditions().add(condition2); requestItem.getConditions().add(condition3); requestItem.getConditions().add(condition4); requestItem.setOptional(false); requestItem.setResource(resource); ResponseItem responseItem = new ResponseItem(); responseItem.setDecision(Decision.INDETERMINATE); responseItem.setRequestItem(requestItem); return responseItem; } }