From 8d2d44105418b2f0b0aec79558859d76aa556c71 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Fri, 19 Jul 2024 19:01:23 +1000 Subject: [PATCH 01/10] Added tests for removing discrepancies from an IRVComparisonAudit. --- .../corla/model/IRVComparisonAuditTests.java | 112 ++++++++++++++++-- 1 file changed, 100 insertions(+), 12 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index f051556a..7a8d445f 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -50,10 +50,7 @@ /** * This class contains tests for the functionality present in IRVComparisonAudit. - * TODO: tests for removing discrepancies -2, -1, 0, 1, 2 * TODO: tests for risk measurement. - * TODO: tests of the reaudit ballot workflow. - * TODO: tests for remaining error modes. */ public class IRVComparisonAuditTests extends AssertionTests { @@ -131,6 +128,12 @@ public class IRVComparisonAuditTests extends AssertionTests { @Mock private CVRAuditInfo auditInfo; + /** + * Mock of a CVRAuditInfo object, matched to a null CVR + */ + @Mock + private CVRAuditInfo auditInfoNullCVR; + /** * Initialise mocked objects prior to the first test. Note that the diluted margin * returned by ContestResult's for IRV will not have a sensible value, and it will @@ -167,6 +170,10 @@ public void initContestResultMocks() { when(auditInfo.id()).thenReturn(1L); when(auditInfo.cvr()).thenReturn(cvr); when(auditInfo.acvr()).thenReturn(auditedCvr); + + when(auditInfoNullCVR.id()).thenReturn(1L); + when(auditInfoNullCVR.cvr()).thenReturn(null); + when(auditInfoNullCVR.acvr()).thenReturn(auditedCvr); } @@ -460,6 +467,72 @@ public void testNENRecordNoDiscrepancy(int theType){ ca.recordDiscrepancy(auditInfo, theType); } + /** + * If we call removeDiscrepancy() with an invalid discrepancy type (3), an IllegalArgumentException + * should be thrown. + */ + @Test(expectedExceptions = IllegalArgumentException.class) + public void testRemoveInvalidDiscrepancy1(){ + log(LOGGER, "testRemoveInvalidDiscrepancy1"); + IRVComparisonAudit ca = new IRVComparisonAudit(testEstimationNEBOnly, + AssertionTests.riskLimit3, AuditReason.OPPORTUNISTIC_BENEFITS); + + ca.removeDiscrepancy(auditInfo, 3); + } + + /** + * If we call removeDiscrepancy() with an invalid discrepancy type (-3), an IllegalArgumentException + * should be thrown. + */ + @Test(expectedExceptions = IllegalArgumentException.class) + public void testRemoveInvalidDiscrepancy2(){ + log(LOGGER, "testRemoveInvalidDiscrepancy2"); + IRVComparisonAudit ca = new IRVComparisonAudit(testEstimationNEBOnly, + AssertionTests.riskLimit3, AuditReason.OPPORTUNISTIC_BENEFITS); + + ca.removeDiscrepancy(auditInfo, -3); + } + + /** + * If we call removeDiscrepancy() on an audit that does not contain any discrepancies, no + * discrepancies will be removed. + */ + @Test + public void testRemoveInvalidDiscrepancy3(){ + log(LOGGER, "testRemoveInvalidDiscrepancy3"); + IRVComparisonAudit ca = new IRVComparisonAudit(mixedContest2, + AssertionTests.riskLimit3, AuditReason.OPPORTUNISTIC_BENEFITS); + + checkDiscrepancies(ca, 0, 0, 0, 0, 0); + ca.removeDiscrepancy(auditInfo, 1); + checkDiscrepancies(ca, 0, 0, 0, 0, 0); + } + + /** + * If we call removeDiscrepancy() with a null audit info, an IllegalArgumentException will be + * thrown. + */ + @Test(expectedExceptions = IllegalArgumentException.class) + public void testRemoveNullAuditInfo(){ + log(LOGGER, "testRemoveNullAuditInfo"); + IRVComparisonAudit ca = new IRVComparisonAudit(testEstimationNEBOnly, + AssertionTests.riskLimit3, AuditReason.OPPORTUNISTIC_BENEFITS); + + ca.removeDiscrepancy(null, -1); + } + + /** + * If we call removeDiscrepancy() with a null cvr in the provided audit info, an + * IllegalArgumentException will be thrown. + */ + @Test(expectedExceptions = IllegalArgumentException.class) + public void testRemoveNullAuditInfoCVR(){ + log(LOGGER, "testRemoveNullAuditInfoCVR"); + IRVComparisonAudit ca = createIRVComparisonAuditMixed(); + + ca.removeDiscrepancy(auditInfoNullCVR, -1); + } + /** * Discrepancy computation for 'Mixed Contest' with CVR "A" and audited ballot "A", "B", "C" ,"D". * The maximum discrepancy is 0. @@ -507,8 +580,8 @@ public void testRecordWrongDiscrepancy(){ * "B","A","C","D" and recording of the resulting maximum discrepancy of type 2. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) - public void testComputeRecordDiscrepancyCVR_ABCD_ACVR_BACD(RecordType auditedType){ - log(LOGGER, String.format("testComputeRecordDiscrepancyCVR_ABCD_ACVR_BACD[%s]", auditedType)); + public void testComputeRecordRemoveDiscrepancyCVR_ABCD_ACVR_BACD(RecordType auditedType){ + log(LOGGER, String.format("testComputeRecordRemoveDiscrepancyCVR_ABCD_ACVR_BACD[%s]", auditedType)); resetMocks(ABCD, BACD, RecordType.UPLOADED, ConsensusValue.YES, auditedType, "Mixed Contest"); IRVComparisonAudit ca = createIRVComparisonAuditMixed(); @@ -524,6 +597,9 @@ public void testComputeRecordDiscrepancyCVR_ABCD_ACVR_BACD(RecordType auditedTyp ca.recordDiscrepancy(auditInfo, 2); checkDiscrepancies(ca, 0, 1, 0, 0, 0); + + ca.removeDiscrepancy(auditInfo, 2); + checkDiscrepancies(ca, 0, 0, 0, 0, 0); } /** @@ -574,8 +650,8 @@ public void testComputeDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ * audited ballot "A","B","C","D". The maximum discrepancy is 1. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) - public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ - log(LOGGER, String.format("testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD[%s]", auditedType)); + public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ + log(LOGGER, String.format("testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD[%s]", auditedType)); resetMocks(BACD, ABCD, RecordType.UPLOADED, ConsensusValue.YES, auditedType, "Mixed Contest"); IRVComparisonAudit ca = createIRVComparisonAuditMixed(); @@ -591,6 +667,9 @@ public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedTyp ca.recordDiscrepancy(auditInfo, 1); checkDiscrepancies(ca, 1, 0, 0, 0, 0); + + ca.removeDiscrepancy(auditInfo, 1); + checkDiscrepancies(ca, 0, 0, 0, 0, 0); } /** @@ -598,8 +677,8 @@ public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedTyp * audited ballot "A","B","C","D". The maximum discrepancy is -1. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) - public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType auditedType){ - log(LOGGER, String.format("testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_mixed2[%s]", auditedType)); + public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType auditedType){ + log(LOGGER, String.format("testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2[%s]", auditedType)); resetMocks(BACD, ABCD, RecordType.UPLOADED, ConsensusValue.YES, auditedType, "Mixed Contest 2"); IRVComparisonAudit ca = createIRVComparisonAuditMixed2(); @@ -615,6 +694,9 @@ public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType aud ca.recordDiscrepancy(auditInfo, -1); checkDiscrepancies(ca, 0, 0, 1, 0, 0); + + ca.removeDiscrepancy(auditInfo, -1); + checkDiscrepancies(ca, 0, 0, 0, 0, 0); } /** @@ -622,7 +704,7 @@ public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType aud * audited ballot "A","B","C","D". The maximum discrepancy is -2. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) - public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_simple3(RecordType auditedType){ + public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_simple3(RecordType auditedType){ log(LOGGER, String.format("testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_simple3[%s]", auditedType)); resetMocks(BACD, ABCD, RecordType.UPLOADED, ConsensusValue.YES, auditedType, "Simple Contest 3"); IRVComparisonAudit ca = createIRVComparisonAuditSimple3(); @@ -639,6 +721,9 @@ public void testComputeRecordDiscrepancyCVR_BACD_ACVR_ABCD_simple3(RecordType au ca.recordDiscrepancy(auditInfo, -2); checkDiscrepancies(ca, 0, 0, 0, 1, 0); + + ca.removeDiscrepancy(auditInfo, -2); + checkDiscrepancies(ca, 0, 0, 0, 0, 0); } /** @@ -703,8 +788,8 @@ public void testComputeDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ * "A","B","C","D". The maximum discrepancy is 0. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) - public void testComputeRecordDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ - log(LOGGER, String.format("testComputeRecordDiscrepancyCVR_blank_ACVR_ABCD[%s]", auditedType)); + public void testComputeRecordRemoveDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ + log(LOGGER, String.format("testComputeRecordRemoveDiscrepancyCVR_blank_ACVR_ABCD[%s]", auditedType)); resetMocks(blank, ABCD, RecordType.UPLOADED, ConsensusValue.YES, auditedType, "Mixed Contest"); IRVComparisonAudit ca = createIRVComparisonAuditMixed(); @@ -720,6 +805,9 @@ public void testComputeRecordDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedTy ca.recordDiscrepancy(auditInfo, 0); checkDiscrepancies(ca, 0, 0, 0, 0, 1); + + ca.removeDiscrepancy(auditInfo, 0); + checkDiscrepancies(ca, 0, 0, 0, 0, 0); } /** From f2510547507f7b65838c7dd4810a6190642762a9 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Fri, 26 Jul 2024 16:36:40 +1000 Subject: [PATCH 02/10] Some rogue use of "NEB" in place of "NEN" in commenting fixed. --- .../model/assertion/NENAssertionTests.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index b03ed053..5e9d66f3 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -1066,7 +1066,7 @@ public void testNENComputeDiscrepancyTwoUnder2(RecordType recordType){ /** * Given a CVR with a vote "A", "B", "C", "D" and audited ballot with a vote of "B", "A", "C", "D", - * check that the right discrepancy is computed for the assertions D NEB C assuming "B", "C", + * check that the right discrepancy is computed for the assertions D NEN C assuming "B", "C", * and "D" are continuing, and D NEN E assuming "C", "D", and "E" are continuing. * (In this case, an "other" discrepancy). */ @@ -1383,7 +1383,7 @@ public void testNENComputeDiscrepancyPhantomBallotNormalCVR4(){ /** * Given a CVR with vote "A", "B", "C", "D", and a ballot with no consensus, check that * the right discrepancy is computed for assertions A NEN F given that "A", "C", and "F" are - * continuing, B NEB C given "B", and "C" are continuing, and D NEN F given "D" and "F" are + * continuing, B NEN C given "B", and "C" are continuing, and D NEN F given "D" and "F" are * continuing. (A two vote overstatement). */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) @@ -1853,8 +1853,8 @@ public void testNENExcessRemovalCausesErrorTwoVoteOver(){ * in error. The n+1'th call the removeDiscrepancy should throw an exception. */ @Test(expectedExceptions = RuntimeException.class) - public void testNEBExcessRemovalCausesErrorTwoVoteUnder(){ - log(LOGGER, "testNEBExcessRemovalCausesErrorTwoVoteUnder"); + public void testNENExcessRemovalCausesErrorTwoVoteUnder(){ + log(LOGGER, "testNENExcessRemovalCausesErrorTwoVoteUnder"); final int N = 2; CVRAuditInfo info = new CVRAuditInfo(); @@ -1877,8 +1877,8 @@ public void testNEBExcessRemovalCausesErrorTwoVoteUnder(){ * in error. The n+1'th call the removeDiscrepancy should throw an exception. */ @Test(expectedExceptions = RuntimeException.class) - public void testNEBExcessRemovalCausesErrorOneVoteUnder(){ - log(LOGGER, "testNEBExcessRemovalCausesErrorOneVoteUnder"); + public void testNENExcessRemovalCausesErrorOneVoteUnder(){ + log(LOGGER, "testNENExcessRemovalCausesErrorOneVoteUnder"); final int N = 2; CVRAuditInfo info = new CVRAuditInfo(); @@ -1901,8 +1901,8 @@ public void testNEBExcessRemovalCausesErrorOneVoteUnder(){ * in error. The n+1'th call the removeDiscrepancy should throw an exception. */ @Test(expectedExceptions = RuntimeException.class) - public void testNEBExcessRemovalCausesErrorOneVoteOver(){ - log(LOGGER, "testNEBExcessRemovalCausesErrorOneVoteOver"); + public void testNENExcessRemovalCausesErrorOneVoteOver(){ + log(LOGGER, "testNENExcessRemovalCausesErrorOneVoteOver"); final int N = 2; CVRAuditInfo info = new CVRAuditInfo(); @@ -1925,8 +1925,8 @@ public void testNEBExcessRemovalCausesErrorOneVoteOver(){ * in error. The n+1'th call the removeDiscrepancy should throw an exception. */ @Test(expectedExceptions = RuntimeException.class) - public void testNEBExcessRemovalCausesErrorOther(){ - log(LOGGER, "testNEBExcessRemovalCausesErrorOther"); + public void testNENExcessRemovalCausesErrorOther(){ + log(LOGGER, "testNENExcessRemovalCausesErrorOther"); final int N = 2; CVRAuditInfo info = new CVRAuditInfo(); @@ -2141,7 +2141,7 @@ public void computeEstimatedSamplesToAudit(int auditedSampleCount){ * @param twoVoteOver Number of two vote overstatements to associate with the assertion. * @param twoVoteUnder Number of two vote understatements to associate with the assertion. * @param other Number of other discrepancies to associate with the assertion. - * @return an NEB assertion with the given specification. + * @return an NEN assertion with the given specification. */ private static Assertion createNENAssertion(String winner, String loser, String contestName, List continuing, int rawMargin, double dilutedMargin, double difficulty, From 54daaa5154ef955fddbe59b69b0620a334207a98 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Mon, 29 Jul 2024 12:09:25 +1000 Subject: [PATCH 03/10] Added risk measurement tests for NEN Assertions. --- .../corla/model/IRVComparisonAuditTests.java | 40 ++++++- .../corla/model/assertion/AssertionTests.java | 14 +++ .../model/assertion/NEBAssertionTests.java | 30 +++++- .../model/assertion/NENAssertionTests.java | 101 +++++++++++++----- 4 files changed, 156 insertions(+), 29 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index db64358b..c839e40e 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -52,7 +52,6 @@ /** * This class contains tests for the functionality present in IRVComparisonAudit. - * TODO: tests for risk measurement. */ @Transactional public class IRVComparisonAuditTests extends AssertionTests { @@ -218,6 +217,19 @@ public void testCreateIRVAuditOneNEBAssertion(){ 0, 0, 23, 23, 1, Map.of(), 0.32); } + /** + * Create an IRVComparisonAudit for a contest with one NEB assertion stored in the database, and + * test that riskMeasurement() returns the maximum risk (no samples audited). + */ + @Test + public void testCreateIRVAuditOneNEBAssertionRiskMeasurement(){ + testUtils.log(LOGGER, "testCreateIRVAuditOneNEBAssertionRiskMeasurement"); + IRVComparisonAudit ca = new IRVComparisonAudit(oneNEBContestResult, AssertionTests.riskLimit3, + AuditReason.COUNTY_WIDE_CONTEST); + + assertEquals(0, testUtils.doubleComparator.compare(1.0, ca.riskMeasurement().doubleValue())); + } + /** @@ -241,6 +253,19 @@ public void testCreateIRVAuditOneNENAssertion(){ 61, 1, Map.of(), 0.12); } + /** + * Create an IRVComparisonAudit for a contest with one NEN assertion stored in the database, and + * test that riskMeasurement() returns the maximum risk (no samples audited). + */ + @Test + public void testCreateIRVAuditOneNENAssertionRiskMeasurement(){ + testUtils.log(LOGGER, "testCreateIRVAuditOneNENAssertionRiskMeasurement"); + IRVComparisonAudit ca = new IRVComparisonAudit(oneNENContestResult, AssertionTests.riskLimit3, + AuditReason.GEOGRAPHICAL_SCOPE); + + assertEquals(0, testUtils.doubleComparator.compare(1.0, ca.riskMeasurement().doubleValue())); + } + /** * Create an IRVComparisonAudit for a contest with one NEN and one NEB assertion stored in the * database. The smallest diluted margin across these assertions is 0.1. @@ -265,6 +290,19 @@ public void testCreateIRVAuditOneNENNEBAssertion(){ 15, 1, Map.of(), 0.5); } + /** + * Create an IRVComparisonAudit for a contest with one NEN and one NEN assertion stored in the database, and + * test that riskMeasurement() returns the maximum risk (no samples audited). + */ + @Test + public void testCreateIRVAuditOneNENNEBAssertionRiskMeasurement(){ + testUtils.log(LOGGER, "testCreateIRVAuditOneNENNEBAssertionRiskMeasurement"); + IRVComparisonAudit ca = new IRVComparisonAudit(oneNENNEBContestResult, AssertionTests.riskLimit3, + AuditReason.COUNTY_WIDE_CONTEST); + + assertEquals(0, testUtils.doubleComparator.compare(1.0, ca.riskMeasurement().doubleValue())); + } + /** * Create an IRVComparisonAudit for a multi-county contest with two NEBs and one NEN stored in the * database. The smallest diluted margin across these assertions is 0.1. diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java index e0a64de7..3b5cfdca 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java @@ -28,6 +28,7 @@ import static org.testng.Assert.assertEquals; import au.org.democracydevelopers.corla.util.TestClassWithDatabase; +import au.org.democracydevelopers.corla.util.testUtils; import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -660,4 +661,17 @@ public static void checkCountsDiscrepancyMap(final Assertion a, int oneOver, int assertEquals(a.cvrDiscrepancy, cvrDiscrepancy); } + + /** + * Checks whether an assertion's riskMeasurement() method calculates the correct risks for + * varying sample numbers. + * @param a Assertion whose riskMeasurement() method we are testing. + * @param risks Map of expected sample counts to risk values. + */ + public static void checkRiskMeasurement(Assertion a, final Map risks){ + for(Map.Entry entry : risks.entrySet()){ + final BigDecimal r = a.riskMeasurement(entry.getKey()); + assertEquals(testUtils.doubleComparator.compare(entry.getValue(), r.doubleValue()), 0); + } + } } diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java index 4520b239..be5003b3 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java @@ -28,6 +28,7 @@ import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; +import au.org.democracydevelopers.corla.util.testUtils; import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -52,7 +53,6 @@ * -- Scoring of NEB assertions. * -- Computation of discrepancies for NEB assertions. * -- The logic involved in the re-auditing of ballots. - * -- TODO: Test Assertion::riskMeasurement() * Refer to the Guide to RAIRE for details on how NEB assertions are scored, and how * discrepancies are computed (Part 2, Appendix A). */ @@ -142,6 +142,34 @@ public void testNEBEstimatedVaryingSamples(Integer auditedSamples, BigDecimal ri assertEquals(a.estimatedSamplesToAudit.intValue(), expected); } + /** + * Test riskMeasurement() for an NEB assertion with no discrepancies. + */ + @Test + public void testNEBRiskMeasurementNoDiscrepancies(){ + log(LOGGER, "testNEBRiskMeasurementNoDiscrepancies"); + + Assertion a = createNEBAssertion("W", "L", TC, 80, + 0.2, 8, Map.of(), 0, 0, + 0, 0, 0); + + // Test risk measurement after 5 samples, no discrepancies + BigDecimal r = a.riskMeasurement(5); + assertEquals(testUtils.doubleComparator.compare(0.603, r.doubleValue()), 0); + + // Test risk measurement after 10 samples, no discrepancies + r = a.riskMeasurement(10); + assertEquals(testUtils.doubleComparator.compare(0.364, r.doubleValue()), 0); + + // Test risk measurement after 50 samples, no discrepancies + r = a.riskMeasurement(50); + assertEquals(testUtils.doubleComparator.compare(0.006, r.doubleValue()), 0); + + // Test risk measurement after 100 samples, no discrepancies + r = a.riskMeasurement(100); + assertEquals(testUtils.doubleComparator.compare(0.0, r.doubleValue()), 0); + } + /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) in the context where no discrepancy has * been computed for the given CVR-ACVR pair, and the assertion has no prior recorded diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index 5e9d66f3..cf660f02 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -28,6 +28,7 @@ import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; +import au.org.democracydevelopers.corla.util.testUtils; import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -194,9 +195,26 @@ public void testNENRecordNoMatch2(){ Map.of(2L, -1, 3L, 1)); } + /** + * Test riskMeasurement() for an NEN assertion with no discrepancies. + */ + @Test + public void testNENRiskMeasurementNoDiscrepancies(){ + log(LOGGER, "testNENRiskMeasurementNoDiscrepancies"); + + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, + 0.1, 8, Map.of(), 0, 0, + 0, 0, 0); + + checkRiskMeasurement(a, Map.of(5, 0.781, 10, 0.611, 100, 0.007)); + } + + + /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context - * where the assertion has no recorded discrepancies. + * where the assertion has no recorded discrepancies. Also check risk measurement given one + * 1 vote overstatement and varying sample counts. */ @Test public void testNENRecordOneVoteOverstatement1(){ @@ -210,11 +228,14 @@ public void testNENRecordOneVoteOverstatement1(){ assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 0, 0, Map.of(1L, 1)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 10, 1.0, 20, 0.719, 100, 0.014)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context - * where the assertion has no recorded discrepancies. + * where the assertion has no recorded discrepancies. Also check risk measurement in the context + * where the assertion has one 1 vote understatement and varying sample counts. */ @Test public void testNENRecordOneVoteUnderstatement1(){ @@ -222,17 +243,20 @@ public void testNENRecordOneVoteUnderstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, -1), 0, 0, + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 60, + 0.15, 8, Map.of(1L, -1), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 1, 0, 0, 0, Map.of(1L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.464, 10, 0.319, 50, 0.016)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context - * where the assertion has no recorded discrepancies. + * where the assertion has no recorded discrepancies. Also check risk measurement in the context + * where the assertion has one 2 vote overstatement and varying sample counts. */ @Test public void testNENRecordTwoVoteOverstatement1(){ @@ -240,17 +264,20 @@ public void testNENRecordTwoVoteOverstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, 2), 0, 0, + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 102, + 0.22, 8, Map.of(1L, 2), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 1, 0, 0, Map.of(1L, 2)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 20, 1.0, 30, 0.927, 50, 0.099)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has no recorded discrepancies. + * where the assertion has no recorded discrepancies. Also check risk measurement in the context + * where the assertion has one 2 vote understatement and varying sample counts. */ @Test public void testNENRecordTwoVoteUnderstatement1(){ @@ -258,17 +285,20 @@ public void testNENRecordTwoVoteUnderstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, -2), 0, 0, 0, + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 80, + 0.32, 8, Map.of(1L, -2), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 1, 0, Map.of(1L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.221, 10, 0.096, 20, 0.018)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has no recorded discrepancies. + * where the assertion has no recorded discrepancies. Also check risk measurement in the context + * where the assertion has one other discrepancy and varying sample counts. */ @Test public void testNENRecordOther1(){ @@ -276,17 +306,20 @@ public void testNENRecordOther1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, 0), 0, 0, 0, + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 59, + 0.19, 8, Map.of(1L, 0), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 1, Map.of(1L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.619, 10, 0.383, 50, 0.008)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRecordOneVoteOverstatement2(){ @@ -294,18 +327,21 @@ public void testNENRecordOneVoteOverstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1), + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 100, + 0.14, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 2, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 10, 0.943, 50, 0.058, 80, 0.007)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRecordOneVoteUnderstatement2(){ @@ -313,18 +349,21 @@ public void testNENRecordOneVoteUnderstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -1), + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 42, + 0.09, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -1), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 1, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.531, 10, 0.426, 50, 0.072, 80, 0.019)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRecordTwoVoteOverstatement2(){ @@ -332,18 +371,21 @@ public void testNENRecordTwoVoteOverstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 2), + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 88, + 0.21, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 2), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 1, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 2)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 10, 1.0, 50, 0.127, 80, 0.005)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRecordTwoVoteUnderstatement2(){ @@ -358,11 +400,14 @@ public void testNENRecordTwoVoteUnderstatement2(){ assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 2, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.391, 10, 0.306, 50, 0.127, 80, 0.005)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRecordOther2(){ @@ -370,13 +415,15 @@ public void testNENRecordOther2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 50, - 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0), + Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, 35, + 0.05, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 2, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.870, 10, 0.770, 50, 0.291, 80, 0.140)); } @@ -825,7 +872,7 @@ public void testNENComputeDiscrepancyNone(CVRContestInfo info, RecordType audite * "C" are continuing candidates. (In this case, a one vote overstatement). */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) - public void testNENomputeDiscrepancyOneOver1(RecordType recordType){ + public void testNENComputeDiscrepancyOneOver1(RecordType recordType){ log(LOGGER, String.format("testNENComputeDiscrepancyOneOver1[%s]", recordType)); resetMocks(ABCD, BACD, RecordType.UPLOADED, ConsensusValue.YES, recordType, TC); From 0872d5de4005bb8da4e8ee6dfa68e6a1c8287153 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Mon, 29 Jul 2024 14:00:31 +1000 Subject: [PATCH 04/10] Added risk measurement tests for NEB Assertions. --- .../model/assertion/NEBAssertionTests.java | 165 ++++++++++++------ .../model/assertion/NENAssertionTests.java | 2 - 2 files changed, 109 insertions(+), 58 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java index be5003b3..a3bfcc0e 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java @@ -153,21 +153,7 @@ public void testNEBRiskMeasurementNoDiscrepancies(){ 0.2, 8, Map.of(), 0, 0, 0, 0, 0); - // Test risk measurement after 5 samples, no discrepancies - BigDecimal r = a.riskMeasurement(5); - assertEquals(testUtils.doubleComparator.compare(0.603, r.doubleValue()), 0); - - // Test risk measurement after 10 samples, no discrepancies - r = a.riskMeasurement(10); - assertEquals(testUtils.doubleComparator.compare(0.364, r.doubleValue()), 0); - - // Test risk measurement after 50 samples, no discrepancies - r = a.riskMeasurement(50); - assertEquals(testUtils.doubleComparator.compare(0.006, r.doubleValue()), 0); - - // Test risk measurement after 100 samples, no discrepancies - r = a.riskMeasurement(100); - assertEquals(testUtils.doubleComparator.compare(0.0, r.doubleValue()), 0); + checkRiskMeasurement(a, Map.of(5, 0.603, 10, 0.364, 50, 0.006, 100, 0.0)); } /** @@ -212,7 +198,8 @@ public void testNEBRecordNoMatch2(){ } /** - * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement. + * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement. Also check risk + * measurement given one 1 vote overstatement and varying sample counts. */ @Test public void testNEBRecordOneVoteOverstatement1(){ @@ -220,16 +207,19 @@ public void testNEBRecordOneVoteOverstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 123, 0.31, 8, Map.of(1L, 1), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 0, 0, Map.of(1L, 1)); + + checkRiskMeasurement(a, Map.of(5, 0.859, 10, 0.383, 20, 0.076, 50, 0.001)); } /** - * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement. + * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement. Also check risk + * measurement given one 1 vote understatement and varying sample counts. */ @Test public void testNEBRecordOneVoteUnderstatement1(){ @@ -237,16 +227,20 @@ public void testNEBRecordOneVoteUnderstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC,50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC,10, 0.02, 8, Map.of(1L, -1), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 1, 0, 0, 0, Map.of(1L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.643, 10, 0.613, 20, 0.556, 50, + 0.416, 200, 0.098)); } /** - * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement. + * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement. Also check risk + * measurement given one 2 vote overstatement and varying sample counts. */ @Test public void testNEBRecordTwoVoteOverstatement1(){ @@ -254,16 +248,19 @@ public void testNEBRecordTwoVoteOverstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 81, 0.29, 8, Map.of(1L, 2), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 1, 0, 0, Map.of(1L, 2)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 20, 1.0, 50, 0.014)); } /** - * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement. + * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement. Also check risk + * measurement given one 2 vote understatement and varying sample counts. */ @Test public void testNEBRecordTwoVoteUnderstatement1(){ @@ -271,16 +268,19 @@ public void testNEBRecordTwoVoteUnderstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC,50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC,5, 0.001, 8, Map.of(1L, -2), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 1, 0, Map.of(1L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.508, 20, 0.505, 50, 0.497, 500, 0.401)); } /** - * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement. + * Test Assertion::recordDiscrepancy(CVRAuditInfo) for an "other" discrepancy. Also check risk + * measurement given one "other" discrepancy and varying sample counts. */ @Test public void testNEBRecordOther1(){ @@ -288,17 +288,20 @@ public void testNEBRecordOther1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 55, 0.12, 8, Map.of(1L, 0), 0, 0, 0, 0, 0); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 1, Map.of(1L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.743, 10, 0.552, 20, 0.304, 50, 0.051)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRecordOneVoteOverstatement2(){ @@ -313,11 +316,14 @@ public void testNEBRecordOneVoteOverstatement2(){ assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 2, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 20, 0.706, 50, 0.161, 80, 0.037)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRecordOneVoteUnderstatement2(){ @@ -325,18 +331,21 @@ public void testNEBRecordOneVoteUnderstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 63, 0.34, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -1), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 1, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.271, 10, 0.111, 20, 0.019)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRecordTwoVoteOverstatement2(){ @@ -344,18 +353,21 @@ public void testNEBRecordTwoVoteOverstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC,50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC,25, 0.08, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 2), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 1, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 2)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 50, 1.0, 100, 0.516, 200, 0.01)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRecordTwoVoteUnderstatement2(){ @@ -363,18 +375,21 @@ public void testNEBRecordTwoVoteUnderstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 75, 0.25, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 2, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.264, 10, 0.139, 20, 0.039)); } /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRecordOther2(){ @@ -382,13 +397,15 @@ public void testNEBRecordOther2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 77, 0.19, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0), 1, 0, 0, 1, 1); assertTrue(a.recordDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 2, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.608, 10, 0.377, 20, 0.144, 50, 0.008)); } /** @@ -398,7 +415,8 @@ public void testNEBRecordOther2(){ * removeDiscrepancy() does is look for the CVRAuditInfo's ID in its cvrDiscrepancy map. If it is * there, the value matching the ID key is retrieved, the associated discrepancy type * decremented, and the ID removed from the map. If it is not there, then the discrepancy counts - * and the map are not changed, and the method returns false. + * and the map are not changed, and the method returns false. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveNoMatch1(){ @@ -406,17 +424,20 @@ public void testNEBRemoveNoMatch1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 51, 0.11, 8, Map.of(), 0, 0, 0, 0, 0); assertFalse(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of()); + + checkRiskMeasurement(a, Map.of(5, 0.762, 10, 0.581, 20, 0.337, 50, 0.066)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) in the context where no discrepancy has * been computed for the given CVR-ACVR pair, and the assertion has some discrepancies recorded - * already. It should not change the assertion's discrepancy counts. + * already. It should not change the assertion's discrepancy counts. Also check that risk measurement + * yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveNoMatch2(){ @@ -424,17 +445,20 @@ public void testNEBRemoveNoMatch2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 53, 0.12, 8, Map.of(2L, -1, 3L, 1), 1, 1, 0, 0, 0); assertFalse(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 1, 0, 0, 0, Map.of(2L, -1, 3L, 1)); + + checkRiskMeasurement(a, Map.of(5, 0.967, 10, 0.718, 20, 0.396, 50, 0.066)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement. Also check that + * risk measurement yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveOneVoteOverstatement1(){ @@ -442,16 +466,19 @@ public void testNEBRemoveOneVoteOverstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 60, 0.23, 8, Map.of(1L, 1), 1, 0, 0, 0, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L,1)); + + checkRiskMeasurement(a, Map.of(5, 0.556, 10, 0.309, 20, 0.096, 50, 0.003)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement. Also check that + * risk measurement yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveOneVoteUnderstatement1(){ @@ -459,16 +486,19 @@ public void testNEBRemoveOneVoteUnderstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC,50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC,41, 0.09, 8, Map.of(1L, -1), 0, 1, 0, 0, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L,-1)); + + checkRiskMeasurement(a, Map.of(5, 0.801, 10, 0.642, 20, 0.413, 50, 0.109)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement. Also check that + * risk measurement yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveTwoVoteOverstatement1(){ @@ -476,16 +506,19 @@ public void testNEBRemoveTwoVoteOverstatement1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC,50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC,35, 0.06, 8, Map.of(1L, 2), 0, 0, 1, 0, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L,2)); + + checkRiskMeasurement(a, Map.of(5, 0.864, 10, 0.746, 20, 0.557, 50, 0.231)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. Also check that + * risk measurement yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveTwoVoteUnderstatement1(){ @@ -499,10 +532,13 @@ public void testNEBRemoveTwoVoteUnderstatement1(){ assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L,-2)); + + checkRiskMeasurement(a, Map.of(5, 0.781, 10, 0.611, 20, 0.373, 50, 0.085)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for an "other" discrepancy. Also check that + * risk measurement yields the correct values for varying sample sizes. */ @Test public void testNEBRemoveOther1(){ @@ -510,17 +546,20 @@ public void testNEBRemoveOther1(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(1L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 200, 0.5, 8, Map.of(1L, 0), 0, 0, 0, 0, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L,0)); + + checkRiskMeasurement(a, Map.of(5, 0.253, 10, 0.064, 20, 0.004)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement yields + * the correct values for varying sample sizes. */ @Test public void testNEBRemoveOneVoteOverstatement2(){ @@ -535,11 +574,14 @@ public void testNEBRemoveOneVoteOverstatement2(){ assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1)); + + checkRiskMeasurement(a, Map.of(5, 0.768, 10, 0.6, 50, 0.083)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement yields + * the correct values for varying sample sizes. */ @Test public void testNEBRemoveOneVoteUnderstatement2(){ @@ -547,18 +589,21 @@ public void testNEBRemoveOneVoteUnderstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 64, 0.39, 8, Map.of(1L, 0, 2L, 1, 3L, -1, 4L, -1), 1, 2, 0, 0, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 1, 0, 0, 1, Map.of(1L, 0, 2L, 1, 3L, -1, 4L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.46, 10, 0.163, 50, 0.0)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement yields + * the correct values for varying sample sizes. */ @Test public void testNEBRemoveTwoVoteOverstatement2(){ @@ -566,18 +611,21 @@ public void testNEBRemoveTwoVoteOverstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 37, 0.06, 8, Map.of(1L, 2, 2L, 1, 3L, -2, 4L, 2), 1, 0, 2, 1, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 1, 1, 0, Map.of(1L, 2, 2L, 1, 3L, -2, 4L, 2)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 100, 1.0, 150, 0.323, 200, 0.075)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement yields + * the correct values for varying sample sizes. */ @Test public void testNEBRemoveTwoVoteUnderstatement2(){ @@ -585,18 +633,21 @@ public void testNEBRemoveTwoVoteUnderstatement2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC,50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC,71, 0.28, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2), 1, 0, 0, 2, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.476, 10, 0.231, 20, 0.054)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also check that risk measurement yields + * the correct values for varying sample sizes. */ @Test public void testNEBRemoveOther2(){ @@ -604,13 +655,15 @@ public void testNEBRemoveOther2(){ CVRAuditInfo info = new CVRAuditInfo(); info.setID(4L); - Assertion a = createNEBAssertion("W", "L", TC, 50, 0.1, + Assertion a = createNEBAssertion("W", "L", TC, 63, 0.21, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0), 1, 0, 0, 1, 2); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.577, 10, 0.338, 20, 0.117, 50, 0.005)); } /** diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index cf660f02..b27975e5 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -28,7 +28,6 @@ import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; -import au.org.democracydevelopers.corla.util.testUtils; import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -52,7 +51,6 @@ * -- Scoring of NEN assertions. * -- Computation of discrepancies. * -- The logic involved in the re-auditing of ballots. - * -- TODO: Test Assertion::riskMeasurement() * Refer to the Guide to RAIRE for details on how NEN assertions are scored, and how * discrepancies are computed (Part 2, Appendix A.) */ From f7050cb54a70ba58c2492c6d3d58f79d9b9ecb60 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Mon, 29 Jul 2024 14:20:07 +1000 Subject: [PATCH 05/10] Added further risk measurement tests for NEN assertions. --- .../model/assertion/NENAssertionTests.java | 89 +++++++++++++------ 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index b27975e5..ae15419e 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -296,7 +296,7 @@ public void testNENRecordTwoVoteUnderstatement1(){ /** * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context * where the assertion has no recorded discrepancies. Also check risk measurement in the context - * where the assertion has one other discrepancy and varying sample counts. + * where the assertion has one other discrepancies and varying sample counts. */ @Test public void testNENRecordOther1(){ @@ -403,7 +403,7 @@ public void testNENRecordTwoVoteUnderstatement2(){ } /** - * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context + * Test Assertion::recordDiscrepancy(CVRAuditInfo) for an "other" discrepancy, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. */ @@ -433,7 +433,7 @@ public void testNENRecordOther2(){ * removeDiscrepancy() does is look for the CVRAuditInfo's ID in its cvrDiscrepancy map. If it is * there, the value matching the ID key is retrieved, the associated discrepancy type * decremented, and the ID removed from the map. If it is not there, then the discrepancy counts - * and the map are not changed. + * and the map are not changed. Also test risk measurement in this context with varying sample counts. */ @Test public void testNENRemoveNoMatch1(){ @@ -442,17 +442,20 @@ public void testNENRemoveNoMatch1(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(), 0, 0, + 24, 0.07, 8, Map.of(), 0, 0, 0, 0, 0); assertFalse(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of()); + + checkRiskMeasurement(a, Map.of(5, 0.843, 10, 0.710, 50, 0.180, 100, 0.033)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) in the context where no discrepancy has * been computed for the given CVR-ACVR pair, and the assertion has some discrepancies recorded - * already. It should not change the assertion's discrepancy counts. + * already. It should not change the assertion's discrepancy counts. Also test risk measurement in + * this context with varying sample counts. */ @Test public void testNENRemoveNoMatch2(){ @@ -461,16 +464,19 @@ public void testNENRemoveNoMatch2(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(2L, -1, 3L, 1), + 91, 0.412, 8, Map.of(2L, -1, 3L, 1), 1, 1, 0, 0, 0); assertFalse(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 1, 0, 0, 0, Map.of(2L, -1, 3L, 1)); + + checkRiskMeasurement(a, Map.of(5, 0.431, 10, 0.143, 20, 0.016)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement. Also test risk + * measurement in this context with varying sample counts. */ @Test public void testNENRemoveOneVoteOverstatement1(){ @@ -479,15 +485,18 @@ public void testNENRemoveOneVoteOverstatement1(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 1), 1, + 66, 0.341, 8, Map.of(1L, 1), 1, 0, 0, 0, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L, 1)); + + checkRiskMeasurement(a, Map.of(5, 0.408, 10, 0.167, 20, 0.028)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement. Also test risk + * measurement in this context with varying sample counts. */ @Test public void testNENRemoveOneVoteUnderstatement1(){ @@ -496,15 +505,18 @@ public void testNENRemoveOneVoteUnderstatement1(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, -1), 0, + 44, 0.083, 8, Map.of(1L, -1), 0, 1, 0, 0, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.816, 10, 0.665, 20, 0.443, 50, 0.130)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement. Also test risk + * measurement in this context with varying sample counts. */ @Test public void testNENRemoveTwoVoteOverstatement1(){ @@ -513,15 +525,18 @@ public void testNENRemoveTwoVoteOverstatement1(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 2), 0, + 51, 0.099, 8, Map.of(1L, 2), 0, 0, 1, 0, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L, 2)); + + checkRiskMeasurement(a, Map.of(5, 0.783, 10, 0.614, 20, 0.377, 50, 0.087)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. Also test risk + * measurement in this context with varying sample counts. */ @Test public void testNENRemoveTwoVoteUnderstatement1(){ @@ -530,15 +545,18 @@ public void testNENRemoveTwoVoteUnderstatement1(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, -2), 0, + 37, 0.1, 8, Map.of(1L, -2), 0, 0, 0, 1, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.781, 10, 0.611, 20, 0.372, 50, 0.085)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for an "other" discrepancy. Also test risk + * measurement in this context with varying sample counts. */ @Test public void testNENRemoveOther1(){ @@ -547,16 +565,19 @@ public void testNENRemoveOther1(){ info.setID(1L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 0), 0, + 55, 0.131, 8, Map.of(1L, 0), 0, 0, 0, 0, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.722, 10, 0.521, 20, 0.272, 50, 0.039)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRemoveOneVoteOverstatement2(){ @@ -565,17 +586,20 @@ public void testNENRemoveOneVoteOverstatement2(){ info.setID(4L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, + 56, 0.199, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1), 2, 0, 0, 1, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 1)); + + checkRiskMeasurement(a, Map.of(5, 0.594, 10, 0.359, 20, 0.131, 50, 0.006)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRemoveOneVoteUnderstatement2(){ @@ -584,17 +608,20 @@ public void testNENRemoveOneVoteUnderstatement2(){ info.setID(4L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -1, + 50, 0.112, 8, Map.of(1L, 0, 2L, 1, 3L, -1, 4L, -1), 1, 2, 0, 0, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 1, 0, 0, 1, Map.of(1L, 0, 2L, 1, 3L, -1, 4L, -1)); + + checkRiskMeasurement(a, Map.of(5, 0.986, 10, 0.748, 20, 0.43, 50, 0.082)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRemoveTwoVoteOverstatement2(){ @@ -603,17 +630,20 @@ public void testNENRemoveTwoVoteOverstatement2(){ info.setID(4L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 2, 2L, 1, 3L, -2, + 25, 0.066, 8, Map.of(1L, 2, 2L, 1, 3L, -2, 4L, 2), 1, 0, 2, 1, 0); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 1, 1, 0, Map.of(1L, 2, 2L, 1, 3L, -2, 4L, 2)); + + checkRiskMeasurement(a, Map.of(5, 1.0, 50, 1.0, 150, 0.206, 200, 0.041)); } /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRemoveTwoVoteUnderstatement2(){ @@ -622,17 +652,20 @@ public void testNENRemoveTwoVoteUnderstatement2(){ info.setID(4L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, + 54, 0.102, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2), 1, 0, 0, 2, 1); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2)); + + checkRiskMeasurement(a, Map.of(5, 0.764, 10, 0.594, 50, 0.079)); } /** - * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context - * where the assertion has already recorded discrepancies. + * Test Assertion::removeDiscrepancy(CVRAuditInfo) for an "other" discrepancy, in the context + * where the assertion has already recorded discrepancies. Also test risk measurement in this + * context with varying sample counts. */ @Test public void testNENRemoveOther2(){ @@ -641,12 +674,14 @@ public void testNENRemoveOther2(){ info.setID(4L); Assertion a = createNENAssertion("W", "L", TC, AssertionTests.wlo, - 50, 0.1, 8, Map.of(1L, 0, 2L, 1, 3L, -2, + 133, 0.301, 8, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0), 1, 0, 0, 1, 2); assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 1, 0, 0, 1, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, 0)); + + checkRiskMeasurement(a, Map.of(5, 0.449, 10, 0.205, 20, 0.043)); } From 5ed4eb0eebca42d8dc7183290153cf246d145e69 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Wed, 31 Jul 2024 15:31:42 +1000 Subject: [PATCH 06/10] Fixed bug in IRVComparisonAudit::removeDiscrepancy() discovered as a result of tests. Added some tests for risk measurement in IRVComparisonAudit. --- .../corla/model/IRVComparisonAudit.java | 3 +- .../corla/model/IRVComparisonAuditTests.java | 51 ++++++++++++++++--- .../test/resources/SQL/simple-assertions.sql | 1 + 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java index 027bdf87..902c0126 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java @@ -461,7 +461,8 @@ public void removeDiscrepancy(final CVRAuditInfo theRecord, final int theType) { // exists, in each of the audit's assertions. boolean removed = false; for (Assertion a : assertions) { - removed = removed || a.removeDiscrepancy(theRecord); + boolean removed_a = a.removeDiscrepancy(theRecord); + removed = removed || removed_a; } // Update the discrepancy tallies in the base ComparisonAudit class, for reporting purposes, diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index c839e40e..50354418 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -38,6 +38,7 @@ import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.mockito.Mock; +import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import us.freeandfair.corla.model.AuditReason; @@ -49,6 +50,7 @@ import us.freeandfair.corla.model.ContestResult; import javax.transaction.Transactional; +import us.freeandfair.corla.util.Pair; /** * This class contains tests for the functionality present in IRVComparisonAudit. @@ -230,8 +232,6 @@ public void testCreateIRVAuditOneNEBAssertionRiskMeasurement(){ assertEquals(0, testUtils.doubleComparator.compare(1.0, ca.riskMeasurement().doubleValue())); } - - /** * Create an IRVComparisonAudit for a contest with one NEN assertion stored in the database. This * assertion has a diluted margin of 0.12. @@ -593,7 +593,7 @@ public void testComputeDiscrepancyCVR_A_ACVR_ABCD(RecordType auditedType){ } /** - * Test that if we follow up discrepancy computation with an invalid call to recordDiscrepancy(). + * Test that if we follow discrepancy computation with an invalid call to recordDiscrepancy(). * (Invalid in the sense that the provided discrepancy type is not the maximum across the * audit's assertions for the given CVR). */ @@ -617,7 +617,8 @@ public void testRecordWrongDiscrepancy(){ /** * Discrepancy computation for 'Mixed Contest' with CVR "A","B","C","D" and audited ballot - * "B","A","C","D" and recording of the resulting maximum discrepancy of type 2. + * "B","A","C","D" and recording of the resulting maximum discrepancy of type 2. Also checks + * risk measurement before and after the removal of the recorded discrepancy. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_ABCD_ACVR_BACD(RecordType auditedType){ @@ -638,8 +639,33 @@ public void testComputeRecordRemoveDiscrepancyCVR_ABCD_ACVR_BACD(RecordType audi checkDiscrepancies(ca, 0, 1, 0, 0, 0); + riskMeasurementCheck(ca, List.of(Pair.make(1000, 0.214), + Pair.make(1500, 0.019))); + ca.removeDiscrepancy(auditInfo, 2); checkDiscrepancies(ca, 0, 0, 0, 0, 0); + + // ca.riskMeasurement() at this point, where the audited sample count is 1500, should yield + // a risk of 0.001. + Assert.assertEquals(testUtils.doubleComparator.compare(0.001, + ca.riskMeasurement().doubleValue()), 0); + } + + /** + * Given an ordered list of sample size and expected risk value, check that the risk + * measurement method in the given IRVComparisonAudit produces expected values. + * @param audit IRVComparisonAudit whose risk measurement method is being tested. + * @param risks Expected risks for varying audited sample counts (ordered by sample size). + */ + private void riskMeasurementCheck(IRVComparisonAudit audit, final List> risks){ + int sample = 0; + for(Pair entry : risks){ + // Increment sample count according to entry key + audit.signalSampleAudited(entry.first()-sample); + sample += (entry.first()-sample); + final BigDecimal r = audit.riskMeasurement(); + Assert.assertEquals(testUtils.doubleComparator.compare(entry.second(), r.doubleValue()), 0); + } } /** @@ -687,7 +713,8 @@ public void testComputeDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ /** * Discrepancy computation and recording for 'Mixed Contest' with CVR "B","A","C","D" and - * audited ballot "A","B","C","D". The maximum discrepancy is 1. + * audited ballot "A","B","C","D". The maximum discrepancy is 1. Also checks risk measurement + * before the removal of the recorded discrepancies against the ballot/CVR pair. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ @@ -708,13 +735,22 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType audi checkDiscrepancies(ca, 1, 0, 0, 0, 0); + riskMeasurementCheck(ca, List.of(Pair.make(10, 1.0), + Pair.make(100, 0.894), Pair.make(200, 0.415))); + ca.removeDiscrepancy(auditInfo, 1); checkDiscrepancies(ca, 0, 0, 0, 0, 0); + + // ca.riskMeasurement() at this point, where the audited sample count is 200, should yield + // a risk of 0.381. + Assert.assertEquals(testUtils.doubleComparator.compare(0.381, + ca.riskMeasurement().doubleValue()), 0); } /** * Discrepancy computation and recording for 'Mixed Contest 2' with CVR "B","A","C","D" and - * audited ballot "A","B","C","D". The maximum discrepancy is -1. + * audited ballot "A","B","C","D". The maximum discrepancy is -1. Also checks risk measurement + * before the removal of the recorded discrepancies against the ballot/CVR pair. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType auditedType){ @@ -735,6 +771,9 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordTy checkDiscrepancies(ca, 0, 0, 1, 0, 0); + riskMeasurementCheck(ca, List.of(Pair.make(10, 0.412), + Pair.make(50, 0.151), Pair.make(100, 0.045))); + ca.removeDiscrepancy(auditInfo, -1); checkDiscrepancies(ca, 0, 0, 0, 0, 0); } diff --git a/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql b/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql index faf48a12..93fbfa97 100644 --- a/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql +++ b/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql @@ -96,6 +96,7 @@ INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEN', 'Mixed Contest', 100, 0.01, 'C', 100, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'A'); INSERT INTO assertion_assumed_continuing values (25, 'A'); INSERT INTO assertion_assumed_continuing values (25, 'B'); +INSERT INTO assertion_assumed_continuing values (25, 'C'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEB', 'Mixed Contest', 159, 0.0159, 'C', 159, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'B'); From f4144ba2f796d6cd916c958ea9c93915f44f3714 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Wed, 31 Jul 2024 16:52:31 +1000 Subject: [PATCH 07/10] Fleshed out further tests of risk measurement in IRVComparisonAudit. --- .../corla/model/IRVComparisonAuditTests.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index 50354418..e5626ca8 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -714,7 +714,7 @@ public void testComputeDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ /** * Discrepancy computation and recording for 'Mixed Contest' with CVR "B","A","C","D" and * audited ballot "A","B","C","D". The maximum discrepancy is 1. Also checks risk measurement - * before the removal of the recorded discrepancies against the ballot/CVR pair. + * before and after the removal of the recorded discrepancies against the ballot/CVR pair. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ @@ -750,7 +750,7 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType audi /** * Discrepancy computation and recording for 'Mixed Contest 2' with CVR "B","A","C","D" and * audited ballot "A","B","C","D". The maximum discrepancy is -1. Also checks risk measurement - * before the removal of the recorded discrepancies against the ballot/CVR pair. + * before and after the removal of the recorded discrepancies against the ballot/CVR pair. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType auditedType){ @@ -776,11 +776,17 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordTy ca.removeDiscrepancy(auditInfo, -1); checkDiscrepancies(ca, 0, 0, 0, 0, 0); + + // ca.riskMeasurement() at this point, where the audited sample count is 100, should yield + // a risk of 0.088. + Assert.assertEquals(testUtils.doubleComparator.compare(0.088, + ca.riskMeasurement().doubleValue()), 0); } /** * Discrepancy computation and recording for 'Simple Contest 3' with CVR "B","A","C","D" and - * audited ballot "A","B","C","D". The maximum discrepancy is -2. + * audited ballot "A","B","C","D". The maximum discrepancy is -2. Also checks risk measurement + * before and after the removal of the recorded discrepancies against the ballot/CVR pair. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_simple3(RecordType auditedType){ @@ -801,8 +807,16 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_simple3(RecordT checkDiscrepancies(ca, 0, 0, 0, 1, 0); + riskMeasurementCheck(ca, List.of(Pair.make(10, 0.463), + Pair.make(50, 0.314), Pair.make(100, 0.194))); + ca.removeDiscrepancy(auditInfo, -2); checkDiscrepancies(ca, 0, 0, 0, 0, 0); + + // ca.riskMeasurement() at this point, where the audited sample count is 100, should yield + // a risk of 0.380. + Assert.assertEquals(testUtils.doubleComparator.compare(0.380, + ca.riskMeasurement().doubleValue()), 0); } /** @@ -864,7 +878,8 @@ public void testComputeDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ /** * Discrepancy computation and recording for 'Mixed Contest' with CVR blank and audited ballot - * "A","B","C","D". The maximum discrepancy is 0. + * "A","B","C","D". The maximum discrepancy is 0. Also checks risk measurement before and after + * the removal of the recorded discrepancies against the ballot/CVR pair. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ @@ -885,8 +900,16 @@ public void testComputeRecordRemoveDiscrepancyCVR_blank_ACVR_ABCD(RecordType aud checkDiscrepancies(ca, 0, 0, 0, 0, 1); + riskMeasurementCheck(ca, List.of(Pair.make(10, 0.926), + Pair.make(50, 0.681), Pair.make(100, 0.464))); + ca.removeDiscrepancy(auditInfo, 0); checkDiscrepancies(ca, 0, 0, 0, 0, 0); + + // ca.riskMeasurement() at this point, where the audited sample count is , should yield + // a risk of . + Assert.assertEquals(testUtils.doubleComparator.compare(0.617, + ca.riskMeasurement().doubleValue()), 0); } /** From dfca018c296b2210c7a45808cf34467f2312c34a Mon Sep 17 00:00:00 2001 From: michelleblom Date: Wed, 31 Jul 2024 16:59:22 +1000 Subject: [PATCH 08/10] Fixed two risk measurement tests in NENAssertionTests. --- .../corla/model/assertion/NENAssertionTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index ae15419e..a0c08d4d 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -399,7 +399,7 @@ public void testNENRecordTwoVoteUnderstatement2(){ checkCountsDiscrepancyMap(a, 1, 0, 0, 2, 1, Map.of(1L, 0, 2L, 1, 3L, -2, 4L, -2)); - checkRiskMeasurement(a, Map.of(5, 0.391, 10, 0.306, 50, 0.127, 80, 0.005)); + checkRiskMeasurement(a, Map.of(5, 0.391, 10, 0.306, 50, 0.043, 80, 0.01)); } /** @@ -551,7 +551,7 @@ public void testNENRemoveTwoVoteUnderstatement1(){ assertTrue(a.removeDiscrepancy(info)); checkCountsDiscrepancyMap(a, 0, 0, 0, 0, 0, Map.of(1L, -2)); - checkRiskMeasurement(a, Map.of(5, 0.781, 10, 0.611, 20, 0.372, 50, 0.085)); + checkRiskMeasurement(a, Map.of(5, 0.781, 10, 0.611, 20, 0.373, 50, 0.085)); } /** From 291e79300e91e1206f8f848ef46d9c34a8669167 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Thu, 1 Aug 2024 18:29:42 +1000 Subject: [PATCH 09/10] Removed excess whitespace. --- .../corla/model/assertion/NENAssertionTests.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index a0c08d4d..55b28f16 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -424,8 +424,6 @@ public void testNENRecordOther2(){ checkRiskMeasurement(a, Map.of(5, 0.870, 10, 0.770, 50, 0.291, 80, 0.140)); } - - /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) in the context where no discrepancy has * been recorded for the given CVR-ACVR pair, and the assertion has no prior recorded From 54ea0aa4bf211fba7a0238a5eb0277b90838aa61 Mon Sep 17 00:00:00 2001 From: michelleblom Date: Fri, 2 Aug 2024 15:45:58 +1000 Subject: [PATCH 10/10] Addressed requested changes from review. --- .../corla/model/IRVComparisonAuditTests.java | 23 +++++---- .../corla/model/assertion/AssertionTests.java | 3 +- .../model/assertion/NEBAssertionTests.java | 2 + .../model/assertion/NENAssertionTests.java | 48 +++++++++++++++++++ 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index e5626ca8..e49e950c 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -23,7 +23,7 @@ import static au.org.democracydevelopers.corla.util.testUtils.log; import static org.mockito.Mockito.when; -import static org.testng.AssertJUnit.assertEquals; +import static org.testng.Assert.assertEquals; import au.org.democracydevelopers.corla.model.assertion.Assertion; import au.org.democracydevelopers.corla.model.assertion.AssertionTests; @@ -593,9 +593,9 @@ public void testComputeDiscrepancyCVR_A_ACVR_ABCD(RecordType auditedType){ } /** - * Test that if we follow discrepancy computation with an invalid call to recordDiscrepancy(). - * (Invalid in the sense that the provided discrepancy type is not the maximum across the - * audit's assertions for the given CVR). + * Test that if we follow discrepancy computation with an invalid call to recordDiscrepancy() then + * an IllegalArgumentException is thrown. (Invalid in the sense that the provided discrepancy type + * is not the maximum across the audit's assertions for the given CVR). */ @Test(expectedExceptions = IllegalArgumentException.class) public void testRecordWrongDiscrepancy(){ @@ -714,7 +714,9 @@ public void testComputeDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ /** * Discrepancy computation and recording for 'Mixed Contest' with CVR "B","A","C","D" and * audited ballot "A","B","C","D". The maximum discrepancy is 1. Also checks risk measurement - * before and after the removal of the recorded discrepancies against the ballot/CVR pair. + * before and after the removal of the recorded discrepancies against the ballot/CVR pair. We + * use Equation 9 in Stark's Super Simple Simultaneous Comparison Single-Ballot Risk Limiting + * Audits to compute the expected risk values. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType auditedType){ @@ -750,7 +752,9 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD(RecordType audi /** * Discrepancy computation and recording for 'Mixed Contest 2' with CVR "B","A","C","D" and * audited ballot "A","B","C","D". The maximum discrepancy is -1. Also checks risk measurement - * before and after the removal of the recorded discrepancies against the ballot/CVR pair. + * before and after the removal of the recorded discrepancies against the ballot/CVR pair. We + * use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot Risk Limiting Audits to compute the expected + * risk values. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordType auditedType){ @@ -786,7 +790,9 @@ public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_mixed2(RecordTy /** * Discrepancy computation and recording for 'Simple Contest 3' with CVR "B","A","C","D" and * audited ballot "A","B","C","D". The maximum discrepancy is -2. Also checks risk measurement - * before and after the removal of the recorded discrepancies against the ballot/CVR pair. + * before and after the removal of the recorded discrepancies against the ballot/CVR pair. We + * use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot Risk Limiting Audits to compute the expected + * risk values. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_BACD_ACVR_ABCD_simple3(RecordType auditedType){ @@ -879,7 +885,8 @@ public void testComputeDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ /** * Discrepancy computation and recording for 'Mixed Contest' with CVR blank and audited ballot * "A","B","C","D". The maximum discrepancy is 0. Also checks risk measurement before and after - * the removal of the recorded discrepancies against the ballot/CVR pair. + * the removal of the recorded discrepancies against the ballot/CVR pair. We use Equation 9 in + * Stark's Super Simple Simultaneous Single-Ballot Risk Limiting Audits to compute the expected risk values. */ @Test(dataProvider = "AuditedRecordTypes", dataProviderClass = AssertionTests.class) public void testComputeRecordRemoveDiscrepancyCVR_blank_ACVR_ABCD(RecordType auditedType){ diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java index 3b5cfdca..cd965f24 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/AssertionTests.java @@ -664,7 +664,8 @@ public static void checkCountsDiscrepancyMap(final Assertion a, int oneOver, int /** * Checks whether an assertion's riskMeasurement() method calculates the correct risks for - * varying sample numbers. + * varying sample numbers (note that discrepancies may be present and stored in the given + * Assertion). * @param a Assertion whose riskMeasurement() method we are testing. * @param risks Map of expected sample counts to risk values. */ diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java index be36f501..724a340f 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java @@ -53,6 +53,8 @@ * -- Scoring of NEB assertions. * -- Computation of discrepancies for NEB assertions. * -- The logic involved in the re-auditing of ballots. + * -- Risk measurement (we use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values). * Refer to the Guide to RAIRE for details on how NEB assertions are scored, and how * discrepancies are computed (Part 2, Appendix A). */ diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index 647be1ea..d31d066b 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -51,6 +51,8 @@ * -- Scoring of NEN assertions. * -- Computation of discrepancies. * -- The logic involved in the re-auditing of ballots. + * -- Risk measurement (we use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values). * Refer to the Guide to RAIRE for details on how NEN assertions are scored, and how * discrepancies are computed (Part 2, Appendix A.) */ @@ -195,6 +197,8 @@ public void testNENRecordNoMatch2(){ /** * Test riskMeasurement() for an NEN assertion with no discrepancies. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRiskMeasurementNoDiscrepancies(){ @@ -213,6 +217,8 @@ public void testNENRiskMeasurementNoDiscrepancies(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context * where the assertion has no recorded discrepancies. Also check risk measurement given one * 1 vote overstatement and varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordOneVoteOverstatement1(){ @@ -234,6 +240,8 @@ public void testNENRecordOneVoteOverstatement1(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context * where the assertion has no recorded discrepancies. Also check risk measurement in the context * where the assertion has one 1 vote understatement and varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordOneVoteUnderstatement1(){ @@ -255,6 +263,8 @@ public void testNENRecordOneVoteUnderstatement1(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context * where the assertion has no recorded discrepancies. Also check risk measurement in the context * where the assertion has one 2 vote overstatement and varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordTwoVoteOverstatement1(){ @@ -276,6 +286,8 @@ public void testNENRecordTwoVoteOverstatement1(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context * where the assertion has no recorded discrepancies. Also check risk measurement in the context * where the assertion has one 2 vote understatement and varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordTwoVoteUnderstatement1(){ @@ -297,6 +309,8 @@ public void testNENRecordTwoVoteUnderstatement1(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context * where the assertion has no recorded discrepancies. Also check risk measurement in the context * where the assertion has one other discrepancies and varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordOther1(){ @@ -318,6 +332,8 @@ public void testNENRecordOther1(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordOneVoteOverstatement2(){ @@ -340,6 +356,8 @@ public void testNENRecordOneVoteOverstatement2(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordOneVoteUnderstatement2(){ @@ -362,6 +380,8 @@ public void testNENRecordOneVoteUnderstatement2(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordTwoVoteOverstatement2(){ @@ -384,6 +404,8 @@ public void testNENRecordTwoVoteOverstatement2(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordTwoVoteUnderstatement2(){ @@ -406,6 +428,8 @@ public void testNENRecordTwoVoteUnderstatement2(){ * Test Assertion::recordDiscrepancy(CVRAuditInfo) for an "other" discrepancy, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRecordOther2(){ @@ -432,6 +456,8 @@ public void testNENRecordOther2(){ * there, the value matching the ID key is retrieved, the associated discrepancy type * decremented, and the ID removed from the map. If it is not there, then the discrepancy counts * and the map are not changed. Also test risk measurement in this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveNoMatch1(){ @@ -454,6 +480,8 @@ public void testNENRemoveNoMatch1(){ * been computed for the given CVR-ACVR pair, and the assertion has some discrepancies recorded * already. It should not change the assertion's discrepancy counts. Also test risk measurement in * this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveNoMatch2(){ @@ -475,6 +503,8 @@ public void testNENRemoveNoMatch2(){ /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement. Also test risk * measurement in this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveOneVoteOverstatement1(){ @@ -495,6 +525,8 @@ public void testNENRemoveOneVoteOverstatement1(){ /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement. Also test risk * measurement in this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveOneVoteUnderstatement1(){ @@ -515,6 +547,8 @@ public void testNENRemoveOneVoteUnderstatement1(){ /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement. Also test risk * measurement in this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveTwoVoteOverstatement1(){ @@ -535,6 +569,8 @@ public void testNENRemoveTwoVoteOverstatement1(){ /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement. Also test risk * measurement in this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveTwoVoteUnderstatement1(){ @@ -555,6 +591,8 @@ public void testNENRemoveTwoVoteUnderstatement1(){ /** * Test Assertion::removeDiscrepancy(CVRAuditInfo) for an "other" discrepancy. Also test risk * measurement in this context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveOther1(){ @@ -576,6 +614,8 @@ public void testNENRemoveOther1(){ * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote overstatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveOneVoteOverstatement2(){ @@ -598,6 +638,8 @@ public void testNENRemoveOneVoteOverstatement2(){ * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a one vote understatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveOneVoteUnderstatement2(){ @@ -620,6 +662,8 @@ public void testNENRemoveOneVoteUnderstatement2(){ * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote overstatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveTwoVoteOverstatement2(){ @@ -642,6 +686,8 @@ public void testNENRemoveTwoVoteOverstatement2(){ * Test Assertion::removeDiscrepancy(CVRAuditInfo) for a two vote understatement, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveTwoVoteUnderstatement2(){ @@ -664,6 +710,8 @@ public void testNENRemoveTwoVoteUnderstatement2(){ * Test Assertion::removeDiscrepancy(CVRAuditInfo) for an "other" discrepancy, in the context * where the assertion has already recorded discrepancies. Also test risk measurement in this * context with varying sample counts. + * We use Equation 9 in Stark's Super Simple Simultaneous Single-Ballot + * Risk Limiting Audits to compute the expected risk values. */ @Test public void testNENRemoveOther2(){