Skip to content

Commit

Permalink
Merge pull request #225 from DemocracyDevelopers/models-tests
Browse files Browse the repository at this point in the history
More data model tests
  • Loading branch information
vteague authored Dec 11, 2024
2 parents cb33dc7 + 0ddaa4f commit d0a3dfa
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,10 @@
import static us.freeandfair.corla.util.EqualsHashcodeHelper.*;

import java.io.Serializable;
import java.time.Clock;
import java.time.Instant;

import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;
import javax.persistence.*;

import us.freeandfair.corla.persistence.PersistentEntity;

Expand Down Expand Up @@ -106,6 +93,12 @@ public class Administrator implements PersistentEntity, Serializable {
* The last logout time.
*/
private Instant my_last_logout_time;

/**
* A clock that is only used for testing
*/
@Transient
private Clock my_clock;

/**
* Constructs a new Administrator with default values.
Expand Down Expand Up @@ -133,7 +126,25 @@ public Administrator(final String the_username,
my_full_name = the_full_name;
my_county = the_county;
}


/**
* Same as above, but injects a clock for use with testing.
*
* @param the_username
* @param the_type
* @param the_full_name
* @param the_county
* @param clock
*/
public Administrator(final String the_username,
final AdministratorType the_type,
final String the_full_name,
final County the_county,
final Clock clock) {
this(the_username, the_type, the_full_name, the_county);
my_clock = clock;
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -197,7 +208,12 @@ public Instant lastLoginTime() {
* Updates the last login time to the current time.
*/
public void updateLastLoginTime() {
my_last_login_time = Instant.now();
// If we're not testing, there will be no clock
if (my_clock == null) {
my_last_login_time = Instant.now();
} else {
my_last_login_time = Instant.now(my_clock);
}
}

/**
Expand All @@ -211,7 +227,12 @@ public Instant lastLogoutTime() {
* Updates the last logout time to the current time.
*/
public void updateLastLogoutTime() {
my_last_logout_time = Instant.now();
// If we're not testing, there will be no clock
if (my_clock == null) {
my_last_logout_time = Instant.now();
} else {
my_last_logout_time = Instant.now(my_clock);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
import java.nio.charset.StandardCharsets;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import au.org.democracydevelopers.corla.endpoint.AbstractAllIrvEndpoint;
import au.org.democracydevelopers.corla.model.ContestType;
import au.org.democracydevelopers.corla.model.GenerateAssertionsSummary;
import au.org.democracydevelopers.corla.model.IRVComparisonAudit;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package us.freeandfair.corla.model;

import org.testng.annotations.Test;
import us.freeandfair.corla.persistence.Persistence;
import us.freeandfair.corla.util.TestClassWithDatabase;

import java.time.Clock;
import java.time.Instant;

import static org.testng.Assert.assertNotEquals;
import static org.testng.AssertJUnit.*;
import static us.freeandfair.corla.util.EqualsHashcodeHelper.nullableHashCode;

@Test
public class AdministratorTest extends TestClassWithDatabase {

@Test
public static void testGettersAndSetters() {
String expectedUsername = "testname";
Administrator.AdministratorType expectedType = Administrator.AdministratorType.STATE;
String expectedFullname = "fulltestname";

// Make the clock stuck
Clock testClock = Clock.fixed(Instant.now(), Clock.systemDefaultZone().getZone());
Administrator admin = new Administrator(expectedUsername,
expectedType,
expectedFullname,
null,
testClock);


assertNull(admin.id());
assertNull(admin.version());
Persistence.saveOrUpdate(admin);

// this is a database constraint
assertNotNull(admin.id());

Long expectedID = 42L;
admin.setID(expectedID);
assertEquals(expectedID, admin.id());

assertEquals(expectedUsername, admin.username());
assertEquals(expectedFullname, admin.fullName());
assertEquals(expectedType, admin.type());
assertNull(admin.county());

// Because we're using a stopped clock, this time will be the same for both
Instant expectedTime = testClock.instant();
assertNull(admin.lastLoginTime());
admin.updateLastLoginTime();
assertEquals(expectedTime, admin.lastLoginTime());

assertNull(admin.lastLogoutTime());
admin.updateLastLogoutTime();
assertEquals(expectedTime, admin.lastLogoutTime());

String expected_string = "Administrator [username=" + expectedUsername + ", type=" +
expectedType+ ", full_name=" + expectedFullname+ ", county=" +
null + ", last_login_time=" + expectedTime +
", last_logout_time=" + expectedTime + "]";

assertEquals(expected_string, admin.toString());

/**
* Now test an admin without a clock set. This means we can't test timing-specific things,
* but we can at least test that the code paths behave the way we expect.
*/
admin = new Administrator(expectedUsername,
expectedType,
expectedFullname,
null);

assertNull(admin.lastLoginTime());
assertNull(admin.lastLogoutTime());

admin.updateLastLoginTime();
assertNotNull(admin.lastLoginTime());
admin.updateLastLogoutTime();
assertNotNull(admin.lastLogoutTime());
assert(admin.lastLoginTime() != admin.lastLogoutTime());
}

@Test
public static void testEquality() {
String firstAdminUsername = "first";
String secondAdminUsername = "second";
Administrator.AdministratorType expectedType = Administrator.AdministratorType.STATE;
String expectedFullname = "fulltestname";

Administrator firstAdmin = new Administrator(firstAdminUsername, expectedType, expectedFullname, null);
Administrator secondAdmin = new Administrator(secondAdminUsername, expectedType, expectedFullname, null);

assertTrue(firstAdmin.equals(firstAdmin));
assertFalse(firstAdmin.equals(secondAdmin));

// Now test that non-admin objects result in false
assertFalse(firstAdmin.equals(firstAdminUsername));
}

@Test
public static void testHash() {
String expectedUsername = "testname";
Administrator.AdministratorType expectedType = Administrator.AdministratorType.STATE;
String expectedFullname = "fulltestname";

Administrator admin = new Administrator(expectedUsername,
expectedType,
expectedFullname,
null);

assertEquals(admin.hashCode(), nullableHashCode(expectedUsername));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package us.freeandfair.corla.model;

import org.testng.annotations.Test;
import us.freeandfair.corla.util.TestClassWithDatabase;

import java.lang.reflect.Array;
import java.time.Instant;

import java.util.ArrayList;

import static org.testng.AssertJUnit.*;
import static us.freeandfair.corla.util.EqualsHashcodeHelper.nullableHashCode;

public class AuditBoardTest extends TestClassWithDatabase {

@Test
public static void testGettersAndSetters () {

AuditBoard defaultAB = new AuditBoard();
assertEquals(new ArrayList<Elector>(), defaultAB.members());
assertNull(defaultAB.signInTime());
assertNull(defaultAB.signOutTime());

ArrayList<Elector> electors = new ArrayList<>();

electors.add(new Elector("firstname", "lastname", "party"));

// TODO: do we want a stopped clock here too?
Instant sign_in_time = Instant.now();

AuditBoard ab = new AuditBoard(electors, sign_in_time);

assertEquals(electors, ab.members());

assertEquals(sign_in_time, ab.signInTime());

Instant sign_out_time = Instant.now();

ab.setSignOutTime(sign_out_time);
assertEquals(sign_out_time, ab.signOutTime());

String expectedToString = "AuditBoard [members=" + electors + ", sign_in_time=" +
sign_in_time + ", sign_out_time=" + sign_out_time + "]";

assertEquals(expectedToString, ab.toString());

assertEquals(nullableHashCode(sign_in_time), ab.hashCode());

assertFalse(ab.equals("Not an auditboard"));
ArrayList<Elector> otherElectors = new ArrayList<>();
otherElectors.add(new Elector("otherfirstname", "otherlastname", "otherparty"));

AuditBoard otherAB = new AuditBoard(otherElectors, sign_in_time);

assertFalse(ab.equals(otherAB));
assertTrue(ab.equals(ab));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@

import us.freeandfair.corla.csv.ContestNameParser;
import us.freeandfair.corla.json.VersionExclusionStrategy;
import us.freeandfair.corla.util.TestClassWithDatabase;

public class AuditInfoTest {
public class AuditInfoTest extends TestClassWithDatabase {
public Gson gson;

@BeforeClass
Expand All @@ -33,7 +34,7 @@ public void AuditInfoTest() {
}

@Test()
private void canonicalContestsTest() {
private void testCanonicalContests() {
Map<String, Set<String>> contestMap = new TreeMap<String, Set<String>>();

Set<String> contests = new HashSet<String>();
Expand Down Expand Up @@ -79,7 +80,7 @@ public String contestsFromJSON(final String json) {
// @SuppressWarnings("PMD.DoNotUseThreads")
// @SuppressFBWarnings(value = {"URF_UNREAD_FIELD"},
// justification = "JSON blobs are big")
public void parsingTest() {
public void testParsing() {
final String json = "{\"election_date\":\"2018-07-31T06:00:00.000Z\",\"election_type\":\"coordinated\",\"public_meeting_date\":\"2018-08-07T06:00:00.000Z\",\"risk_limit\":0.05,\"upload_file\":[{\"preview\":\"blob:http://localhost:3000/54a4f865-9d2a-b442-881a-8630050977dc\",\"contents\":'\"CountyName\",\"ContestName\"\n\"Boulder\",\"Kombucha - DEM\"\n\"Boulder\",\"Kale - DEM\"\n\"Denver\",\"IPA - DEM\"\n\"Denver\",\"Porter - REP\"\n\"Chaffee\",\"Hooligan Race - DEM\"\n\"Chaffee\",\"Pole Pedal Paddle - DEM\"\n\"Chaffee\",\"Gunbarrel Challenge - REP\"\n'}]}";

String contests = contestsFromJSON(json);
Expand Down

0 comments on commit d0a3dfa

Please sign in to comment.