/* * Copyright 2014-2016 CyberVision, Inc. * * Licensed 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.kaaproject.kaa.server.operations.service.akka; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import akka.actor.ActorContext; import akka.actor.ActorRef; import akka.actor.ActorSystem; import akka.actor.Props; import akka.actor.UntypedActor; import akka.testkit.JavaTestKit; import akka.testkit.TestActorRef; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.kaaproject.kaa.common.Constants; import org.kaaproject.kaa.common.avro.AvroByteArrayConverter; import org.kaaproject.kaa.common.dto.ApplicationDto; import org.kaaproject.kaa.common.dto.EndpointProfileDto; import org.kaaproject.kaa.common.dto.EndpointProfileSchemaDto; import org.kaaproject.kaa.common.dto.EventClassFamilyVersionStateDto; import org.kaaproject.kaa.common.dto.NotificationDto; import org.kaaproject.kaa.common.dto.NotificationTypeDto; import org.kaaproject.kaa.common.dto.ServerProfileSchemaDto; import org.kaaproject.kaa.common.dto.credentials.CredentialsDto; import org.kaaproject.kaa.common.dto.credentials.CredentialsStatus; import org.kaaproject.kaa.common.dto.credentials.EndpointRegistrationDto; import org.kaaproject.kaa.common.dto.ctl.CTLSchemaDto; import org.kaaproject.kaa.common.dto.logs.LogSchemaDto; import org.kaaproject.kaa.common.dto.user.UserVerifierDto; import org.kaaproject.kaa.common.endpoint.gen.ConfigurationSyncRequest; import org.kaaproject.kaa.common.endpoint.gen.EndpointAttachRequest; import org.kaaproject.kaa.common.endpoint.gen.EndpointDetachRequest; import org.kaaproject.kaa.common.endpoint.gen.Event; import org.kaaproject.kaa.common.endpoint.gen.EventSequenceNumberRequest; import org.kaaproject.kaa.common.endpoint.gen.EventSequenceNumberResponse; import org.kaaproject.kaa.common.endpoint.gen.EventSyncRequest; import org.kaaproject.kaa.common.endpoint.gen.EventSyncResponse; import org.kaaproject.kaa.common.endpoint.gen.LogEntry; import org.kaaproject.kaa.common.endpoint.gen.LogSyncRequest; import org.kaaproject.kaa.common.endpoint.gen.NotificationSyncRequest; import org.kaaproject.kaa.common.endpoint.gen.ProfileSyncRequest; import org.kaaproject.kaa.common.endpoint.gen.RedirectSyncResponse; import org.kaaproject.kaa.common.endpoint.gen.SyncRequest; import org.kaaproject.kaa.common.endpoint.gen.SyncRequestMetaData; import org.kaaproject.kaa.common.endpoint.gen.SyncResponse; import org.kaaproject.kaa.common.endpoint.gen.SyncResponseResultType; import org.kaaproject.kaa.common.endpoint.gen.UserAttachNotification; import org.kaaproject.kaa.common.endpoint.gen.UserDetachNotification; import org.kaaproject.kaa.common.endpoint.gen.UserSyncRequest; import org.kaaproject.kaa.common.endpoint.gen.UserSyncResponse; import org.kaaproject.kaa.common.endpoint.security.KeyUtil; import org.kaaproject.kaa.common.endpoint.security.MessageEncoderDecoder; import org.kaaproject.kaa.common.endpoint.security.MessageEncoderDecoder.CipherPair; import org.kaaproject.kaa.common.hash.EndpointObjectHash; import org.kaaproject.kaa.common.hash.Sha1HashUtils; import org.kaaproject.kaa.server.common.Base64Util; import org.kaaproject.kaa.server.common.dao.ApplicationService; import org.kaaproject.kaa.server.common.dao.CtlService; import org.kaaproject.kaa.server.common.dao.exception.CredentialsServiceException; import org.kaaproject.kaa.server.common.dao.exception.EndpointRegistrationServiceException; import org.kaaproject.kaa.server.common.log.shared.appender.LogAppender; import org.kaaproject.kaa.server.common.log.shared.appender.LogDeliveryCallback; import org.kaaproject.kaa.server.common.log.shared.appender.LogSchema; import org.kaaproject.kaa.server.common.log.shared.appender.data.BaseLogEventPack; import org.kaaproject.kaa.server.common.thrift.gen.operations.Notification; import org.kaaproject.kaa.server.common.thrift.gen.operations.RedirectionRule; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEndpointConfigurationRefreshMessage; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftEndpointDeregistrationMessage; import org.kaaproject.kaa.server.common.thrift.gen.operations.ThriftUnicastNotificationMessage; import org.kaaproject.kaa.server.node.service.credentials.CredentialsService; import org.kaaproject.kaa.server.node.service.credentials.CredentialsServiceLocator; import org.kaaproject.kaa.server.node.service.registration.RegistrationService; import org.kaaproject.kaa.server.operations.pojo.SyncContext; import org.kaaproject.kaa.server.operations.pojo.exceptions.GetDeltaException; import org.kaaproject.kaa.server.operations.service.OperationsService; import org.kaaproject.kaa.server.operations.service.akka.actors.core.endpoint.local.LocalEndpointActorMessageProcessor; import org.kaaproject.kaa.server.operations.service.akka.messages.core.route.ActorClassifier; import org.kaaproject.kaa.server.operations.service.akka.messages.core.route.EndpointAddress; import org.kaaproject.kaa.server.operations.service.akka.messages.core.route.RouteOperation; import org.kaaproject.kaa.server.operations.service.akka.messages.core.route.ThriftEndpointActorMsg; import org.kaaproject.kaa.server.operations.service.akka.messages.core.user.EndpointEventDeliveryMessage; import org.kaaproject.kaa.server.operations.service.akka.messages.core.user.EndpointEventReceiveMessage; import org.kaaproject.kaa.server.operations.service.cache.AppVersionKey; import org.kaaproject.kaa.server.operations.service.cache.CacheService; import org.kaaproject.kaa.server.operations.service.cache.EventClassFqnKey; import org.kaaproject.kaa.server.operations.service.cluster.ClusterService; import org.kaaproject.kaa.server.operations.service.event.EndpointEvent; import org.kaaproject.kaa.server.operations.service.event.EventClassFamilyVersion; import org.kaaproject.kaa.server.operations.service.event.EventClassFqnVersion; import org.kaaproject.kaa.server.operations.service.event.EventService; import org.kaaproject.kaa.server.operations.service.event.RemoteEndpointEvent; import org.kaaproject.kaa.server.operations.service.event.RouteInfo; import org.kaaproject.kaa.server.operations.service.event.RouteTableAddress; import org.kaaproject.kaa.server.operations.service.event.RouteTableKey; import org.kaaproject.kaa.server.operations.service.event.UserRouteInfo; import org.kaaproject.kaa.server.operations.service.logs.LogAppenderService; import org.kaaproject.kaa.server.operations.service.metrics.MeterClient; import org.kaaproject.kaa.server.operations.service.metrics.MetricsService; import org.kaaproject.kaa.server.operations.service.notification.NotificationDeltaService; import org.kaaproject.kaa.server.operations.service.security.KeyStoreService; import org.kaaproject.kaa.server.operations.service.user.EndpointUserService; import org.kaaproject.kaa.server.sync.ClientSync; import org.kaaproject.kaa.server.sync.ConfigurationClientSync; import org.kaaproject.kaa.server.sync.ConfigurationServerSync; import org.kaaproject.kaa.server.sync.EventClientSync; import org.kaaproject.kaa.server.sync.EventServerSync; import org.kaaproject.kaa.server.sync.NotificationClientSync; import org.kaaproject.kaa.server.sync.ProfileClientSync; import org.kaaproject.kaa.server.sync.ServerSync; import org.kaaproject.kaa.server.sync.UserClientSync; import org.kaaproject.kaa.server.sync.UserServerSync; import org.kaaproject.kaa.server.sync.platform.AvroEncDec; import org.kaaproject.kaa.server.transport.EndpointRevocationException; import org.kaaproject.kaa.server.transport.EndpointVerificationException; import org.kaaproject.kaa.server.transport.InvalidSdkTokenException; import org.kaaproject.kaa.server.transport.channel.ChannelContext; import org.kaaproject.kaa.server.transport.channel.ChannelType; import org.kaaproject.kaa.server.transport.message.ErrorBuilder; import org.kaaproject.kaa.server.transport.message.MessageBuilder; import org.kaaproject.kaa.server.transport.message.SessionAwareMessage; import org.kaaproject.kaa.server.transport.message.SessionInitMessage; import org.kaaproject.kaa.server.transport.session.SessionInfo; import org.mockito.Matchers; import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.test.util.ReflectionTestUtils; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.PublicKey; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.concurrent.TimeUnit; public class DefaultAkkaServiceTest { private static final String LOCAL_NODE_ID = "LOCAL_NODE_ID"; private static final Logger LOG = LoggerFactory.getLogger(DefaultAkkaServiceTest.class); private static final String SERVER2 = "SERVER2"; private static final String FQN1 = "fqn1"; private static final int ECF1_VERSION = 43; private static final String ECF1_ID = "EF1_ID"; private static final String TOPIC_ID = "TopicId"; private static final String UNICAST_NOTIFICATION_ID = "UnicastNotificationId"; private static final int TIMEOUT = 10000; private static final String TENANT_ID = "TENANT_ID"; private static final String USER_ID = "USER_ID"; private static final String APP_TOKEN = "APP_TOKEN"; private static final String SDK_TOKEN = "SDK_TOKEN"; private static final String INVALID_SDK_TOKEN = "INVALID_SDK_TOKEN"; private static final String APP_ID = "APP_ID"; private static final String PROFILE_BODY = "ProfileBody"; private static final int REQUEST_ID = 42; private DefaultAkkaService akkaService; private AkkaClusterServiceListener clusterServiceListener; // mocks private ClusterService clusterService; private CacheService cacheService; private MetricsService metricsService; private KeyStoreService operationsKeyStoreService; private OperationsService operationsService; private NotificationDeltaService notificationDeltaService; private ApplicationService applicationService; private EventService eventService; private ApplicationDto applicationDto; private SyncContext simpleResponse; private SyncContext noDeltaResponse; private SyncContext deltaResponse; private SyncContext deltaResponseWithProfile; private SyncContext noDeltaResponseWithTopicState; private NotificationDto topicNotification; private LogAppenderService logAppenderService; private EndpointUserService endpointUserService; private CtlService ctlService; private CredentialsServiceLocator credentialsServiceLocator; private CredentialsService credentialsService; private RegistrationService registrationService; private KeyPair clientPair; private KeyPair targetPair; private KeyPair serverPair; private ByteBuffer clientPublicKey; private ByteBuffer clientPublicKeyHash; private ByteBuffer targetPublicKeyHash; private EndpointProfileDto mockProfile; @Before public void before() throws GeneralSecurityException, CredentialsServiceException, EndpointRegistrationServiceException { akkaService = new DefaultAkkaService(); AkkaContext context = new AkkaContext(); clusterService = mock(ClusterService.class); cacheService = mock(CacheService.class); metricsService = mock(MetricsService.class); operationsKeyStoreService = mock(KeyStoreService.class); operationsService = mock(OperationsService.class); notificationDeltaService = mock(NotificationDeltaService.class); applicationService = mock(ApplicationService.class); eventService = mock(EventService.class); logAppenderService = mock(LogAppenderService.class); endpointUserService = mock(EndpointUserService.class); ctlService = mock(CtlService.class); credentialsServiceLocator = mock(CredentialsServiceLocator.class); credentialsService = mock(CredentialsService.class); registrationService = mock(RegistrationService.class); ReflectionTestUtils.setField(context, "clusterService", clusterService); ReflectionTestUtils.setField(context, "cacheService", cacheService); ReflectionTestUtils.setField(context, "metricsService", metricsService); ReflectionTestUtils.setField(context, "operationsKeyStoreService", operationsKeyStoreService); ReflectionTestUtils.setField(context, "operationsService", operationsService); ReflectionTestUtils.setField(context, "notificationDeltaService", notificationDeltaService); ReflectionTestUtils.setField(context, "applicationService", applicationService); ReflectionTestUtils.setField(context, "eventService", eventService); ReflectionTestUtils.setField(context, "logAppenderService", logAppenderService); ReflectionTestUtils.setField(context, "endpointUserService", endpointUserService); ReflectionTestUtils.setField(context, "ctlService", ctlService); ReflectionTestUtils.setField(context, "credentialsServiceLocator", credentialsServiceLocator); ReflectionTestUtils.setField(context, "registrationService", registrationService); clientPair = KeyUtil.generateKeyPair(); targetPair = KeyUtil.generateKeyPair(); serverPair = KeyUtil.generateKeyPair(); Mockito.when(operationsKeyStoreService.getPublicKey()).thenReturn(serverPair.getPublic()); Mockito.when(operationsKeyStoreService.getPrivateKey()).thenReturn(serverPair.getPrivate()); Mockito.when(metricsService.createMeter(Mockito.anyString(), Mockito.anyString())).thenReturn(Mockito.mock(MeterClient.class)); Mockito.when(credentialsServiceLocator.getCredentialsService(Mockito.anyString())).thenReturn(credentialsService); Mockito.when(credentialsService.lookupCredentials(Mockito.anyString())).thenReturn(Optional.ofNullable((CredentialsDto) null)); registerPublicKey(clientPair.getPublic()); registerPublicKey(targetPair.getPublic()); ReflectionTestUtils.setField(akkaService, "context", context); if (akkaService.getActorSystem() == null) { akkaService.initActorSystem(); } clusterServiceListener = (AkkaClusterServiceListener) ReflectionTestUtils.getField(akkaService, "clusterListener"); clientPublicKey = ByteBuffer.wrap(clientPair.getPublic().getEncoded()); clientPublicKeyHash = ByteBuffer.wrap(Sha1HashUtils.hashToBytes(clientPair.getPublic().getEncoded())); targetPublicKeyHash = ByteBuffer.wrap(Sha1HashUtils.hashToBytes(targetPair.getPublic().getEncoded())); Mockito.when(cacheService.getTenantIdByAppToken(APP_TOKEN)).thenReturn(TENANT_ID); Mockito.when(cacheService.getAppTokenBySdkToken(SDK_TOKEN)).thenReturn(APP_TOKEN); Mockito.when(cacheService.getAppTokenBySdkToken(INVALID_SDK_TOKEN)).thenReturn(null); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(targetPublicKeyHash.array()))) .thenReturn(targetPair.getPublic()); applicationDto = new ApplicationDto(); applicationDto.setId(APP_ID); applicationDto.setApplicationToken(APP_TOKEN); applicationDto.setTenantId(TENANT_ID); ServerSync response = new ServerSync(); response.setRequestId(REQUEST_ID); response.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); ConfigurationServerSync confSyncResponse = new ConfigurationServerSync(); confSyncResponse.setResponseStatus(org.kaaproject.kaa.server.sync.SyncResponseStatus.NO_DELTA); response.setConfigurationSync(confSyncResponse); noDeltaResponse = new SyncContext(response); Map<String, Integer> subscriptionStates = new HashMap<>(); subscriptionStates.put(TOPIC_ID, new Integer(0)); noDeltaResponseWithTopicState = new SyncContext(response); noDeltaResponseWithTopicState.setSubscriptionStates(subscriptionStates); EndpointProfileDto epDto = new EndpointProfileDto(); epDto.setSystemNfVersion(42); epDto.setUserNfVersion(43); epDto.setLogSchemaVersion(44); noDeltaResponseWithTopicState.setNotificationVersion(epDto); response = new ServerSync(); response.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); confSyncResponse = new ConfigurationServerSync(); confSyncResponse.setResponseStatus(org.kaaproject.kaa.server.sync.SyncResponseStatus.DELTA); response.setConfigurationSync(confSyncResponse); deltaResponse = new SyncContext(response); response = new ServerSync(); response.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); confSyncResponse = new ConfigurationServerSync(); confSyncResponse.setResponseStatus(org.kaaproject.kaa.server.sync.SyncResponseStatus.DELTA); response.setConfigurationSync(confSyncResponse); deltaResponseWithProfile = new SyncContext(response); mockProfile = mock(EndpointProfileDto.class); deltaResponseWithProfile.setNotificationVersion(mockProfile); response = new ServerSync(); response.setRequestId(REQUEST_ID); response.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); simpleResponse = new SyncContext(response); topicNotification = new NotificationDto(); topicNotification.setApplicationId(APP_ID); topicNotification.setTopicId(TOPIC_ID); topicNotification.setId(UNICAST_NOTIFICATION_ID); topicNotification.setExpiredAt(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(7))); topicNotification.setSecNum(1); topicNotification.setNfVersion(42); topicNotification.setType(NotificationTypeDto.SYSTEM); topicNotification.setBody("I am a dummy notification".getBytes()); when(applicationService.findAppByApplicationToken(APP_TOKEN)).thenReturn(applicationDto); when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); when(endpointUserService.findUserVerifiers(APP_ID)).thenReturn(new ArrayList<UserVerifierDto>()); when(eventService.isMainUserNode(Mockito.anyString())).thenReturn(true); when(clusterService.getNodeId()).thenReturn(LOCAL_NODE_ID); when(clusterService.getEntityNode(Mockito.any(byte[].class))).thenReturn(LOCAL_NODE_ID); when(clusterService.getEntityNode(Mockito.any(EndpointObjectHash.class))).thenReturn(LOCAL_NODE_ID); } private void registerPublicKey(PublicKey publicKey) throws EndpointRegistrationServiceException { byte[] clientPublicKeyBytes = publicKey.getEncoded(); String endpointId = Base64Util.encode(EndpointObjectHash.fromSha1(clientPublicKeyBytes).getData()); EndpointRegistrationDto endpointRegistration = new EndpointRegistrationDto(APP_ID, endpointId, endpointId, null, null); Mockito.when(registrationService.findEndpointRegistrationByCredentialsId(endpointId)).thenReturn(Optional.of(endpointRegistration)); } @After public void after() { akkaService.getActorSystem().shutdown(); akkaService.getActorSystem().awaitTermination(); } private SessionInitMessage toSignedRequest(final UUID uuid, final ChannelType channelType, final ChannelContext ctx, SyncRequest request, final MessageBuilder responseBuilder, final ErrorBuilder errorBuilder) throws Exception { MessageEncoderDecoder crypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); return toSignedRequest(uuid, channelType, ctx, request, responseBuilder, errorBuilder, crypt); } private SessionInitMessage toSignedRequest(final UUID uuid, final ChannelType channelType, final ChannelContext ctx, SyncRequest request, final MessageBuilder responseBuilder, final ErrorBuilder errorBuilder, MessageEncoderDecoder crypt) throws Exception { AvroByteArrayConverter<SyncRequest> requestConverter = new AvroByteArrayConverter<>(SyncRequest.class); byte[] data = requestConverter.toByteArray(request); final byte[] encodedData = crypt.encodeData(data); final byte[] encodedSessionKey = crypt.getEncodedSessionKey(); final byte[] sessionKeySignature = crypt.sign(encodedSessionKey); return new SessionInitMessage() { @Override public UUID getChannelUuid() { return uuid; } @Override public ChannelType getChannelType() { return channelType; } @Override public ChannelContext getChannelContext() { return ctx; } @Override public byte[] getSessionKeySignature() { return sessionKeySignature; } @Override public byte[] getEncodedSessionKey() { return encodedSessionKey; } @Override public byte[] getEncodedMessageData() { return encodedData; } @Override public MessageBuilder getMessageBuilder() { return responseBuilder; } @Override public ErrorBuilder getErrorBuilder() { return errorBuilder; } @Override public void onSessionCreated(SessionInfo session) { } @Override public int getKeepAlive() { return 100; } @Override public boolean isEncrypted() { return true; } @Override public int getPlatformId() { return Constants.KAA_PLATFORM_PROTOCOL_AVRO_ID; } }; } @Test public void testAkkaInitialization() { Assert.assertNotNull(akkaService.getActorSystem()); } @Test public void testDecodeSighnedException() throws Exception { SessionInitMessage message = Mockito.mock(SessionInitMessage.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); Mockito.when(message.getChannelContext()).thenReturn(Mockito.mock(ChannelContext.class)); Mockito.when(message.getErrorBuilder()).thenReturn(errorBuilder); Mockito.when(message.getEncodedMessageData()).thenReturn("dummy".getBytes()); Mockito.when(message.getEncodedSessionKey()).thenReturn("dummy".getBytes()); Mockito.when(message.getSessionKeySignature()).thenReturn("dummy".getBytes()); Mockito.when(message.isEncrypted()).thenReturn(true); akkaService.process(message); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT * 10).atLeastOnce()).build(Mockito.any(Exception.class)); } @Test public void testDecodeSessionException() throws Exception { SessionAwareMessage message = Mockito.mock(SessionAwareMessage.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInfo sessionInfo = new SessionInfo(UUID.randomUUID(), Constants.KAA_PLATFORM_PROTOCOL_AVRO_ID, Mockito.mock(ChannelContext.class), ChannelType.ASYNC, Mockito.mock(CipherPair.class), EndpointObjectHash.fromSha1("test"), "applicationToken", "sdkToken", 100, true); Mockito.when(message.getChannelContext()).thenReturn(Mockito.mock(ChannelContext.class)); Mockito.when(message.getErrorBuilder()).thenReturn(errorBuilder); Mockito.when(message.getSessionInfo()).thenReturn(sessionInfo); Mockito.when(message.getEncodedMessageData()).thenReturn("dummy".getBytes()); Mockito.when(message.isEncrypted()).thenReturn(true); akkaService.process(message); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT * 10).atLeastOnce()).build(Mockito.any(Exception.class)); } @Test public void testInvalidSDKTokenException() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(INVALID_SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); ProfileSyncRequest profileSync = new ProfileSyncRequest(); profileSync.setEndpointPublicKey(clientPublicKey); profileSync.setProfileBody(ByteBuffer.wrap(PROFILE_BODY.getBytes())); request.setProfileSyncRequest(profileSync); whenSync(simpleResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.isA(InvalidSdkTokenException.class)); } @Test public void testEndpointRegistrationRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); ProfileSyncRequest profileSync = new ProfileSyncRequest(); profileSync.setEndpointPublicKey(clientPublicKey); profileSync.setProfileBody(ByteBuffer.wrap(PROFILE_BODY.getBytes())); request.setProfileSyncRequest(profileSync); whenSync(simpleResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT * 10).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testEndpointUpdateRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); ProfileSyncRequest profileSync = new ProfileSyncRequest(); profileSync.setProfileBody(ByteBuffer.wrap(PROFILE_BODY.getBytes())); request.setProfileSyncRequest(profileSync); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(simpleResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT * 10).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); SyncContext holder = simpleResponse; Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(holder); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testMultipleSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); SyncContext holder = simpleResponse; Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(holder); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message1 = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); SessionInitMessage message2 = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); akkaService.process(message1); akkaService.process(message2); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT * 10).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeast(2)).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testLongSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); md.setTimeout(1000l); request.setSyncRequestMetaData(md); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(noDeltaResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } private void whenSync(SyncContext response) throws GetDeltaException { Mockito.when(operationsService.syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class))) .thenReturn(response); Mockito.when( operationsService.processEndpointAttachDetachRequests(Mockito.any(SyncContext.class), Mockito.any(UserClientSync.class))) .thenReturn(response); Mockito.when(operationsService.processEventListenerRequests(Mockito.any(SyncContext.class), Mockito.any(EventClientSync.class))) .thenReturn(response); Mockito.when(operationsService.syncConfiguration(Mockito.any(SyncContext.class), Mockito.any(ConfigurationClientSync.class))) .thenReturn(response); Mockito.when(operationsService.syncNotification(Mockito.any(SyncContext.class), Mockito.any(NotificationClientSync.class))) .thenReturn(response); Mockito.when(operationsService.syncUseConfigurationRawSchema(Mockito.any(SyncContext.class), Matchers.anyBoolean())) .thenReturn(response); } private void whenSync(ClientSync request, SyncContext response) throws GetDeltaException { SyncContext context = new SyncContext(new ServerSync()); if (request.getClientSyncMetaData() != null) { request.getClientSyncMetaData().setApplicationToken(APP_TOKEN); } context.setRequestHash(request.hashCode()); Mockito.when(operationsService.syncClientProfile(context, request.getProfileSync())).thenReturn(response); Mockito.when(operationsService.processEndpointAttachDetachRequests(response, request.getUserSync())).thenReturn(response); Mockito.when(operationsService.processEventListenerRequests(response, request.getEventSync())).thenReturn(response); Mockito.when(operationsService.syncConfiguration(response, request.getConfigurationSync())).thenReturn(response); Mockito.when(operationsService.syncNotification(response, request.getNotificationSync())).thenReturn(response); Mockito.when(operationsService.syncUseConfigurationRawSchema(response, request.isUseConfigurationRawSchema())).thenReturn(response); } @Test public void testLongSyncNotification() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = buildSyncRequestMetaData(); request.setSyncRequestMetaData(md); ConfigurationSyncRequest csRequest = new ConfigurationSyncRequest(); csRequest.setConfigurationHash(ByteBuffer.wrap(new byte[]{})); csRequest.setResyncOnly(true); request.setConfigurationSyncRequest(csRequest); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(noDeltaResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); whenSync(deltaResponse); Notification thriftNotification = new Notification(); thriftNotification.setAppId(APP_ID); akkaService.onNotification(thriftNotification); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testLongSyncUnicastNotification() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); request.setSyncRequestMetaData(buildSyncRequestMetaData()); NotificationSyncRequest nfRequest = new NotificationSyncRequest(); request.setNotificationSyncRequest(nfRequest); whenSync(noDeltaResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT / 2).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.when(operationsService.updateSyncResponse(noDeltaResponse.getResponse(), new ArrayList<NotificationDto>(), UNICAST_NOTIFICATION_ID)).thenReturn(noDeltaResponse.getResponse()); Mockito.when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); EndpointAddress address = new EndpointAddress(applicationDto.getTenantId(), applicationDto.getApplicationToken(), EndpointObjectHash.fromBytes(clientPublicKeyHash.array())); ActorClassifier classifier = ActorClassifier.GLOBAL; // TODO: replace nulls with values ThriftUnicastNotificationMessage msg = new ThriftUnicastNotificationMessage(null, null, UNICAST_NOTIFICATION_ID); clusterServiceListener.onEndpointActorMsg(new ThriftEndpointActorMsg<ThriftUnicastNotificationMessage>(address, classifier, msg)); Mockito.verify(operationsService, Mockito.timeout(10 * TIMEOUT / 2).atLeastOnce()).updateSyncResponse(noDeltaResponse.getResponse(), new ArrayList<NotificationDto>(), UNICAST_NOTIFICATION_ID); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testLongSyncTopicNotificationOnStart() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); Mockito.when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); Notification thriftNotification = new Notification(); thriftNotification.setAppId(APP_ID); thriftNotification.setTopicId(TOPIC_ID); thriftNotification.setNotificationId(UNICAST_NOTIFICATION_ID); akkaService.onNotification(thriftNotification); Mockito.when(notificationDeltaService.findNotificationById(UNICAST_NOTIFICATION_ID)).thenReturn(topicNotification); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); request.setSyncRequestMetaData(buildSyncRequestMetaData()); NotificationSyncRequest nfRequest = new NotificationSyncRequest(); request.setNotificationSyncRequest(nfRequest); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); whenSync(noDeltaResponseWithTopicState); Mockito.when(operationsService.updateSyncResponse(noDeltaResponseWithTopicState.getResponse(), Collections.singletonList(topicNotification), null)).thenReturn(noDeltaResponseWithTopicState.getResponse()); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT / 2).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT / 2).atLeastOnce()) .updateSyncResponse(noDeltaResponseWithTopicState.getResponse(), Collections.singletonList(topicNotification), null); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testLongSyncTopicNotification() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); request.setSyncRequestMetaData(buildSyncRequestMetaData()); NotificationSyncRequest nfRequest = new NotificationSyncRequest(); request.setNotificationSyncRequest(nfRequest); Mockito.when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); Mockito.when(notificationDeltaService.findNotificationById(UNICAST_NOTIFICATION_ID)).thenReturn(topicNotification); whenSync(noDeltaResponseWithTopicState); Mockito.when(operationsService.updateSyncResponse(noDeltaResponseWithTopicState.getResponse(), Collections.singletonList(topicNotification), null)).thenReturn(noDeltaResponseWithTopicState.getResponse()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Thread.sleep(3000); Notification thriftNotification = new Notification(); thriftNotification.setAppId(APP_ID); thriftNotification.setTopicId(TOPIC_ID); thriftNotification.setNotificationId(UNICAST_NOTIFICATION_ID); akkaService.onNotification(thriftNotification); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT / 2).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT / 2).atLeastOnce()) .updateSyncResponse(noDeltaResponseWithTopicState.getResponse(), Collections.singletonList(topicNotification), null); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testRedirect() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); MessageEncoderDecoder crypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); akkaService.onRedirectionRule(new RedirectionRule("testDNS".hashCode(), 123, 1.0, 0.0, 60000)); Thread.sleep(1000); SyncRequest request = new SyncRequest(); request.setRequestId(32); request.setSyncRequestMetaData(buildSyncRequestMetaData()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder, crypt); akkaService.process(message); SyncResponse response = new SyncResponse(); response.setRequestId(request.getRequestId()); response.setStatus(SyncResponseResultType.REDIRECT); response.setRedirectSyncResponse(new RedirectSyncResponse("testDNS".hashCode())); Thread.sleep(TIMEOUT / 2); Mockito.verify(operationsService, Mockito.never()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] encodedData = crypt.encodeData(responseConverter.toByteArray(response)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testRedirectSessionRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); MessageEncoderDecoder crypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); akkaService.onRedirectionRule(new RedirectionRule("testDNS".hashCode(), 123, 0.0, 1.0, 60000)); Thread.sleep(1000); SyncRequest request = new SyncRequest(); request.setRequestId(32); request.setSyncRequestMetaData(buildSyncRequestMetaData()); final MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); final ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); AvroByteArrayConverter<SyncRequest> requestConverter = new AvroByteArrayConverter<>(SyncRequest.class); final org.kaaproject.kaa.common.channels.protocols.kaatcp.messages.SyncRequest kaaSync = new org.kaaproject.kaa.common.channels.protocols.kaatcp.messages.SyncRequest( crypt.encodeData(requestConverter.toByteArray(request)), false, true); final SessionInfo session = new SessionInfo(UUID.randomUUID(), Constants.KAA_PLATFORM_PROTOCOL_AVRO_ID, channelContextMock, ChannelType.ASYNC, crypt.getSessionCipherPair(), EndpointObjectHash.fromBytes(clientPublicKey.array()), APP_TOKEN, SDK_TOKEN, 100, true); SessionAwareMessage message = new SessionAwareMessage() { @Override public SessionInfo getSessionInfo() { return session; } @Override public int getPlatformId() { return session.getPlatformId(); } @Override public UUID getChannelUuid() { return session.getUuid(); } @Override public ChannelType getChannelType() { return session.getChannelType(); } @Override public ChannelContext getChannelContext() { return session.getCtx(); } @Override public boolean isEncrypted() { return session.isEncrypted(); } @Override public MessageBuilder getMessageBuilder() { return responseBuilder; } @Override public ErrorBuilder getErrorBuilder() { return errorBuilder; } @Override public byte[] getEncodedMessageData() { return kaaSync.getAvroObject(); } }; akkaService.process(message); SyncResponse response = new SyncResponse(); response.setRequestId(request.getRequestId()); response.setStatus(SyncResponseResultType.REDIRECT); response.setRedirectSyncResponse(new RedirectSyncResponse("testDNS".hashCode())); Thread.sleep(TIMEOUT / 2); Mockito.verify(operationsService, Mockito.never()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] encodedData = crypt.encodeData(responseConverter.toByteArray(response)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testRedirectExpire() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); MessageEncoderDecoder crypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); akkaService.onRedirectionRule(new RedirectionRule("testDNS".hashCode(), 123, 1.0, 1.0, 1000)); Thread.sleep(2000); SyncRequest request = new SyncRequest(); request.setRequestId(32); request.setSyncRequestMetaData(buildSyncRequestMetaData()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder, crypt); whenSync(noDeltaResponseWithTopicState); akkaService.process(message); SyncResponse response = new SyncResponse(); response.setRequestId(request.getRequestId()); response.setStatus(SyncResponseResultType.REDIRECT); response.setRedirectSyncResponse(new RedirectSyncResponse("testDNS".hashCode())); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT / 2).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); } @Test public void testEndpointEventBasic() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); EndpointProfileDto sourceProfileMock = Mockito.mock(EndpointProfileDto.class); EndpointProfileDto targetProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); Event event = new Event(0, FQN1, ByteBuffer.wrap(new byte[0]), Base64Util.encode(clientPublicKeyHash.array()), null); SyncRequest sourceRequest = new SyncRequest(); sourceRequest.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); md.setTimeout(TIMEOUT * 1L); sourceRequest.setSyncRequestMetaData(md); EventSyncRequest eventRequest = new EventSyncRequest(); eventRequest.setEvents(Arrays.asList(event)); sourceRequest.setEventSyncRequest(eventRequest); ServerSync sourceResponse = new ServerSync(); sourceResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); SyncContext sourceResponseHolder = new SyncContext(sourceResponse); sourceResponseHolder.setNotificationVersion(sourceProfileMock); SyncRequest targetRequest = new SyncRequest(); targetRequest.setRequestId(REQUEST_ID); md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(targetPublicKeyHash); md.setProfileHash(targetPublicKeyHash); md.setTimeout(TIMEOUT * 1L); targetRequest.setSyncRequestMetaData(md); targetRequest.setEventSyncRequest(new EventSyncRequest()); ServerSync targetResponse = new ServerSync(); targetResponse.setRequestId(REQUEST_ID); targetResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); SyncContext targetResponseHolder = new SyncContext(targetResponse); targetResponseHolder.setNotificationVersion(targetProfileMock); whenSync(AvroEncDec.convert(sourceRequest), sourceResponseHolder); whenSync(AvroEncDec.convert(targetRequest), targetResponseHolder); when(sourceProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(sourceProfileMock.getEndpointKeyHash()).thenReturn(clientPublicKeyHash.array()); when(sourceProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(targetProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(targetProfileMock.getEndpointKeyHash()).thenReturn(targetPublicKeyHash.array()); when(targetProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); MessageEncoderDecoder sourceCrypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); SessionInitMessage sourceMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, sourceRequest, responseBuilder, errorBuilder, sourceCrypt); akkaService.process(sourceMessage); // sourceRequest Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); MessageEncoderDecoder targetCrypt = new MessageEncoderDecoder(targetPair.getPrivate(), targetPair.getPublic(), serverPair.getPublic()); SessionInitMessage targetMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, targetRequest, responseBuilder, errorBuilder, targetCrypt); akkaService.process(targetMessage); // targetRequest Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); SyncResponse eventResponse = new SyncResponse(); eventResponse.setRequestId(REQUEST_ID); eventResponse.setStatus(SyncResponseResultType.SUCCESS); eventResponse.setEventSyncResponse(new EventSyncResponse()); eventResponse.getEventSyncResponse().setEvents(Arrays.asList(event)); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] response = responseConverter.toByteArray(eventResponse); byte[] encodedData = targetCrypt.encodeData(response); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testEndpointNotAttachedEvent() throws Exception { AkkaContext context = mock(AkkaContext.class); ActorContext actorCtxMock = mock(ActorContext.class); ActorRef actorMock = spy(ActorRef.class); ActorSystem system = ActorSystem.create(); try { final Props props = Props.create(TestActor.class); final TestActorRef<TestActor> parentMock = TestActorRef.create(system, props, "testA"); when(actorCtxMock.self()).thenReturn(actorMock); when(actorCtxMock.parent()).thenReturn(parentMock); EndpointEventReceiveMessage msg = mock(EndpointEventReceiveMessage.class); LocalEndpointActorMessageProcessor processor = spy(new LocalEndpointActorMessageProcessor( context, APP_TOKEN, EndpointObjectHash.fromSha1(clientPublicKeyHash.array()), "ACTOR_TOKEN" )); processor.processEndpointEventReceiveMessage(actorCtxMock, msg); Assert.assertEquals( EndpointEventDeliveryMessage.EventDeliveryStatus.FAILURE, ((EndpointEventDeliveryMessage) parentMock.underlyingActor().getMsg()).getStatus()); } finally { JavaTestKit.shutdownActorSystem(system); } } @Test public void testEndpointEventSeqNumberBasic() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); EndpointProfileDto sourceProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); SyncRequest sourceRequest = new SyncRequest(); sourceRequest.setRequestId(REQUEST_ID); sourceRequest.setSyncRequestMetaData(buildSyncRequestMetaData()); EventSyncRequest eventRequest = new EventSyncRequest(); eventRequest.setEventSequenceNumberRequest(new EventSequenceNumberRequest()); sourceRequest.setEventSyncRequest(eventRequest); ServerSync sourceResponse = new ServerSync(); sourceResponse.setRequestId(REQUEST_ID); sourceResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); SyncContext sourceResponseHolder = new SyncContext(sourceResponse); sourceResponseHolder.setNotificationVersion(sourceProfileMock); whenSync(AvroEncDec.convert(sourceRequest), sourceResponseHolder); when(sourceProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(sourceProfileMock.getEndpointKeyHash()).thenReturn(clientPublicKeyHash.array()); when(sourceProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); MessageEncoderDecoder sourceCrypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); SessionInitMessage sourceMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, sourceRequest, responseBuilder, errorBuilder, sourceCrypt); akkaService.process(sourceMessage); // sourceRequest Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); SyncResponse eventResponse = new SyncResponse(); eventResponse.setRequestId(REQUEST_ID); eventResponse.setStatus(SyncResponseResultType.SUCCESS); eventResponse.setEventSyncResponse(new EventSyncResponse()); eventResponse.getEventSyncResponse().setEventSequenceNumberResponse(new EventSequenceNumberResponse(0)); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] response = responseConverter.toByteArray(eventResponse); LOG.trace("Response to compare {}", Arrays.toString(response)); byte[] encodedData = sourceCrypt.encodeData(response); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testRemoteIncomingEndpointEventBasic() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); EndpointProfileDto targetProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); SyncRequest targetRequest = new SyncRequest(); targetRequest.setRequestId(REQUEST_ID); targetRequest.setSyncRequestMetaData(buildSyncRequestMetaData(targetPublicKeyHash)); targetRequest.setEventSyncRequest(new EventSyncRequest()); ServerSync targetResponse = new ServerSync(); targetResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); SyncContext targetResponseHolder = new SyncContext(targetResponse); targetResponseHolder.setNotificationVersion(targetProfileMock); whenSync(AvroEncDec.convert(targetRequest), targetResponseHolder); when(targetProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(targetProfileMock.getEndpointKeyHash()).thenReturn(targetPublicKeyHash.array()); when(targetProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); MessageEncoderDecoder targetCrypt = new MessageEncoderDecoder(targetPair.getPrivate(), targetPair.getPublic(), serverPair.getPublic()); SessionInitMessage targetMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, targetRequest, responseBuilder, errorBuilder, targetCrypt); akkaService.process(targetMessage); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); org.kaaproject.kaa.server.sync.Event event = new org.kaaproject.kaa.server.sync.Event(0, FQN1, ByteBuffer.wrap(new byte[0]), null, null); EndpointEvent endpointEvent = new EndpointEvent(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()), event, UUID.randomUUID(), System.currentTimeMillis(), ECF1_VERSION); RemoteEndpointEvent remoteEvent = new RemoteEndpointEvent(TENANT_ID, USER_ID, endpointEvent, new RouteTableAddress(EndpointObjectHash.fromBytes(targetPublicKeyHash.array()), APP_TOKEN, "SERVER1")); akkaService.getListener().onEvent(remoteEvent); event = new org.kaaproject.kaa.server.sync.Event(0, FQN1, ByteBuffer.wrap(new byte[0]), null, Base64Util.encode(targetPublicKeyHash.array())); ServerSync eventResponse = new ServerSync(); eventResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); eventResponse.setEventSync(new EventServerSync()); eventResponse.getEventSync().setEvents(Arrays.asList(event)); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] response = responseConverter.toByteArray(AvroEncDec.convert(eventResponse)); byte[] encodedData = targetCrypt.encodeData(response); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testRemoteOutcomingEndpointEventBasic() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); EndpointProfileDto sourceProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); Event event = new Event(0, FQN1, ByteBuffer.wrap(new byte[0]), Base64Util.encode(clientPublicKeyHash.array()), null); SyncRequest sourceRequest = new SyncRequest(); sourceRequest.setRequestId(REQUEST_ID); sourceRequest.setSyncRequestMetaData(buildSyncRequestMetaData(clientPublicKeyHash)); EventSyncRequest eventRequest = new EventSyncRequest(); eventRequest.setEvents(Arrays.asList(event)); sourceRequest.setEventSyncRequest(eventRequest); ServerSync sourceResponse = new ServerSync(); sourceResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); SyncContext sourceResponseHolder = new SyncContext(sourceResponse); sourceResponseHolder.setNotificationVersion(sourceProfileMock); whenSync(AvroEncDec.convert(sourceRequest), sourceResponseHolder); when(sourceProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(sourceProfileMock.getEndpointKeyHash()).thenReturn(clientPublicKeyHash.array()); when(sourceProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); MessageEncoderDecoder sourceCrypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); SessionInitMessage sourceMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, sourceRequest, responseBuilder, errorBuilder, sourceCrypt); akkaService.process(sourceMessage); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); UserRouteInfo userRouteInfo = new UserRouteInfo(TENANT_ID, USER_ID, SERVER2, RouteOperation.ADD); akkaService.getListener().onUserRouteInfo(userRouteInfo); RouteTableAddress remoteAddress = new RouteTableAddress(EndpointObjectHash.fromBytes(targetPublicKeyHash.array()), APP_TOKEN, SERVER2); RouteInfo routeInfo = new RouteInfo(TENANT_ID, USER_ID, remoteAddress, Arrays.asList(new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION))); TimeUnit.SECONDS.sleep(2); akkaService.getListener().onRouteInfo(routeInfo); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()).sendEvent(Mockito.any(RemoteEndpointEvent.class)); } @Test public void testLogSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); md.setTimeout(1000l); request.setSyncRequestMetaData(md); LogSyncRequest logRequest = new LogSyncRequest(REQUEST_ID, Collections.singletonList(new LogEntry(ByteBuffer.wrap("String".getBytes())))); request.setLogSyncRequest(logRequest); whenSync(noDeltaResponseWithTopicState); LogAppender mockAppender = Mockito.mock(LogAppender.class); Mockito.when(logAppenderService.getApplicationAppenders(APP_ID)).thenReturn(Collections.singletonList(mockAppender)); Mockito.when(logAppenderService.getLogSchema(Mockito.anyString(), Mockito.anyInt())).thenReturn(new LogSchema(new LogSchemaDto(), "")); EndpointProfileSchemaDto profileSchemaDto = new EndpointProfileSchemaDto(); profileSchemaDto.setId("1"); profileSchemaDto.setCtlSchemaId("22"); CTLSchemaDto ctlSchema = new CTLSchemaDto(); ctlSchema.setId("22"); when(cacheService.getProfileSchemaByAppAndVersion(new AppVersionKey(APP_TOKEN, 0))).thenReturn(profileSchemaDto); when(cacheService.getCtlSchemaById("22")).thenReturn(ctlSchema); when(ctlService.flatExportAsString(ctlSchema)).thenReturn("ClientProfileSchema"); ServerProfileSchemaDto serverProfileSchemaDto = new ServerProfileSchemaDto(); serverProfileSchemaDto.setId("1"); serverProfileSchemaDto.setCtlSchemaId("23"); CTLSchemaDto serverCtlSchema = new CTLSchemaDto(); serverCtlSchema.setId("23"); when(cacheService.getServerProfileSchemaByAppAndVersion(new AppVersionKey(APP_TOKEN, 0))).thenReturn(serverProfileSchemaDto); when(cacheService.getCtlSchemaById("23")).thenReturn(serverCtlSchema); when(ctlService.flatExportAsString(serverCtlSchema)).thenReturn("ServerProfileSchema"); Mockito.when(mockAppender.isSchemaVersionSupported(Mockito.anyInt())).thenReturn(true); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(logAppenderService, Mockito.timeout(TIMEOUT).atLeastOnce()).getLogSchema(APP_ID, 44); Mockito.verify(mockAppender, Mockito.timeout(TIMEOUT).atLeastOnce()).doAppend(Mockito.any(BaseLogEventPack.class), Mockito.any(LogDeliveryCallback.class)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(byte[].class), Mockito.any(boolean.class)); } @Test public void testUserChange() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); MessageEncoderDecoder targetCrypt = new MessageEncoderDecoder(targetPair.getPrivate(), targetPair.getPublic(), serverPair.getPublic()); EndpointProfileDto targetProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); SyncRequest targetRequest = new SyncRequest(); targetRequest.setRequestId(REQUEST_ID); targetRequest.setSyncRequestMetaData(buildSyncRequestMetaData(targetPublicKeyHash)); targetRequest.setEventSyncRequest(new EventSyncRequest()); ServerSync targetResponse = new ServerSync(); targetResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); SyncContext targetResponseHolder = new SyncContext(targetResponse); targetResponseHolder.setNotificationVersion(targetProfileMock); whenSync(AvroEncDec.convert(targetRequest), targetResponseHolder); when(targetProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(targetProfileMock.getEndpointKeyHash()).thenReturn(targetPublicKeyHash.array()); when(targetProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, targetRequest, responseBuilder, errorBuilder, targetCrypt); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()).sendUserRouteInfo(new UserRouteInfo(TENANT_ID, USER_ID)); UserRouteInfo userRouteInfo = new UserRouteInfo(TENANT_ID, USER_ID, SERVER2, RouteOperation.ADD); akkaService.getListener().onUserRouteInfo(userRouteInfo); TimeUnit.SECONDS.sleep(2); RouteTableAddress remoteAddress = new RouteTableAddress(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()), APP_TOKEN, SERVER2); RouteInfo remoteRouteInfo = new RouteInfo(TENANT_ID, USER_ID, remoteAddress, Arrays.asList(new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION))); TimeUnit.SECONDS.sleep(2); akkaService.getListener().onRouteInfo(remoteRouteInfo); RouteTableAddress localAddress = new RouteTableAddress(EndpointObjectHash.fromBytes(targetPublicKeyHash.array()), APP_TOKEN, null); RouteInfo localRouteInfo = new RouteInfo(TENANT_ID, USER_ID, localAddress, Arrays.asList(new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION))); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()).sendRouteInfo(Collections.singletonList(localRouteInfo), SERVER2); targetRequest = new SyncRequest(); targetRequest.setRequestId(REQUEST_ID); targetRequest.setSyncRequestMetaData(buildSyncRequestMetaData(targetPublicKeyHash)); targetResponse = new ServerSync(); targetResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); targetResponseHolder = new SyncContext(targetResponse); targetResponseHolder.setNotificationVersion(targetProfileMock); when(targetProfileMock.getEndpointUserId()).thenReturn(USER_ID + "2"); whenSync(AvroEncDec.convert(targetRequest), targetResponseHolder); SessionInitMessage targetMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, targetRequest, responseBuilder, errorBuilder, targetCrypt); akkaService.process(targetMessage); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()).sendUserRouteInfo(new UserRouteInfo(TENANT_ID, USER_ID + "2")); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()) .sendRouteInfo(RouteInfo.deleteRouteFromAddress(TENANT_ID, USER_ID, localAddress), SERVER2); } @Test public void testEndpointAttach() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); MessageEncoderDecoder targetCrypt = new MessageEncoderDecoder(targetPair.getPrivate(), targetPair.getPublic(), serverPair.getPublic()); EndpointProfileDto targetProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); SyncRequest targetRequest = new SyncRequest(); targetRequest.setRequestId(REQUEST_ID); targetRequest.setSyncRequestMetaData(buildSyncRequestMetaData(targetPublicKeyHash)); targetRequest.setEventSyncRequest(new EventSyncRequest()); ServerSync targetResponse = new ServerSync(); targetResponse.setRequestId(REQUEST_ID); targetResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); targetResponse.setUserSync(new UserServerSync()); SyncContext targetResponseHolder = new SyncContext(targetResponse); targetResponseHolder.setNotificationVersion(targetProfileMock); whenSync(AvroEncDec.convert(targetRequest), targetResponseHolder); when(targetProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(targetProfileMock.getEndpointKeyHash()).thenReturn(targetPublicKeyHash.array()); when(targetProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage targetMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, targetRequest, responseBuilder, errorBuilder, targetCrypt); akkaService.process(targetMessage); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()).sendUserRouteInfo(new UserRouteInfo(TENANT_ID, USER_ID)); EndpointProfileDto sourceProfileMock = Mockito.mock(EndpointProfileDto.class); SyncRequest sourceRequest = new SyncRequest(); sourceRequest.setRequestId(REQUEST_ID); sourceRequest.setSyncRequestMetaData(buildSyncRequestMetaData(clientPublicKeyHash)); sourceRequest.setEventSyncRequest(new EventSyncRequest()); UserSyncRequest userSyncRequest = new UserSyncRequest(); EndpointAttachRequest eaRequest = new EndpointAttachRequest(REQUEST_ID, "token"); userSyncRequest.setEndpointAttachRequests(Collections.singletonList(eaRequest)); sourceRequest.setUserSyncRequest(userSyncRequest); ServerSync sourceResponse = new ServerSync(); sourceResponse.setRequestId(REQUEST_ID); sourceResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); UserServerSync userSyncResponse = new UserServerSync(); userSyncResponse .setEndpointAttachResponses(Collections.singletonList(new org.kaaproject.kaa.server.sync.EndpointAttachResponse(REQUEST_ID, Base64Util.encode(targetPublicKeyHash.array()), org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS))); sourceResponse.setUserSync(userSyncResponse); SyncContext sourceResponseHolder = new SyncContext(sourceResponse); sourceResponseHolder.setNotificationVersion(sourceProfileMock); whenSync(AvroEncDec.convert(sourceRequest), sourceResponseHolder); when(sourceProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(sourceProfileMock.getEndpointKeyHash()).thenReturn(clientPublicKeyHash.array()); when(sourceProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); MessageBuilder sourceResponseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder sourceErrorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage sourceMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, sourceRequest, sourceResponseBuilder, sourceErrorBuilder); akkaService.process(sourceMessage); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); SyncResponse targetSyncResponse = new SyncResponse(); targetSyncResponse.setRequestId(REQUEST_ID); targetSyncResponse.setStatus(SyncResponseResultType.SUCCESS); targetSyncResponse.setUserSyncResponse(new UserSyncResponse()); targetSyncResponse.getUserSyncResponse() .setUserAttachNotification(new UserAttachNotification(USER_ID, Base64Util.encode(clientPublicKeyHash.array()))); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] response = responseConverter.toByteArray(targetSyncResponse); LOG.trace("Expected response {}", Arrays.toString(response)); byte[] encodedData = targetCrypt.encodeData(response); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testEndpointDetach() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); MessageEncoderDecoder targetCrypt = new MessageEncoderDecoder(targetPair.getPrivate(), targetPair.getPublic(), serverPair.getPublic()); EndpointProfileDto targetProfileMock = Mockito.mock(EndpointProfileDto.class); EventClassFamilyVersionStateDto ecfVdto = new EventClassFamilyVersionStateDto(); ecfVdto.setEcfId(ECF1_ID); ecfVdto.setVersion(ECF1_VERSION); SyncRequest targetRequest = new SyncRequest(); targetRequest.setRequestId(REQUEST_ID); targetRequest.setSyncRequestMetaData(buildSyncRequestMetaData(targetPublicKeyHash)); targetRequest.setEventSyncRequest(new EventSyncRequest()); ServerSync targetResponse = new ServerSync(); targetResponse.setRequestId(REQUEST_ID); targetResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); targetResponse.setUserSync(new UserServerSync()); SyncContext targetResponseHolder = new SyncContext(targetResponse); targetResponseHolder.setNotificationVersion(targetProfileMock); whenSync(AvroEncDec.convert(targetRequest), targetResponseHolder); when(targetProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(targetProfileMock.getEndpointKeyHash()).thenReturn(targetPublicKeyHash.array()); when(targetProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); when(cacheService.getEventClassFamilyIdByEventClassFqn(new EventClassFqnKey(TENANT_ID, FQN1))).thenReturn(ECF1_ID); RouteTableKey routeKey = new RouteTableKey(APP_TOKEN, new EventClassFamilyVersion(ECF1_ID, ECF1_VERSION)); when(cacheService.getRouteKeys(new EventClassFqnVersion(TENANT_ID, FQN1, ECF1_VERSION))) .thenReturn(Collections.singleton(routeKey)); Assert.assertNotNull(akkaService.getActorSystem()); MessageBuilder targetResponseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder targetErrorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage targetMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, targetRequest, targetResponseBuilder, targetErrorBuilder, targetCrypt); akkaService.process(targetMessage); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.verify(eventService, Mockito.timeout(TIMEOUT).atLeastOnce()).sendUserRouteInfo(new UserRouteInfo(TENANT_ID, USER_ID)); EndpointProfileDto sourceProfileMock = Mockito.mock(EndpointProfileDto.class); SyncRequest sourceRequest = new SyncRequest(); sourceRequest.setRequestId(REQUEST_ID); sourceRequest.setSyncRequestMetaData(buildSyncRequestMetaData(clientPublicKeyHash)); sourceRequest.setEventSyncRequest(new EventSyncRequest()); UserSyncRequest userSyncRequest = new UserSyncRequest(); EndpointDetachRequest eaRequest = new EndpointDetachRequest(REQUEST_ID, Base64Util.encode(targetPublicKeyHash.array())); userSyncRequest.setEndpointDetachRequests(Collections.singletonList(eaRequest)); sourceRequest.setUserSyncRequest(userSyncRequest); ServerSync sourceResponse = new ServerSync(); sourceResponse.setRequestId(REQUEST_ID); sourceResponse.setStatus(org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS); UserServerSync userSyncResponse = new UserServerSync(); userSyncResponse.setEndpointDetachResponses(Collections.singletonList( new org.kaaproject.kaa.server.sync.EndpointDetachResponse(REQUEST_ID, org.kaaproject.kaa.server.sync.SyncStatus.SUCCESS))); sourceResponse.setUserSync(userSyncResponse); SyncContext sourceResponseHolder = new SyncContext(sourceResponse); sourceResponseHolder.setNotificationVersion(sourceProfileMock); whenSync(AvroEncDec.convert(sourceRequest), sourceResponseHolder); when(sourceProfileMock.getEndpointUserId()).thenReturn(USER_ID); when(sourceProfileMock.getEndpointKeyHash()).thenReturn(clientPublicKeyHash.array()); when(sourceProfileMock.getEcfVersionStates()).thenReturn(Arrays.asList(ecfVdto)); MessageBuilder sourceResponseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder sourceErrorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage sourceMessage = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, sourceRequest, sourceResponseBuilder, sourceErrorBuilder); akkaService.process(sourceMessage); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); SyncResponse targetSyncResponse = new SyncResponse(); targetSyncResponse.setRequestId(REQUEST_ID); targetSyncResponse.setStatus(SyncResponseResultType.SUCCESS); targetSyncResponse.setUserSyncResponse(new UserSyncResponse()); targetSyncResponse.getUserSyncResponse() .setUserDetachNotification(new UserDetachNotification(Base64Util.encode(clientPublicKeyHash.array()))); AvroByteArrayConverter<SyncResponse> responseConverter = new AvroByteArrayConverter<>(SyncResponse.class); byte[] response = responseConverter.toByteArray(targetSyncResponse); byte[] encodedData = targetCrypt.encodeData(response); Mockito.verify(targetResponseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(encodedData, true); } @Test public void testNoEndpointCredentialsSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); SyncContext holder = simpleResponse; Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(holder); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); Mockito.when(registrationService.findEndpointRegistrationByCredentialsId(Mockito.anyString())).thenReturn(Optional.ofNullable((EndpointRegistrationDto) null)); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(EndpointVerificationException.class)); } // TODO: fix when server profile feature will be ready // @Test // public void testServerProfileUpdate() throws Exception { // ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); // // SyncRequest request = new SyncRequest(); // request.setRequestId(REQUEST_ID); // SyncRequestMetaData md = buildSyncRequestMetaData(); // request.setSyncRequestMetaData(md); // // ConfigurationSyncRequest csRequest = new ConfigurationSyncRequest(); // request.setConfigurationSyncRequest(csRequest); // // Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))).thenReturn( // clientPair.getPublic()); // whenSync(deltaResponseWithProfile); // // MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); // ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); // // SessionInitMessage message = toSignedRequest(UUID.randomUUID(), // ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, // responseBuilder, errorBuilder); // Assert.assertNotNull(akkaService.getActorSystem()); // akkaService.process(message); // // Mockito.verify(operationsService, // Mockito.timeout(TIMEOUT).atLeastOnce()).syncProfile(Mockito.any(SyncContext.class), // Mockito.any(ProfileClientSync.class)); // // Notification thriftNotification = new Notification(); // thriftNotification.setAppId(APP_ID); // thriftNotification.setOp(Operation.UPDATE_SERVER_PROFILE); // thriftNotification.setKeyHash(clientPublicKeyHash); // akkaService.onNotification(thriftNotification); // // Mockito.verify(operationsService, // Mockito.timeout(TIMEOUT*100).atLeastOnce()) // .refreshServerEndpointProfile(EndpointObjectHash.fromBytes(clientPublicKeyHash.array())); // } //TODO: Implement tests that cover endpoint verification logic. @Test public void testRevokedEndpointCredentialsSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); SyncContext holder = simpleResponse; Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(holder); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); Mockito.when(registrationService.findEndpointRegistrationByCredentialsId(Mockito.anyString())).thenReturn(Optional.ofNullable((EndpointRegistrationDto) null)); Mockito.when(credentialsService.lookupCredentials(Mockito.anyString())).thenReturn(Optional.of(new CredentialsDto(new byte[]{}, CredentialsStatus.REVOKED))); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(EndpointVerificationException.class)); } @Test public void testInUseEndpointCredentialsSyncRequest() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(clientPublicKeyHash); md.setProfileHash(clientPublicKeyHash); request.setSyncRequestMetaData(md); SyncContext holder = simpleResponse; Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(holder); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); Mockito.when(registrationService.findEndpointRegistrationByCredentialsId(Mockito.anyString())).thenReturn(Optional.ofNullable((EndpointRegistrationDto) null)); Mockito.when(credentialsService.lookupCredentials(Mockito.anyString())).thenReturn(Optional.of(new CredentialsDto(new byte[]{}, CredentialsStatus.IN_USE))); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(EndpointVerificationException.class)); } @Test public void testLongSyncRevocation() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = buildSyncRequestMetaData(); request.setSyncRequestMetaData(md); ConfigurationSyncRequest csRequest = new ConfigurationSyncRequest(); csRequest.setConfigurationHash(ByteBuffer.wrap(new byte[]{})); csRequest.setResyncOnly(true); request.setConfigurationSyncRequest(csRequest); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(noDeltaResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(Mockito.any(SyncContext.class), Mockito.any(ProfileClientSync.class)); Mockito.when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); whenSync(deltaResponse); EndpointAddress address = new EndpointAddress(applicationDto.getTenantId(), applicationDto.getApplicationToken(), EndpointObjectHash.fromBytes(clientPublicKeyHash.array())); ActorClassifier classifier = ActorClassifier.APPLICATION; clusterServiceListener.onEndpointActorMsg(new ThriftEndpointActorMsg<ThriftEndpointDeregistrationMessage>( address, classifier, new ThriftEndpointDeregistrationMessage())); Mockito.verify(errorBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(Mockito.any(EndpointRevocationException.class)); } @Test public void testEndpointConfigurationRefresh() throws Exception { ChannelContext channelContextMock = Mockito.mock(ChannelContext.class); EndpointProfileDto profileDto = new EndpointProfileDto(); SyncRequest request = new SyncRequest(); request.setRequestId(REQUEST_ID); SyncRequestMetaData md = buildSyncRequestMetaData(); request.setSyncRequestMetaData(md); ConfigurationSyncRequest csRequest = new ConfigurationSyncRequest(); csRequest.setConfigurationHash(ByteBuffer.wrap("hash".getBytes())); request.setConfigurationSyncRequest(csRequest); Mockito.when(cacheService.getEndpointKey(EndpointObjectHash.fromBytes(clientPublicKeyHash.array()))) .thenReturn(clientPair.getPublic()); whenSync(noDeltaResponse); MessageBuilder responseBuilder = Mockito.mock(MessageBuilder.class); ErrorBuilder errorBuilder = Mockito.mock(ErrorBuilder.class); SessionInitMessage message = toSignedRequest(UUID.randomUUID(), ChannelType.SYNC_WITH_TIMEOUT, channelContextMock, request, responseBuilder, errorBuilder); Assert.assertNotNull(akkaService.getActorSystem()); akkaService.process(message); Mockito.verify(operationsService, Mockito.timeout(TIMEOUT).atLeastOnce()).syncClientProfile(any(SyncContext.class), any(ProfileClientSync.class)); byte[] epsConfHash = "hash2".getBytes(); whenSync(deltaResponse); Mockito.when(applicationService.findAppById(APP_ID)).thenReturn(applicationDto); Mockito.when(operationsService.fetchEndpointSpecificConfigurationHash(any(EndpointProfileDto.class))).thenReturn(epsConfHash); Mockito.when(operationsService.refreshServerEndpointProfile(any(EndpointObjectHash.class))).thenReturn(profileDto); EndpointAddress address = new EndpointAddress(applicationDto.getTenantId(), applicationDto.getApplicationToken(), EndpointObjectHash.fromBytes(clientPublicKeyHash.array())); ActorClassifier classifier = ActorClassifier.GLOBAL; ThriftEndpointConfigurationRefreshMessage msg = new ThriftEndpointConfigurationRefreshMessage(null, null); clusterServiceListener.onEndpointActorMsg(new ThriftEndpointActorMsg<>(address, classifier, msg)); Mockito.verify(responseBuilder, Mockito.timeout(TIMEOUT).atLeastOnce()).build(any(byte[].class), any(boolean.class)); Mockito.verify(operationsService).syncConfigurationHashes(any(SyncContext.class), isNull(byte[].class), eq(epsConfHash)); } private SyncRequestMetaData buildSyncRequestMetaData() { return buildSyncRequestMetaData(clientPublicKeyHash); } private SyncRequestMetaData buildSyncRequestMetaData(ByteBuffer keyHash) { SyncRequestMetaData md = new SyncRequestMetaData(); md.setSdkToken(SDK_TOKEN); md.setEndpointPublicKeyHash(keyHash); md.setProfileHash(keyHash); md.setTimeout(2l * TIMEOUT); return md; } private static class TestActor extends UntypedActor { private Object msg; @Override public void onReceive(Object msg) throws Exception { this.msg = (Object) msg; } public Object getMsg() { return msg; } } }