/**
* Copyright (C) 2011 JTalks.org Team
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jtalks.jcommune.model.dao.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.jtalks.common.model.entity.Group;
import org.jtalks.common.model.entity.Section;
import org.jtalks.jcommune.model.dao.GroupDao;
import org.jtalks.jcommune.model.dto.GroupAdministrationDto;
import org.jtalks.jcommune.model.entity.Branch;
import org.jtalks.jcommune.model.entity.JCUser;
import org.jtalks.jcommune.model.entity.ObjectsFactory;
import org.jtalks.jcommune.model.entity.PersistedObjectsFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.annotation.Nonnull;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.text.Collator;
import java.text.ParseException;
import java.text.RuleBasedCollator;
import java.util.*;
import static io.qala.datagen.RandomShortApi.alphanumeric;
import static io.qala.datagen.RandomValue.between;
import static org.testng.Assert.*;
import static org.unitils.reflectionassert.ReflectionAssert.assertReflectionEquals;
/**
* @author Leonid Kazancev
*/
@ContextConfiguration(locations = {"classpath:/org/jtalks/jcommune/model/entity/applicationContext-dao.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public class GroupHibernateDaoTest extends AbstractTransactionalTestNGSpringContextTests {
static final String NO_FILTER = "";
private static final String SORTING_TEST_RULES =
"< A< a< B< b< C< c< D< d< E< e< F< f< G< g< " +
"H< h< I< i< J< j< K< k< L< l< M< m< " +
"N< n< O< o< P< p< Q< q< R< r< S< s< " +
"T< t< U< u< V< v< W< w< X< x< Y< y< Z< z< " +
"А< а< Б< б< В< в< Г< г< Д< д< Е< е< " +
"Ё< ё< Ж< ж< З< з< И< и< Й< й< К< к< " +
"Л< л< М< м< Н< н< О< о< П< п< Р< р< " +
"С< с< Т< т< У< у< Ф< ф< Х< х< Ц< ц< " +
"Ч< ч< Ш< ш< Щ< щ< Ь< ь< Ы< ы< Ъ< ъ< " +
"Э< э< Ю< ю< Я< я";
private static final String DICTIONARY_RU = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ" +
"абвгдеёжзийклмнопрстуфхцчшщьыъэюя" +
"0123456789";
private static final int MIN_GROUP_NAME_LENGTH = 1;
private static final int MAX_GROUP_NAME_LENGTH = Group.GROUP_NAME_MAX_LENGTH;
@Autowired
private GroupDao groupDao;
@Autowired
private SessionFactory sessionFactory;
private Session session;
@Resource(lookup = "org/jtalks/jcommune/model/datasource.properties")
private DataSource dataSource;
@BeforeMethod
public void setUp() throws Exception {
session = sessionFactory.getCurrentSession();
PersistedObjectsFactory.setSession(session);
}
@Test
public void testSave() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
Group savedGroup = (Group) session.get(Group.class, group.getId());
assertReflectionEquals(group, savedGroup);
}
@Test
public void testSaveIdGeneration() {
Group group = ObjectsFactory.getRandomGroup();
long initialId = 0;
group.setId(initialId);
saveAndEvict(group);
assertNotSame(group.getId(), initialId, "ID is not created");
}
@Test
public void testGetById() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
Group actual = groupDao.get(group.getId());
assertReflectionEquals(actual, group);
}
@Test
public void testGetAll() {
Group group0 = ObjectsFactory.getRandomGroup();
saveAndEvict(group0);
Group group1 = ObjectsFactory.getRandomGroup();
saveAndEvict(group1);
List<Group> actual = groupDao.getAll();
sortById(actual);
assertEquals(actual.size(), 2);
assertReflectionEquals(actual.get(0), group0);
assertReflectionEquals(actual.get(1), group1);
}
private void sortById(List<Group> groups) {
Collections.sort(groups, new Comparator<Group>() {
@Override
public int compare(@Nonnull Group group, @Nonnull Group group1) {
return Long.compare(group.getId(), group1.getId());
}
});
}
@Test
public void testGetByNameContains() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
List<Group> actual = groupDao.getMatchedByName(group.getName());
assertEquals(actual.size(), 1);
assertReflectionEquals(actual.get(0), group);
}
@Test
public void testGetByNameContainsWithEmptyName() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
List<Group> actual = groupDao.getMatchedByName(NO_FILTER);
List<Group> all = groupDao.getAll();
assertEquals(actual, all);
}
@Test
public void testGetByName() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
Group actual = groupDao.getGroupByName(group.getName());
assertReflectionEquals(actual, group);
}
@Test
public void testGetByNameFailWithEmptyString() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
Group actual = groupDao.getGroupByName(NO_FILTER);
assertNull(actual);
}
@Test
public void testGetByNameLowerCase() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
Group actual = groupDao.getGroupByName(group.getName().toLowerCase());
assertReflectionEquals(actual, group);
}
@Test
public void testGetByNameUpperCase() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
Group actual = groupDao.getGroupByName(group.getName().toUpperCase());
assertReflectionEquals(actual, group);
}
@Test
public void testGetByNameWithSpecialChars() {
Group group = ObjectsFactory.getRandomGroup();
group.setName("!@#$%^&*()\"\'\\/");
saveAndEvict(group);
Group actual = groupDao.getGroupByName(group.getName());
assertReflectionEquals(actual, group);
}
@Test
public void getGetUsersCount() {
int count = 5;
Group group = PersistedObjectsFactory.groupWithUsers(count);
int actual = groupDao.get(group.getId()).getUsers().size();
assertEquals(actual, count);
}
@Test
public void testDeleteGroup() {
Group group = ObjectsFactory.getRandomGroup();
saveAndEvict(group);
groupDao.delete(group);
Group actual = groupDao.get(group.getId());
assertNull(actual);
}
private void saveAndEvict(Branch branch) {
saveAndEvict(branch.getModeratorsGroup());
Section section = ObjectsFactory.getDefaultSection();
branch.setSection(section);
session.save(section);
session.save(branch);
session.evict(branch);
session.evict(section);
}
private void saveAndEvict(JCUser user) {
session.save(user);
session.evict(user);
}
private void saveAndEvict(Group group) {
saveAndEvict((Iterable<JCUser>) (Object) group.getUsers());
session.save(group);
session.evict(group);
}
private void saveAndEvict(Iterable<JCUser> users) {
for (JCUser user : users) {
saveAndEvict(user);
}
}
/**
* Works properly only with MySql database
* @throws ParseException
*/
@Test
public void listOfGroupsMustBeSortedAlphabetically() throws ParseException{
if (isMySql()){
List<GroupAdministrationDto> expected = new LinkedList<>();
for (int i = 0; i < 10; i++) {
Group en = new Group(alphanumeric(MIN_GROUP_NAME_LENGTH, MAX_GROUP_NAME_LENGTH));
Group ru = new Group(between(MIN_GROUP_NAME_LENGTH, MAX_GROUP_NAME_LENGTH).string(DICTIONARY_RU));
saveAndEvict(en);
saveAndEvict(ru);
expected.add(new GroupAdministrationDto(en.getName(), en.getUsers().size()));
expected.add(new GroupAdministrationDto(ru.getName(), ru.getUsers().size()));
}
sortByName(expected);
List<GroupAdministrationDto> actual = groupDao.getGroupNamesWithCountOfUsers();
assertReflectionEquals(expected, actual);
}
}
private void sortByName(List<GroupAdministrationDto> dtoList) throws ParseException {
RuleBasedCollator enUS = (RuleBasedCollator) Collator.getInstance(new Locale("en", "US"));
final RuleBasedCollator finalCollator = new RuleBasedCollator(enUS.getRules() + SORTING_TEST_RULES);
Collections.sort(dtoList, new Comparator<GroupAdministrationDto>() {
@Override
public int compare(GroupAdministrationDto o1, GroupAdministrationDto o2) {
return finalCollator.compare(o1.getName(), o2.getName());
}
});
}
/**
* listOfGroupsMustBeSortedAlphabetically test can run only with MySql database,
* so we need to check whether jdbc driver is MySql
* @return
*/
private boolean isMySql(){
String driverName = "";
try {
driverName = dataSource.getConnection().getMetaData().getDriverName();
} catch (SQLException e) {
logger.warn(e.getMessage());
}
return driverName.equalsIgnoreCase("MySQL Connector Java");
}
}