/*
* 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.common.nosql.mongo.dao;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kaaproject.kaa.common.dto.EndpointGroupDto;
import org.kaaproject.kaa.common.dto.EndpointGroupStateDto;
import org.kaaproject.kaa.common.dto.EndpointProfileBodyDto;
import org.kaaproject.kaa.common.dto.EndpointProfileDto;
import org.kaaproject.kaa.common.dto.EndpointProfilesBodyDto;
import org.kaaproject.kaa.common.dto.EndpointProfilesPageDto;
import org.kaaproject.kaa.common.dto.PageLinkDto;
import org.kaaproject.kaa.server.common.dao.exception.KaaOptimisticLockingFailureException;
import org.kaaproject.kaa.server.common.dao.model.EndpointProfile;
import org.kaaproject.kaa.server.common.nosql.mongo.dao.model.MongoEndpointProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/mongo-dao-test-context.xml")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class EndpointProfileMongoDaoTest extends AbstractMongoTest {
private static final Logger LOG = LoggerFactory.getLogger(EndpointProfileMongoDaoTest.class);
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(10);
private static final String TEST_ENDPOINT_GROUP_ID = "124";
private static final String TEST_LIMIT = "3";
private static final String TEST_OFFSET = "0";
private static final int GENERATED_PROFILES_COUNT = 5;
@BeforeClass
public static void init() throws Exception {
MongoDBTestRunner.setUp();
}
@AfterClass
public static void after() throws Exception {
MongoDBTestRunner.tearDown();
}
@After
public void afterTest() throws IOException {
MongoDataLoader.clearDBData();
clearDBData();
}
@Test
public void testFindByKeyHash() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
Assert.assertNotNull(endpointProfile);
MongoEndpointProfile found = endpointProfileDao.findByKeyHash(endpointProfile.getEndpointKeyHash());
Assert.assertNotNull(found);
Assert.assertEquals(endpointProfile, found.toDto());
}
@Test
public void findBodyByKeyHashTest() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
Assert.assertNotNull(endpointProfile);
EndpointProfileBodyDto found = endpointProfileDao.findBodyByKeyHash(endpointProfile.getEndpointKeyHash());
Assert.assertNotNull(found);
Assert.assertEquals(endpointProfile.getClientProfileBody(), found.getClientSideProfile());
Assert.assertEquals(endpointProfile.getServerProfileBody(), found.getServerSideProfile());
}
@Test
public void findBodyByEndpointGroupIdTest() {
for (int i = 0; i < GENERATED_PROFILES_COUNT; i++) {
generateEndpointProfileWithGroupIdDto(TEST_ENDPOINT_GROUP_ID);
}
int lim = Integer.valueOf(TEST_LIMIT);
PageLinkDto pageLink = new PageLinkDto(TEST_ENDPOINT_GROUP_ID, TEST_LIMIT, TEST_OFFSET);
EndpointProfilesBodyDto found = endpointProfileDao.findBodyByEndpointGroupId(pageLink);
Assert.assertFalse(found.getEndpointProfilesBody().isEmpty());
Assert.assertEquals(lim, found.getEndpointProfilesBody().size());
}
@Test
public void findBodyByEndpointGroupIdWithNfGroupStateTest() {
for (int i = 0; i < GENERATED_PROFILES_COUNT; i++) {
generateEndpointProfileWithGroupIdDto(TEST_ENDPOINT_GROUP_ID);
}
int lim = Integer.valueOf(TEST_LIMIT);
PageLinkDto pageLink = new PageLinkDto(TEST_ENDPOINT_GROUP_ID, TEST_LIMIT, TEST_OFFSET);
EndpointProfilesBodyDto found = endpointProfileDao.findBodyByEndpointGroupId(pageLink);
Assert.assertFalse(found.getEndpointProfilesBody().isEmpty());
Assert.assertEquals(lim, found.getEndpointProfilesBody().size());
}
@Test
public void findByEndpointGroupIdTest() {
for (int i = 0; i < GENERATED_PROFILES_COUNT; i++) {
generateEndpointProfileWithGroupIdDto(TEST_ENDPOINT_GROUP_ID);
}
int lim = Integer.valueOf(TEST_LIMIT);
PageLinkDto pageLink = new PageLinkDto(TEST_ENDPOINT_GROUP_ID, TEST_LIMIT, TEST_OFFSET);
EndpointProfilesPageDto found = endpointProfileDao.findByEndpointGroupId(pageLink);
Assert.assertFalse(found.getEndpointProfiles().isEmpty());
Assert.assertEquals(lim, found.getEndpointProfiles().size());
}
@Test
public void findByEndpointGroupIdWithNfGroupStateTest() {
for (int i = 0; i < GENERATED_PROFILES_COUNT; i++) {
generateEndpointProfileWithGroupIdDto(TEST_ENDPOINT_GROUP_ID);
}
int lim = Integer.valueOf(TEST_LIMIT);
PageLinkDto pageLink = new PageLinkDto(TEST_ENDPOINT_GROUP_ID, TEST_LIMIT, TEST_OFFSET);
EndpointProfilesPageDto found = endpointProfileDao.findByEndpointGroupId(pageLink);
Assert.assertFalse(found.getEndpointProfiles().isEmpty());
Assert.assertEquals(lim, found.getEndpointProfiles().size());
}
@Test
public void testFindById() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
MongoEndpointProfile profile = endpointProfileDao.findById(ByteBuffer.wrap(endpointProfile.getEndpointKeyHash()));
Assert.assertNotNull(profile);
}
@Test
public void testRemoveByKeyHash() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
Assert.assertNotNull(endpointProfile);
endpointProfileDao.removeByKeyHash(endpointProfile.getEndpointKeyHash());
MongoEndpointProfile profile = endpointProfileDao.findByKeyHash(endpointProfile.getEndpointKeyHash());
Assert.assertNull(profile);
}
@Test
public void removeByIdTest() {
EndpointProfileDto epDto = generateEndpointProfileDto(null, null);
Assert.assertNotNull(epDto);
endpointProfileDao.removeById(ByteBuffer.wrap(epDto.getEndpointKeyHash()));
MongoEndpointProfile endpointProfile = endpointProfileDao.findById(ByteBuffer.wrap(epDto.getEndpointKeyHash()));
Assert.assertNull(endpointProfile);
}
@Test
public void saveEndpointProfileTest() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
Assert.assertNotNull(endpointProfile);
endpointProfile.setId(null);
endpointProfile.setVersion(null);
MongoEndpointProfile saved = endpointProfileDao.save(new MongoEndpointProfile(endpointProfile));
Assert.assertNotNull(saved);
Assert.assertEquals(endpointProfile, saved.toDto());
}
@Test
public void convertToDtoTest() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
endpointProfile.setAccessToken("Trololo");
endpointProfileDao.save(endpointProfile);
Assert.assertNotNull(endpointProfile);
MongoEndpointProfile converted = new MongoEndpointProfile(endpointProfile);
Assert.assertEquals(endpointProfile, converted.toDto());
}
@Test
public void testFindEndpointIdByKeyHash() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
Assert.assertNotNull(endpointProfile);
EndpointProfile ep = endpointProfileDao.findEndpointIdByKeyHash(endpointProfile.getEndpointKeyHash());
Assert.assertEquals(endpointProfile.getId(), ep.getId());
Assert.assertNull(endpointProfile.getEndpointKey());
Assert.assertNull(ep.getEndpointKey());
Assert.assertNull(ep.getEndpointUserId());
Assert.assertNull(ep.getSubscriptions());
}
@Test
public void removeByAppId() {
EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
Assert.assertNotNull(endpointProfile);
byte[] keyHash = endpointProfile.getEndpointKeyHash();
endpointProfileDao.removeByAppId(endpointProfile.getApplicationId());
MongoEndpointProfile found = endpointProfileDao.findByKeyHash(keyHash);
Assert.assertNull(found);
}
@Test
public void testUpdate() throws Exception {
List<EndpointGroupStateDto> cfGroupStateSave = new ArrayList<EndpointGroupStateDto>();
List<EndpointGroupStateDto> cfGroupStateUpdate = new ArrayList<EndpointGroupStateDto>();
PageLinkDto pageLink;
EndpointProfilesPageDto found;
EndpointGroupDto endpointGroupDto = new EndpointGroupDto();
endpointGroupDto.setWeight(1);
cfGroupStateSave.add(new EndpointGroupStateDto("111", null, null));
cfGroupStateSave.add(new EndpointGroupStateDto("222", null, null));
cfGroupStateSave.add(new EndpointGroupStateDto("333", null, null));
EndpointProfileDto endpointProfileSave = generateEndpointProfileForTestUpdate(null, "TEST_KEY_HASH".getBytes(), cfGroupStateSave);
EndpointProfile saved = endpointProfileDao.save(endpointProfileSave);
cfGroupStateUpdate.add(new EndpointGroupStateDto("111", null, null));
cfGroupStateUpdate.add(new EndpointGroupStateDto("444", null, null));
EndpointProfileDto endpointProfileUpdate = generateEndpointProfileForTestUpdate(saved.getId(), "TEST_KEY_HASH".getBytes(), cfGroupStateUpdate);
endpointProfileUpdate.setVersion(saved.getVersion());
endpointProfileDao.save(endpointProfileUpdate);
String limit = "10";
String offset = "0";
String[] endpointGroupId = {"111", "444", "222", "333"};
for (int i = 0; i < 2; i++) {
pageLink = new PageLinkDto(endpointGroupId[i], limit, offset);
found = endpointProfileDao.findByEndpointGroupId(pageLink);
Assert.assertFalse(found.getEndpointProfiles().isEmpty());
}
for (int i = 2; i < 4; i++) {
pageLink = new PageLinkDto(endpointGroupId[i], limit, offset);
found = endpointProfileDao.findByEndpointGroupId(pageLink);
Assert.assertTrue(found.getEndpointProfiles().isEmpty());
}
}
protected EndpointProfileDto generateEndpointProfileForTestUpdate(String id, byte[] keyHash, List<EndpointGroupStateDto> groupState) {
EndpointProfileDto profileDto = new EndpointProfileDto();
profileDto.setId(id);
profileDto.setApplicationId(generateStringId());
profileDto.setEndpointKeyHash(keyHash);
profileDto.setAccessToken(generateStringId());
profileDto.setGroupState(groupState);
profileDto.setSdkToken(UUID.randomUUID().toString());
return profileDto;
}
protected String generateStringId() {
return UUID.randomUUID().toString();
}
@Test(expected = KaaOptimisticLockingFailureException.class)
public void testOptimisticLockWithConcurrency() throws Throwable {
final EndpointProfileDto endpointProfile = generateEndpointProfileDto(null, null);
List<Future<?>> tasks = new ArrayList<>();
for (int i = 0; i < 100; i++) {
final int id = i;
tasks.add(EXECUTOR.submit(new Runnable() {
@Override
public void run() {
try {
MongoEndpointProfile ep = new MongoEndpointProfile(endpointProfile);
ep.setEndpointUserId("Ololo " + id);
endpointProfileDao.save(ep.toDto());
} catch (KaaOptimisticLockingFailureException ex) {
LOG.error("Catch optimistic exception.");
throw ex;
}
}
}));
}
for (Future future : tasks) {
try {
future.get();
} catch (ExecutionException ex) {
throw ex.getCause();
}
}
}
}