/*
This file is part of OpenMyEWB.
OpenMyEWB is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenMyEWB 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMyEWB. If not, see <http://www.gnu.org/licenses/>.
OpenMyEWB is Copyright 2005-2009 Nicolas Kruchten (nicolas@kruchten.com), Francis Kung, Engineers Without Borders Canada, Michael Trauttmansdorff, Jon Fishbein, David Kadish
*/
package ca.myewb.dbinvariants;
import java.math.BigInteger;
import java.util.List;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.Transaction;
import ca.myewb.frame.HibernateUtil;
import ca.myewb.frame.Helpers;
import ca.myewb.model.GroupModel;
public class MultiGroupInvariantsTest extends TestCase
{
Session session;
Transaction tx;
public void setUp()
{
try
{
// Register DB
Class.forName("com.mysql.jdbc.Driver");
// Start a Hibernate session
if(!HibernateUtil.isFactoryInitialized())
{
HibernateUtil.createFactory("deploy");
}
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
}
catch (Exception e)
{
System.err.println("Exception " + e);
e.printStackTrace();
}
}
public void tearDown()
{
try
{
tx.commit();
HibernateUtil.closeSession();
}
catch (Exception e)
{
System.err.println("Excpetion: " + e);
e.printStackTrace();
}
}
////////////// top-level memberships
public void testAllUsersOrgOrDeleted()
{
String sql = "SELECT count(*) " +
"FROM users u " +
"WHERE NOT EXISTS (" +
"SELECT * " +
"FROM roles r, groups g " +
"WHERE r.userid = u.id " +
"AND r.end IS NULL " +
"AND r.groupid = g.id " +
"AND (g.name = 'Org' OR g.name = 'Deleted') " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every known user should be a member of Org or Deleted", 0, result);
}
public void testUserMemberOrg()
{
int result = numViolationsOfMutuallyInclusiveGroups("Users", "Org");
assertEquals("Every member of the User group must be a member of the Org", 0, result);
}
public void testDeletionInvariant()
{
String sql = "SELECT count(*) " +
"FROM roles r1, roles r2, groups g1 " +
"WHERE r1.userid = r2.userid " +
"AND r1.groupid = g1.id " +
"AND g1.name = 'Deleted' " +
"AND r1.end IS NULL " +
"AND r2.end IS NULL " +
"AND r1.id != r2.id ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("No deleted user should be a member of any group", 0, result);
}
////////////// associate/regular
public void testAssociateOrRegularInvariant()
{
int result = numViolationsOfMutuallyExclusiveGroups("Associate", "Regular");
assertEquals("No user should be a member of the Associate group and Regular group", 0, result);
}
public void testUserAssociateOrRegular()
{
int result = numViolationsOfInGroupXMustBeInYOrZ("Users", "Associate", "Regular");
assertEquals("Every user should be a member of Associate or Regular", 0, result);
}
public void testAssociateUser()
{
int result = numViolationsOfMutuallyInclusiveGroups("Associate", "Users");
assertEquals("Every member of associate must be a registered User", 0, result);
}
public void testRegularUser()
{
int result = numViolationsOfMutuallyInclusiveGroups("Regular", "Users");
assertEquals("Every member of regular must be a registered User", 0, result);
}
////////////// chapter/no chapter
public void testOrgChapterOrNoChapter()
{
int result = numViolationsOfInGroupXMustBeInYOrZ("Org", "Chapter", "NoChapter");
assertEquals("Every user should be a member of Chapter or NoChapter", 0, result);
}
public void testChapterOrg()
{
int result = numViolationsOfMutuallyInclusiveGroups("Chapter", "Org");
assertEquals("Every member of Chapter must be a registered User", 0, result);
}
public void testNoChapterOrg()
{
int result = numViolationsOfMutuallyInclusiveGroups("NoChapter", "Org");
assertEquals("Every member of NoChapter must be a registered User", 0, result);
}
public void testChapterOrNochapterInvariant()
{
int result = numViolationsOfMutuallyExclusiveGroups("Chapter", "NoChapter");
assertEquals("No user should be a member of the Chapter group and NoChapter group", 0, result);
}
////////////// other chapter stuff
public void testChapterMemberOfChapter()
{
String sql = "SELECT count(*) " +
"FROM roles r1, groups g " +
"WHERE r1.end IS NULL " +
"AND r1.groupid = g.id " +
"AND g.name = 'Chapter' " +
"AND NOT EXISTS ( " +
"SELECT * " +
"FROM roles r2, groupchapter gc " +
"WHERE r2.userid = r1.userid " +
"AND r2.end IS NULL " +
"AND r2.groupid = gc.id " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every member of the Chapter group must be a member of a chapter", 0, result);
}
public void testNoChapterNotMemberOfChapter()
{
String sql = "SELECT count(*) " +
"FROM roles r1, groups g " +
"WHERE r1.end IS NULL " +
"AND r1.groupid = g.id " +
"AND g.name = 'NoChapter' " +
"AND EXISTS ( " +
"SELECT * " +
"FROM roles r2, groupchapter gc " +
"WHERE r2.userid = r1.userid " +
"AND r2.end IS NULL " +
"AND r2.groupid = gc.id " +
"AND r2.level = 'm' " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every member of the NoChapter group must not be a member of a chapter", 0, result);
}
public void testSingleChapterInvariant()
{
String sql = "SELECT count(*) " +
"FROM roles r1, roles r2, groups g1, groups g2, groupchapter gc1, groupchapter gc2 " +
"WHERE r1.userid = r2.userid " +
"AND r1.groupid = g1.id " +
"AND r2.groupid = g2.id " +
"AND g1.id != g2.id " +
"AND g1.id = gc1.id " +
"AND g2.id = gc2.id " +
"AND r1.level = 'm' " +
"AND r2.level = 'm' " +
"AND r1.end IS NULL " +
"AND r2.end IS NULL ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("No user should be a member of more than one chapter", 0, result);
}
public void testChapterLeaderExecMemberInvariant() {
String sql = "SELECT count(*) " +
"FROM roles r, groups g, groupchapter gc " +
"WHERE r.groupid = g.id " +
"AND g.id = gc.id " +
"AND r.level = 'l' " +
"AND r.end IS NULL " +
"AND r.userid NOT IN ( " +
"SELECT rs.userid " +
"FROM roles rs, groups gs " +
"WHERE rs.groupid = gs.id " +
"AND gs.name = 'Chapter Executive Members (all chapters)' " +
"AND rs.end IS NULL " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every leader of a chapter should be a member of the Exec group", 0, result);
}
public void testExecMemberChapterLeaderInvariant() {
//inverse of above
String sql = "SELECT count(*) " +
"FROM roles rs, groups gs " +
"WHERE rs.groupid = gs.id " +
"AND gs.name = 'exec' " +
"AND rs.end IS NULL " +
"AND rs.userid NOT IN ( " +
"SELECT r.userid " +
"FROM roles r, groups g, groupchapter gc " +
"WHERE r.groupid = g.id " +
"AND g.id = gc.id " +
"AND r.level = 'l' " +
"AND r.end IS NULL " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every member of the exec group should be a leader of a chapter", 0, result);
}
public void testChapterLeaderChapterExecListLeaderInvariant() {
String sql = "SELECT count(*) " +
"FROM roles r, groups g, groupchapter gc " +
"WHERE r.groupid = g.id " +
"AND g.id = gc.id " +
"AND r.level = 'l' " +
"AND r.end IS NULL " +
"AND r.userid NOT IN ( " +
"SELECT rs.userid " +
"FROM roles rs, groups gs, groupchapter gcs " +
"WHERE rs.groupid = gs.id " +
"AND gs.parent = gcs.id " +
"AND gs.shortname = 'exec' " +
"AND rs.level = 'l' " +
"AND gcs.id = g.id " +
"AND rs.end IS NULL " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every leader of a chapter should be a leader of their chapter exec list", 0, result);
}
public void testChapterExecListLeaderChapterLeaderInvariant() {
//Inverse of above
String sql = "SELECT count(*) " +
"FROM roles rs, groups gs, groupchapter gcs, groups g " +
"WHERE rs.groupid = gs.id " +
"AND gs.parent = gcs.id " +
"AND gs.shortname = 'exec' " +
"AND rs.level = 'l' " +
"AND gcs.id = g.id " +
"AND rs.end IS NULL " +
"AND rs.userid NOT IN ( " +
"SELECT r.userid " +
"FROM roles r, groupchapter gc " +
"WHERE r.groupid = g.id " +
"AND g.id = gc.id " +
"AND r.level = 'l' " +
"AND r.end IS NULL " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("Every leader of a chapter exec list should be a leader of their chapter list", 0, result);
}
public void testNatlRepsAreExecOrNatlRepsInvariant() {
List<GroupModel> nrLists = Helpers.getNationalRepLists(true, true);
for(GroupModel nrList: nrLists)
{
int result = numViolationsOfInGroupXMustBeInYOrZ(nrList.getName(), "Chapter Executive Members (all chapters)", "National Reps");
assertEquals("Every member of the " + nrList.getName() + " group should be in the Exec group or in the National Reps group", 0, result);
}
}
public void testNatlRepOrExecInvariant()
{
int result = numViolationsOfMutuallyExclusiveGroups("Chapter Executive Members (all chapters)", "National Reps");
assertEquals("No user should be a member of the Exec group and NatlRep group", 0, result);
}
public void testNatlRepChapterMemberInvariant()
{
int result = numViolationsOfMutuallyInclusiveGroups("National Reps", "Chapter");
assertEquals("Every user who is a member of the NatlRep group should be a Chapter member", 0, result);
}
// Pro vs. Student Chapter tests
public void testStudentChapterRepsNotInProRepOrExecGroups()
{
String sql = "SELECT count(*) " +
"FROM groups g, users u, roles r1, roles r2, groupchapter c " +
"WHERE ( " +
"r1.end IS NULL " +
"AND r2.end IS NULL) " +
"AND " +
"(r1.groupid = c.id " +
"AND r1.userid = u.id " +
"AND r1.level = 'm' " +
"AND c.professional = false) " +
"AND " +
"(r2.groupid = g.id " +
"AND r2.userid = u.id " +
"AND ( g.nationalRepType IN ('p') " +
"OR g.shortname LIKE 'ProChaptersExec' )" +
")";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("No student chapter members should be in professional rep groups", 0, result);
}
public void testProChapterRepsNotInStudentRepOrExecGroups()
{
String sql = "SELECT count(*) " +
"FROM groups g, users u, roles r1, roles r2, groupchapter c " +
"WHERE ( " +
"r1.end IS NULL " +
"AND r2.end IS NULL) " +
"AND " +
"(r1.groupid = c.id " +
"AND r1.userid = u.id " +
"AND r1.level = 'm' " +
"AND c.professional = true) " +
"AND " +
"(r2.groupid = g.id " +
"AND r2.userid = u.id " +
"AND ( g.nationalRepType IN ('s') " +
"OR g.shortname LIKE 'UniChaptersExec' )" +
")";
int result = ((BigInteger)session.createSQLQuery(sql).uniqueResult()).intValue();
assertEquals("No professional chapter members should be in student rep groups", 0, result);
}
public void testUniExecMembersNotInProExecGroup(){
int result = numViolationsOfMutuallyExclusiveGroups("Student Chapter Exec", "Professional Chapter Exec");
assertEquals("Nobody should be in both the University Chapters Exec Group and the Pro Chapters Exec Group"
, 0, result);
}
public void testProAndStudentExecInExecGroup(){
int result = numViolationsOfMutuallyInclusiveGroups("Student Chapter Exec", "Chapter Executive Members (all chapters)");
assertEquals("Users in the UniChaptersExec group should also be in the Exec group"
, 0, result);
result = numViolationsOfMutuallyInclusiveGroups("Professional Chapter Exec", "Chapter Executive Members (all chapters)");
assertEquals("Users in the ProChaptersExec group should also be in the Exec group"
, 0, result);
}
public void testExecMembersInStudentExecOrProExecGroup()
{
int result = numViolationsOfInGroupXMustBeInYOrZ("Chapter Executive Members (all chapters)","Professional Chapter Exec","Student Chapter Exec");
assertEquals("Members of the Exec must be Pro or Uni Exec", 0, result);
}
////////////// generic helpers for some of the above tests
private int numViolationsOfMutuallyExclusiveGroups(String g1, String g2)
{
String sql = "SELECT count(*) " +
"FROM roles r1, roles r2, groups g1, groups g2 " +
"WHERE r1.userid = r2.userid " +
"AND r1.groupid = g1.id " +
"AND r2.groupid = g2.id " +
"AND g1.name = ? " +
"AND g2.name = ? " +
"AND r1.end IS NULL " +
"AND r2.end IS NULL ";
return((BigInteger)session.createSQLQuery(sql).setString(0, g1).setString(1, g2).uniqueResult()).intValue();
}
private int numViolationsOfMutuallyInclusiveGroups(String g1, String g2) {
String sql = "SELECT count(*) " +
"FROM roles r, groups g " +
"WHERE r.groupid = g.id " +
"AND r.end IS NULL " +
"AND g.name = ? " +
"AND r.userid NOT IN ( " +
"SELECT rs.userid " +
"FROM roles rs, groups gs " +
"WHERE rs.groupid = gs.id " +
"AND gs.name = ? " +
"AND rs.end IS NULL " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).setString(0, g1).setString(1, g2).uniqueResult()).intValue();
return result;
}
private int numViolationsOfInGroupXMustBeInYOrZ(String x, String y, String z) {
String sql = "SELECT count(*) " +
"FROM roles r1, groups g1 " +
"WHERE r1.groupid = g1.id " +
"AND r1.end IS NULL " +
"AND g1.name = ? " +
"AND NOT EXISTS (" +
"SELECT * " +
"FROM roles r2, groups g2 " +
"WHERE r1.userid = r2.userid " +
"AND r2.end IS NULL " +
"AND r2.groupid = g2.id " +
"AND (g2.name = ? OR g2.name = ?) " +
") ";
int result = ((BigInteger)session.createSQLQuery(sql).setString(0, x).setString(1, y).setString(2, z).uniqueResult()).intValue();
return result;
}
}