/* * 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.delta; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import org.apache.avro.Schema; import org.apache.avro.generic.GenericContainer; import org.apache.avro.generic.GenericRecord; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.kaaproject.kaa.common.avro.GenericAvroConverter; import org.kaaproject.kaa.common.dto.ApplicationDto; import org.kaaproject.kaa.common.dto.ConfigurationDto; import org.kaaproject.kaa.common.dto.ConfigurationSchemaDto; import org.kaaproject.kaa.common.dto.EndpointConfigurationDto; import org.kaaproject.kaa.common.dto.EndpointGroupDto; import org.kaaproject.kaa.common.dto.EndpointGroupStateDto; import org.kaaproject.kaa.common.dto.EndpointProfileDto; import org.kaaproject.kaa.common.dto.EndpointProfileSchemaDto; import org.kaaproject.kaa.common.dto.ProfileFilterDto; import org.kaaproject.kaa.common.dto.TenantDto; import org.kaaproject.kaa.common.dto.ctl.CTLSchemaDto; import org.kaaproject.kaa.common.dto.ctl.CtlSchemaMetaInfoDto; import org.kaaproject.kaa.common.endpoint.gen.BasicEndpointProfile; import org.kaaproject.kaa.common.hash.EndpointObjectHash; import org.kaaproject.kaa.server.common.core.algorithms.delta.DeltaCalculatorException; import org.kaaproject.kaa.server.common.dao.AbstractTest; import org.kaaproject.kaa.server.common.dao.exception.IncorrectParameterException; import org.kaaproject.kaa.server.common.nosql.mongo.dao.MongoDBTestRunner; import org.kaaproject.kaa.server.control.service.exception.ControlServiceException; import org.kaaproject.kaa.server.operations.pojo.GetDeltaRequest; import org.kaaproject.kaa.server.operations.pojo.GetDeltaResponse; import org.kaaproject.kaa.server.operations.service.OperationsServiceIT; import org.kaaproject.kaa.server.operations.service.cache.CacheService; import org.kaaproject.kaa.server.operations.service.cache.ConfigurationCacheEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.Base64Utils; import javax.transaction.Transactional; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/operations/common-test-context.xml") @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) @Transactional public class DeltaServiceIT extends AbstractTest { protected static final Logger LOG = LoggerFactory.getLogger(DeltaServiceIT.class); private static final Charset UTF_8 = Charset.forName("UTF-8"); private static final int PROFILE_VERSION = 1; private static final int PROFILE_SCHEMA_VERSION = 1; private static final int OLD_ENDPOINT_SEQ_NUMBER = 0; private static final int NEW_APPLICATION_SEQ_NUMBER = 6; private static final int MAJOR_VERSION = 1; private static final int CONF_SCHEMA_VERSION = 2; private static final String CUSTOMER_ID = "CustomerId"; private static final String APPLICATION_ID = "ApplicationId"; private static final String APPLICATION_NAME = "ApplicationName"; private static final GenericAvroConverter<GenericRecord> avroConverter = new GenericAvroConverter<>(BasicEndpointProfile.SCHEMA$); private static final BasicEndpointProfile ENDPOINT_PROFILE = new BasicEndpointProfile("dummy profile 1"); private static final byte[] ENDPOINT_KEY = "EndpointKey".getBytes(UTF_8); private static byte[] PROFILE_BYTES; private static String PROFILE_JSON; private static String APP_TOKEN; @Autowired protected DeltaService deltaService; @Autowired protected CacheService cacheService; private TenantDto tenant; private ApplicationDto application; private EndpointProfileSchemaDto profileSchema; private ProfileFilterDto profileFilter; private EndpointProfileDto endpointProfile; private EndpointConfigurationDto endpointConfiguration; private byte[] endpointConfigurationBytes; private ConfigurationSchemaDto confSchema; private String egAllId; private String pfAllId; private String cfAllId; @BeforeClass public static void init() throws Exception { MongoDBTestRunner.setUp(); } @AfterClass public static void after() throws Exception { MongoDBTestRunner.getDB().dropDatabase(); MongoDBTestRunner.tearDown(); } @Before public void beforeTest() throws IOException, DeltaCalculatorException, ControlServiceException { String dataSchema = OperationsServiceIT.getResourceAsString(OperationsServiceIT.DATA_SCHEMA_LOCATION); PROFILE_BYTES = avroConverter.encode(ENDPOINT_PROFILE); PROFILE_JSON = avroConverter.encodeToJson(ENDPOINT_PROFILE); tenant = new TenantDto(); tenant.setName(CUSTOMER_ID); tenant = userService.saveTenant(tenant); assertNotNull(tenant); assertNotNull(tenant.getId()); ApplicationDto applicationDto = new ApplicationDto(); applicationDto.setTenantId(tenant.getId()); applicationDto.setApplicationToken(APPLICATION_ID); applicationDto.setName(APPLICATION_NAME); applicationDto.setSequenceNumber(NEW_APPLICATION_SEQ_NUMBER); applicationDto = applicationService.saveApp(applicationDto); APP_TOKEN = applicationDto.getApplicationToken(); assertNotNull(applicationDto); assertNotNull(applicationDto.getId()); application = applicationService.findAppById(applicationDto.getId()); EndpointGroupDto groupAll = endpointService.findEndpointGroupsByAppId(application.getId()).get(0); CTLSchemaDto profileCtlSchema = new CTLSchemaDto(); CtlSchemaMetaInfoDto metaInfo = new CtlSchemaMetaInfoDto(BasicEndpointProfile.SCHEMA$.getFullName(), application.getTenantId(), application.getId()); profileCtlSchema.setMetaInfo(metaInfo); profileCtlSchema.setBody(BasicEndpointProfile.SCHEMA$.toString()); profileCtlSchema.setVersion(1); profileCtlSchema.setDependencySet(new HashSet<CTLSchemaDto>()); profileCtlSchema = ctlService.saveCtlSchema(profileCtlSchema); Schema schema = new Schema.Parser().parse(dataSchema); CTLSchemaDto confCtlSchema = new CTLSchemaDto(); CtlSchemaMetaInfoDto confMetaInfo = new CtlSchemaMetaInfoDto(schema.getFullName(), application.getTenantId(), application.getId()); confCtlSchema.setMetaInfo(confMetaInfo); confCtlSchema.setBody(schema.toString()); confCtlSchema.setVersion(CONF_SCHEMA_VERSION); confCtlSchema.setDependencySet(new HashSet<CTLSchemaDto>()); confCtlSchema = ctlService.saveCtlSchema(confCtlSchema); EndpointProfileSchemaDto profileSchemaObj = new EndpointProfileSchemaDto(); profileSchemaObj.setVersion(PROFILE_SCHEMA_VERSION); profileSchemaObj.setCtlSchemaId(profileCtlSchema.getId()); profileSchemaObj.setApplicationId(application.getId()); EndpointProfileSchemaDto profileSchemaDto = profileService.saveProfileSchema(profileSchemaObj); profileSchema = profileService.findProfileSchemaById(profileSchemaDto.getId()); EndpointGroupDto endpointGroup = new EndpointGroupDto(); endpointGroup.setApplicationId(application.getId()); endpointGroup.setName("Test group"); endpointGroup.setWeight(277); endpointGroup.setDescription("Test Description"); endpointGroup = endpointService.saveEndpointGroup(endpointGroup); ProfileFilterDto profileFilterObj = new ProfileFilterDto(); profileFilterObj.setApplicationId(application.getId()); profileFilterObj.setEndpointGroupId(endpointGroup.getId()); profileFilterObj.setBody("profileBody.contains(\"dummy\")"); profileFilterObj.setEndpointProfileSchemaId(profileSchema.getId()); profileFilter = profileService.saveProfileFilter(profileFilterObj); profileService.activateProfileFilter(profileFilter.getId(), null); confSchema = new ConfigurationSchemaDto(); confSchema.setApplicationId(application.getId()); confSchema.setVersion(CONF_SCHEMA_VERSION); confSchema.setCtlSchemaId(confCtlSchema.getId()); try { confSchema = configurationService.saveConfSchema(confSchema); } catch (IncorrectParameterException e) { Assert.fail("Can't generate schemas"); } Assert.assertNotNull(confSchema); Assert.assertNotNull(confSchema.getId()); egAllId = groupAll.getId(); pfAllId = profileFilter.getId(); ConfigurationDto confDto = configurationService.findConfigurationByEndpointGroupIdAndVersion(egAllId, CONF_SCHEMA_VERSION); cfAllId = confDto.getId(); endpointConfiguration = new EndpointConfigurationDto(); endpointConfiguration.setConfiguration(confDto.getBody().getBytes(UTF_8)); endpointConfiguration.setConfigurationHash(EndpointObjectHash.fromSha1(confDto.getBody()).getData()); endpointConfiguration = endpointService.saveEndpointConfiguration(endpointConfiguration); assertNotNull(endpointConfiguration); EndpointGroupStateDto egs = new EndpointGroupStateDto(); egs.setConfigurationId(cfAllId); egs.setEndpointGroupId(egAllId); egs.setProfileFilterId(pfAllId); endpointProfile = new EndpointProfileDto(); endpointProfile.setApplicationId(application.getId()); endpointProfile.setEndpointKeyHash(Base64Utils.decodeFromString("EndpointId")); endpointProfile.setClientProfileBody(PROFILE_JSON); endpointProfile.setProfileHash(EndpointObjectHash.fromSha1(PROFILE_BYTES).getData()); endpointProfile.setConfigurationHash(endpointConfiguration.getConfigurationHash()); endpointProfile.setConfigurationVersion(CONF_SCHEMA_VERSION); endpointProfile.setClientProfileVersion(PROFILE_VERSION); endpointProfile.setGroupState(Collections.singletonList(egs)); endpointProfile = endpointService.saveEndpointProfile(endpointProfile); assertNotNull(endpointProfile); assertNotNull(endpointProfile.getId()); } @After public void afterTest() { MongoDBTestRunner.getDB().dropDatabase(); } @Test public void testDeltaServiceNoHistoryDelta() throws Exception { GetDeltaRequest request = new GetDeltaRequest(application.getApplicationToken(), EndpointObjectHash.fromSha1(endpointConfiguration .getConfiguration()), true); request.setEndpointProfile(endpointProfile); GetDeltaResponse response = deltaService.getDelta(request); assertNotNull(response); assertEquals(GetDeltaResponse.GetDeltaResponseType.NO_DELTA, response.getResponseType()); assertNull(response.getDelta()); assertNull(response.getConfSchema()); } @Test public void testDeltaServiceFirstRequest() throws Exception { GetDeltaRequest request = new GetDeltaRequest(application.getApplicationToken()); request.setEndpointProfile(endpointProfile); GetDeltaResponse response = deltaService.getDelta(request); assertNotNull(response); assertEquals(GetDeltaResponse.GetDeltaResponseType.CONF_RESYNC, response.getResponseType()); assertNotNull(response.getDelta()); endpointConfigurationBytes = response.getDelta().getData(); assertNotNull(endpointConfigurationBytes); } @Test public void testDeltaServiceHashMismatch() throws Exception { GetDeltaRequest request = new GetDeltaRequest(application.getApplicationToken(), EndpointObjectHash.fromBytes(new byte[]{1, 2, 3})); request.setEndpointProfile(endpointProfile); GetDeltaResponse response = deltaService.getDelta(request); assertNotNull(response); assertEquals(GetDeltaResponse.GetDeltaResponseType.CONF_RESYNC, response.getResponseType()); assertNotNull(response.getDelta()); endpointConfigurationBytes = response.getDelta().getData(); assertNotNull(endpointConfigurationBytes); } @Test public void testDeltaServiceSecondRequest() throws Exception { ConfigurationCacheEntry cacheEntry = deltaService.getConfiguration(APP_TOKEN, "EndpointId", endpointProfile); assertNotNull(cacheEntry); assertNotNull(cacheEntry.getConfiguration()); assertNotNull(cacheEntry.getDelta()); assertNotNull(cacheEntry.getHash()); assertNull(cacheEntry.getUserConfigurationHash()); GenericAvroConverter<GenericContainer> newConfConverter = new GenericAvroConverter<>(new Schema.Parser().parse(confSchema .getBaseSchema())); GenericContainer container = newConfConverter.decodeJson(OperationsServiceIT .getResourceAsString(OperationsServiceIT.BASE_DATA_UPDATED_LOCATION)); byte[] newConfData = newConfConverter.encodeToJsonBytes(container); ConfigurationDto newConfDto = new ConfigurationDto(); newConfDto.setEndpointGroupId(egAllId); newConfDto.setSchemaId(confSchema.getId()); newConfDto.setBody(new String(newConfData, UTF_8)); newConfDto = configurationService.saveConfiguration(newConfDto); configurationService.activateConfiguration(newConfDto.getId(), "test"); List<EndpointGroupStateDto> changes = new ArrayList<>(); changes.add(new EndpointGroupStateDto(egAllId, pfAllId, newConfDto.getId())); endpointProfile.setGroupState(changes); ConfigurationCacheEntry newCacheEntry = deltaService.getConfiguration(APP_TOKEN, "EndpointId", endpointProfile); assertNotNull(newCacheEntry); assertNotNull(newCacheEntry.getConfiguration()); assertNotNull(newCacheEntry.getDelta()); assertNotNull(newCacheEntry.getHash()); assertNull(newCacheEntry.getUserConfigurationHash()); assertNotEquals(cacheEntry.getHash(), newCacheEntry.getHash()); } }