Votetest: Voting system logic testing for the VVSG-NI

Draft — Version 1.0

April 1, 2009

Legal notices

Test materials disclaimer

This document and associated files have been prepared by the National Institute of Standards and Technology (NIST) and represent draft test materials for the Election Assistance Commission’s next iteration of the VVSG. It is a preliminary draft and does not represent a consensus view or recommendation from NIST, nor does it represent any policy positions of NIST.

Software disclaimer

This software was developed at the National Institute of Standards and Technology by employees of the Federal Government in the course of their official duties. Pursuant to Title 17 Section 105 of the United States Code this software is not subject to copyright protection and is in the public domain. This software is an experimental system. NIST assumes no responsibility whatsoever for its use by other parties, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. We would appreciate acknowledgement if the software is used.

This software can be redistributed and/or modified freely provided that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.

Commercial products disclaimer

Specific computer hardware and software products are identified in this paper to support reproducibility of results. Such identification does not imply recommendation or endorsement by the National Institute of Standards and Technology, nor does it imply that the products identified are necessarily the best available for the purpose.

Contents

1 Introduction
 1.1 What Votetest Is
 1.2 What Votetest Is Not
 1.3 Structure of this document
2 Background
3 Test materials
 3.1 Overview of test materials
 3.2 File listing
 3.3 How to use Votetest
 3.4 Applicability to VVSG 2005
 3.5 Data model
 3.6 Basic schema
 3.7 Basic test suite
 3.8 Required test cases not included in the basic Votetest test suite
 3.9 Requirements trace
4 Advanced schema
 4.1 Conveniences
 4.2 Adaptation
 4.3 Integrity checks
 4.4 Translation of logic model
5 Advanced test development environment
 5.1 Software prerequisites
 5.2 Hardware prerequisites
 5.3 File listing
 5.4 Installation
 5.5 Infrastructure
 5.6 Test suite self-tests
 5.7 TestGenerator
 5.8 On performance and scalability
 5.9 PostgreSQL configuration help
 5.10 Votetest under Cygwin
6 New test case walk-through
 6.1 Introduction
 6.2 Example election
 6.3 Modelling the election in Votetest
 6.4 Representing the election in the database
 6.5 Generating relevant test cases
 6.6 Reports generated by Votetest
 6.7 Conclusion

List of Figures

How to use a test
Example Votetest test
Example EMS interaction
Example optical scan ballot
Example DRE voting script
“Observed results” for example
“Expected results” for example
Vote data model for core requirements
Sample report
10 Model subset for ballot styles
11 Model subset for ballots
12 Model subset for affiliations and endorsements
13 Model subset for reporting

List of Tables

Basic files in the Votetest distribution
Basic test suite
Additional required test cases
Integrity checks
Advanced files in the Votetest distribution
ReportGenerator return codes
Output of Infrastructure-PairsCoverage
Key to headings appearing in Table 7
Constraint violation tests
10 Scalability figures
11 Party information
12 Precinct relationships
13 Ballot styles
14 Endorsements
15 Ballot style—reporting context associations
16 BallotStyle
17 Contest
18 BallotStyleContestAssociation
19 Choice (before write-ins)
20 Party
21 ReportingContext
22 BallotStyleReportingContextAssociation
23 Endorsement
24 BallotCategory, rejected and blank ballot distributions
25 Precinct and BallotStyle distributions
26 Undervote distributions
27 Choices for anticipated write-ins
28 Canonical choice and write-in distribution

1 Introduction

1.1 What Votetest Is

The Votetest distribution, or simply “Votetest” for short, is a package of public domain data, software, and documentation that the National Institute of Standards and Technology (NIST) is developing. Its purpose is to provide conformance test materials for use by Voting System Testing Laboratories. These test materials are used to assess conformity to the Voluntary Voting System Guidelines (VVSG) [1].

Votetest defines abstract tests that exercise every phase of the voting process from election definition through report generation. The scope of functionality that they cover to some extent is therefore quite broad. The abstract tests are “realized” according to the specifics of the voting system being tested.

In addition to the abstract tests, Votetest includes the expected results for each test, a means to derive the expected results for newly developed tests, a test generator, and detailed documentation.

1.2 What Votetest Is Not

Votetest CANNOT simply be plugged into a voting system to obtain a verdict on conformity. The tests that are defined abstractly by Votetest must be translated into concrete tests that can actually be run on a given voting system. This task requires the same expertise and diligence that test labs have employed in the past when developing their own tests from scratch.

Votetest, by itself, DOES NOT provide complete coverage of the VVSG. Votetest is only one tool that is used in one part of the conformity assessment process. It is designed not to be used in isolation, but rather to complement the other testing activities, which include the physical configuration audit, documentation and design reviews, electromagnetic compatibility and environmental testing, security reviews, usability and accessibility assessments, the volume test (mock election), and the evaluation of reliability, accuracy, and misfeed rates. Test labs should consult Part 3 of the VVSG [1] regarding the full scope of testing to be performed.

Votetest DOES NOT address “fitness for use.” Its scope is strictly limited to conformity assessment. It is not a substitute for Voting System Testing Laboratories’ diligent assessments of the full scope of voting system functionality (including vendor-specific functionality), nor does it obviate the need for acceptance testing by jurisdictions.

1.3 Structure of this document

Section 2 provides additional background of general interest. Section 3 provides detailed technical documentation on the portions of Votetest that are essential to performing conformity assessment. Section 4 and Section 5 provide detailed technical documentation on the portions of Votetest that could be used to develop additional test cases. Finally, Section 6 walks through the process of defining a new test case based on an example election.

2 Background

By authorization of the 2002 Help America Vote Act (HAVA), NIST is assisting the Election Assistance Commission (EAC) with the implementation of Voluntary Voting System Guidelines (VVSG) for states and local governments conducting Federal elections. The EAC’s Technical Guidelines Development Committee (TGDC) in collaboration with NIST researchers has developed a draft of the next iteration of the VVSG. The draft document is a set of detailed technical requirements addressing core requirements, human factors, privacy, security, and transparency of the next generation of voting systems. The EAC plans to issue the next VVSG after receiving and reviewing public comments.

NIST is developing a set of uniform public test suites to be used as part of the EAC’s Testing and Certification Program. Test labs will be able to use these freely available test suites to help determine that VVSG requirements are met by voting systems. The test suites address human factors, security and core functionality requirements for voting systems as specified in the VVSG. Use of the public test suites will produce consistent results and promote transparency of the testing process. The test suites can also assist manufacturers in the development of conforming products by providing precise test specifications. Also, they will help reduce the cost of testing since each test lab would no longer need to develop its own test suites. Finally, a uniform set of public test suites can increase election officials’ and voters’ confidence that voting systems conform to VVSG requirements.

3 Test materials

3.1 Overview of test materials

This is the documentation for the test materials portion of the Votetest distribution. Its intended audience is test labs accredited by the Election Assistance Commission to perform voting system certification testing. The test lab is assumed to have competence with the following:

Votetest includes the following components:

While Votetest includes both basic and advanced materials, only the data model (Section 3.5), basic schema (Section 3.6), basic test suite (Section 3.7) and expected results (Section 3.3.4.3) are essential to the conformance testing process. Section 3.3 explains in more detail how Votetest is used in that process.

3.2 File listing

The Votetest distribution is provided as a zip file named votetest-YYYYMMDD.zip and alternately as a compressed tar file named votetest-YYYYMMDD.tar.bz2, where YYYYMMDD is a sequence of digits indicating the date of the release. The files contained in the distribution are described in Table 1.


Table 1: Basic files in the Votetest distribution
Files
Description
Details



disclaimer.txt

Text file containing the test materials disclaimer.

Legal notices



COPYING

Text file containing the software disclaimer.

Legal notices



doc/

Subdirectory containing the source and PDF of this documentation.

N/A



1-basic-description.sql

SQL, abstract test cases of the basic test suite (92 files).

Section 3.7



sample_output/

Subdirectory containing text files that provide the expected results for each test case and each integrity check (106 files).

Section 3.3.4.3



sample_output_kill-overvotes/

Same, but with overvoting suppressed (106 files).

Section 3.3.4.3



ChangeLog

Text file containing the change log for the Votetest distribution.

N/A



... other files ...

Files pertaining to the advanced test development environment.

Table 5




3.3 How to use Votetest

The steps listed in the following subsections fit within the context of the overall conformity assessment process that is described in [3, Part 3 Chapter 2]. Thus, in practice, the steps will not necessarily follow directly one to the next as is implied here, because there may be other conformity assessment activities occurring in between or parallel to them.

3.3.1 Determine relevant voting variation classes—system level

The Technical Data Package received from the manufacturer is required to include an implementation statement, which is specified by the Conformance Clause of the VVSG [3, Part 1 Section 2.4]. This implementation statement includes the manufacturer’s classification of the voting system as a whole and of the different devices of which it is comprised. For Votetest, the relevant voting variation classes are determined by examining the implementation statement. (The completeness and correctness of the manufacturer’s classification should have been established in a preceding documentation and design review; see [3, Part 3 Req. 4.2-C].) The system and device classes that the manufacturer may reference are defined in the Conformance Clause [3, Part 1 Section 2.5].

Usually, multiple classes will apply to a given voting system or voting device. For example, if a DRE supports both N-of-M and ranked order voting variations, it will be classified as both an N-of-M voting device and a Ranked order voting device in addition to being classified as a DRE. This multiple classification allows multiple sets of tests to apply so that all of the supported functionality will be tested.

At this stage, what is relevant are the system-level classes. If the system as a whole does not support a particular voting variation, then support for that variation in isolated devices is irrelevant.

3.3.2 Determine applicable tests

Table 2 (coming up in Section 3.7) lists the tests in the basic Votetest test suite and indicates the voting variations that are used by each test. The set of tests applicable to a given voting system is the set of all tests that do not use any voting variations that the voting system does not support. In other words, every test is applicable unless it is specifically excluded, and a test is excluded only if it uses a voting variation that, according to the reviewed and accepted implementation statement, the system does not implement.

For example, if a voting system did not support ranked order voting, the following tests would be excluded:

1-basic-NoBallots-RankedOrder.sql
1-basic-RankedOrder-1.sql
1-basic-RankedOrder-2.sql
1-basic-StraightParty-RankedOrder.sql
1-basic-Primary-RankedOrder.sql
1-basic-BallotRotation-RankedOrder.sql
1-basic-AbsenteeByCategory-RankedOrder.sql
1-basic-Cumulative-RankedOrder.sql
1-basic-SplitPrecinct-RankedOrder.sql
1-basic-RankedOrder-WriteIns.sql
1-basic-RankedOrder-NofM.sql
1-basic-RankedOrder-Provisional.sql
1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql

There is a special case regarding absentee voting that will be addressed in Section 3.7.

3.3.3 Multiply tests for different interfaces and devices

At this point the test lab has the beginnings of a test plan with a list of the tests that are applicable to the voting system as a whole. That plan must now be expanded down to the device level.

When a voting system offers multiple paths by which voting can occur, such as a touchscreen interface and an audio ballot on one device plus optical scanning of paper ballots by another device, each of these paths must be tested. It is entirely possible for a failure to be specific to a particular user interface. For example, some controls that can be activated using a touchscreen might be incorrectly skipped over if an input device with a navigational model (next option, previous option) is used.

Several different strategies could be used to divide or replicate the testing among the available interfaces and devices. However, since most tests in the basic test suite are small by design, with relatively few ballots, the recommended approach is to repeat each test on each device and interface separately. For large tests such as the volume test (mock election), one would instead divide the ballots among the available devices and interfaces using a distribution that imitates a realistic election.

Absentee voting is again a special case. In systems where absentee ballots follow a separate path from other ballots (e.g., a dedicated central count optical scanner), it makes sense to repeat tests over the absentee interface. However, the basic test suite also contains tests specifically designated for absentee voting, that mix absentee ballots with non-absentee ballots. These designated tests would be executed using both the absentee and non-absentee paths at the same time, not repeated on each path separately.

As noted in [3, Part 1 Section 6.2], it is not necessarily the case that every device in the system would support every voting variation claimed at the system level. Thus there may be cases where it is not possible to multiply certain tests onto certain devices. However, other devices that do pass those tests must be present to enable satisfaction of the system-level claim.

3.3.4 Perform testing

Once the test plan has been approved, work on implementing the plan can begin. The steps that the test lab must do for each applicable Votetest test are summarized in Figure 1 and explained in more detail in the following subsections.

Translate test from Votetest model to voting system Since interfaces to voting systems vary widely, the test lab must use the basic test suite as input from which to generate system-specific tests. For each applicable test, the test lab translates the abstract, SQL version included in the basic test suite (Section 3.7) into a concrete test for the voting system under test, thereby “realizing” the test. The data model (Section 3.5) and basic schema (Section 3.6) are essential to understanding the abstract tests so that they can be realized correctly.

Figure 2 shows an example of a Votetest test expressed in SQL. It specifies both the election definition and the ballots and votes to be cast.

Things to be determined for the voting system under test would include:



Figure 1: How to use a test

PIC




Figure 2: Example Votetest test

PIC




Figure 3: Example EMS interaction

PIC




Figure 4: Example optical scan ballot

PIC




Figure 5: Example DRE voting script

If at any step you make a mistake performing the Action for tester, go directly to the Botched Test Checklist.

If at any step the DRE does not respond as indicated under Expected DRE response, go directly to the Anomaly Checklist.

Action for tester
Expected DRE response


1. Insert the card that the poll worker gave you into the slot on the front of the DRE.

The DRE should show the text “Ballot activated” followed by instructions to voters.



2. Touch NEXT on the touch-screen.

The DRE should advance to the PARKING COMMITTEE contest.



3. Touch the box to the left of Beeso Tu.

The box should turn green.



4. Touch the box to the left of Tayra Tree.

The box should turn green.



5. Touch NEXT on the touch-screen.

The DRE should advance to the summary screen.



6. Touch CAST BALLOT on the touch-screen.

The DRE should display “Please remove the card and deposit it in the shoe box near the exit.” and “Thank you for voting.”



7. Remove the card.

The DRE should return to its welcome screen, which shows the text “Precinct 1” and “Please insert card.”




Execute test For each test case, the test lab executes the “realized” test case within the voting system under test following the general test template specified in [3, Part 3 Section 5.2.2.1]:

  1. Establish initial state (clean out data from previous tests, verify resident software/firmware);
  2. Program election and prepare ballots and/or ballot styles;
  3. Generate pre-election audit reports;
  4. Configure voting devices;
  5. Run system readiness tests;
  6. Generate system readiness audit reports;
  7. Precinct count only:
    1. Open poll;
    2. Run precinct count test ballots; and
    3. Close poll.
  8. Run central count test ballots (central count / absentee ballots only);
  9. Generate in-process audit reports;
  10. Generate data reports for the specified reporting contexts;
  11. Inspect ballot counters; and
  12. Inspect reports.

This template essentially puts the voting system through the technical paces of a very small election for each test. Although the election definition is simple and the number of ballots small, the process from beginning to end exercises all of the voting system functions that would be used in an election. The surrounding procedures and environment are, of course, quite different, and vastly simplified in the laboratory testing environment, so it is not a mock election in the sense that the volume test is.

Also see [3, Part 3 Section 2.5] regarding the test conditions, test fixtures, test data requirements, and test practices that apply.

Compare observed and expected results As part of the test execution, the voting system under test is instructed to generate vote data reports. These contain the “observed results” with respect to ballot counts and vote totals. Figure 6 shows an example report from the hypothetical voting system.

The “expected results” for all of the test cases are saved as text files in two subdirectories of the Votetest distribution. The subdirectory sample_output contains the results expected from the test cases as written, while the subdirectory sample_output_kill-overvotes contains the results expected from the test cases with overvotes changed to undervotes.

Each results file has the following organization:

An example is shown in Figure 7. Comparing the “observed results” in Figure 6 and the “expected results” in Figure 7, it is clear that the quantities reported for candidate vote totals are identical, even though the form of the reports is somewhat different. The test lab would find no discrepancy in those results. However, the observed results shown in Figure 6 are not in and of themselves sufficient to satisfy all of the VVSG requirements on reporting. For example, [3, Part 1 Req. 7.8.3.2-A through D] specify additional information that the voting system under test must provide in some report if the system is to be found conforming.

The other reports generated as part of the test (pre-election reports, etc.) would also be inspected to look for anomalies and to assess conformity to the L&A testing and auditability requirements of the VVSG. Similarly, any unexpected behavior of the voting system observed by the tester would be assessed by the resident expert (possibly but not necessarily the same person) to determine if a nonconformity was demonstrated.

Some notes and cautions apply:

  1. Many test cases contain overvotes. However, in some voting systems, overvoting is prevented. Votetest handles this possibility through test transformation. For each ballot that overvotes a particular contest, an SQL script (Infrastructure-KillOvervotes.sql) deletes that ballot’s votes in that contest, with the effect that the contest is undervoted instead of overvoted. Expected results are provided both for the test cases as originally written (in sample_output) and for the test cases transformed to remove overvotes (in sample_output_kill-overvotes).
  2. For Ballot rotation tests, the test lab must check to make sure that the voting system does in fact produce and utilize rotated ballots as specified in the VVSG [1]. The assignment of ballot choices to specific ballot positions is abstracted out of the Votetest data model, so the rotation behavior is not represented in the “expected results.”
  3. Ranked order logic is not normative. The algorithm used to derive the “expected results” for ranked order contests is only one example of conforming behavior. This algorithm is not recommended or endorsed by the National Institute of Standards and Technology for use in elections and it is probably not the best algorithm available for the purpose. It is used in Votetest only to provide output for comparison in simple cases where the implementation-dependent details have no impact.



Figure 6: “Observed results” for example

NO-SUCH JURISDICTION
GENERAL ELECTION
MAY 16, 2008
REPORT GENERATED AT 2008-05-16 16:12:23

Total % Election Day Early Provisional
Precincts Counted 1 100.00
Registered Voters 9
Ballots Cast / Turnout 9 100.00 9 0 0






PARKING COMMITTEE (Vote for at most 2)






FOWER, CAR TAY 4 40.00 4 0 0
TREE, TAYRA 3 30.00 3 0 0
TU, BEESO 2 20.00 2 0 0
WON, OONA 1 10.00 1 0 0
ZAYRO, NADA 0 0.00 0 0 0
Write-Ins (combined) 0 0.00 0 0 0
Overvotes 2 2 0 0
Undervotes 6 6 0 0




Figure 7: “Expected results” for example

PIC


3.4 Applicability to VVSG 2005

The 2005 Voluntary Voting System Guidelines (VVSG 2005) [4] have several important differences from the next VVSG [1] that impact the application of Votetest.

There is no technical incompatibility that would outright prevent the use of any of the Votetest test cases in a conformity assessment for VVSG 2005, provided that the draft next VVSG accurately reflects the intent of the requirements of VVSG 2005. A focused effort to develop test cases for VVSG 2005 instead of the next VVSG would not necessarily arrive at a different set of test cases.

3.5 Data model



Figure 8: Vote data model for core requirements

PIC


The data model for voting system core requirements is described in Figure 8 by a Unified Modeling Language (UML) class diagram [5]. Following sections explain the diagram.

3.5.1 Assumptions

All entities in this data model are implicitly scoped by an election. It is assumed that different elections are stored in different databases, and any reuse of definitions from one election to another is accomplished by copying over the relevant data.

This data model is constructed from an integrated, top-level viewpoint. In practice, different portions of the system will deal with only a portion of the data at any given time. It is expected that test labs will project and extract data from the integrated schema as needed to support these limited viewpoints for testing.

The results of tabulation and reporting are derived from the content of the data model, but those results are themselves outside the scope of the model.

3.5.2 POD (Plain Old Data) types

BallotCategory
(enum) Arbitrary tag that may be applied to Ballots; e.g., Early, Regular, InPerson, Absentee, Provisional, Challenged, NotRegistered, WrongPrecinct, IneligibleVoter. Categories are jurisdiction-defined but are likely to include several classes of provisional.
Boolean
Normal true/false data type.
ContestCountingLogic
(enum) N-of-M, Cumulative, Ranked order, or Straight party selection. (1-of-M is a special case of N-of-M.) The tabulation logic for a straight party selection Contest is implicitly 1-of-M, but with side-effects for other Contests.
NaturalNumber
Integer greater than zero.
Text
Normal character string.
WholeNumber
Integer greater than or equal to zero.

3.5.3 Classes

Ballot The undefined primitive in all elections. The Contests that appear on a particular Ballot are defined by its BallotStyle. The applicable ReportingContexts include all those specified for its BallotStyle, but additional ReportingContexts may be specified for the individual Ballot.

Attributes of Ballot:

Categories
Arbitrary, jurisdiction-defined tags applied to the Ballot; e.g., Early, Regular, InPerson, Absentee, Provisional, Challenged, NotRegistered, WrongPrecinct, IneligibleVoter.
Accepted
True if the Ballot should be counted, false if not (e.g., for a provisional Ballot that was not accepted).

BallotStyle Set of Contests and ReportingContexts that is inherited by all Ballots of that style. Depending on the type of election and local practices, a jurisdiction would define a separate BallotStyle for each precinct, each split within a precinct, and/or for each political party.

[1] defines both “ballot style” and “ballot configuration.” This model assumes that the association between styles and configurations is 1-to-1 and represents the combined concept with BallotStyle.

Attributes of BallotStyle:

Name
Human-readable identifier.

Choice One of the things you can vote on in a Contest, such as a candidate, a political party, or yes or no. Choice is scoped by Contest, so even if the same person runs as a candidate in two or more Contests, those separate candidacies are represented by separate Choices. Choices do not map 1:1 with ballot positions—a Choice uniquely identifies a candidate, while a given ballot position might just be a generic write-in slot.

Attributes of Choice:

Name
Human-readable identifier. (In a real system, Choices could have complex descriptive data associated with them that must be displayed to the user somehow, but for logic testing purposes a single field suffices.)
IsWriteIn
True if the Choice is a write-in candidate, false if not.

Contest Subdivision of a Ballot corresponding to a single question being put before the voters, consisting of header text, a discrete set of Choices, and possibly write-in opportunities. It is possible for a Contest to have zero Choices, e.g., if there are no registered candidates but write-ins are being accepted. Choices corresponding to the candidates written in would be added later.

Attributes of Contest:

Description
Human-readable header text.
CountingLogic
Identifies the tabulation method used for the Contest.
N
For CountingLogic other than ranked order, N is the maximum number of votes that may be cast in the Contest by a given voter. In an N-of-M Contest, the voter may cast at most one vote for each Choice, so N is equal to the maximum number of Choices that the voter may select without overvoting.1 In a cumulative Contest, there is no such constraint—the voter may cast more than one vote for a given Choice.

Typically, N also is the number of winners for the Contest, but not necessarily. The voting system only needs to gather votes and report the totals; the picking of winners may be an external process impacted by election law, late-breaking judicial rulings, etc. However, for ranked order Contests, N is specifically the number of Choices to be elected, and has no other meaning.

MaxWriteIns
The number of ballot positions allocated for write-ins; the maximum number of candidates that the voter may write in. Any value between zero and N is possible. Zero would mean that write-ins are not allowed; N would mean that write-ins are allowed; a number in between would mean that write-ins must be approved and the number of approved write-in candidates is less than N.
Rotate
True if the ordering of Choices within the Contest should be rotated, false if not.

ElectionDistrict Surrogate for real-world entity that may have associated ReportingContexts. Any relationship between ElectionDistricts and Contests appearing on the ballot in those districts is implemented by BallotStyles.

Party Surrogate for real-world political party.

Attributes of Party:

Name
Unique human-readable identifier.

Precinct Surrogate for real-world entity that may have associated ReportingContexts. Any relationship between Precincts and Contests appearing on the ballot in those Precincts is implemented by BallotStyles.

ReportingContext Particular scope within which the system must be capable of generating reports. E.g., to support reporting at the precinct level, there must be a ReportingContext for each precinct. The association between ReportingContexts and individual tabulators, precincts, election districts, political parties, ballot categories, or other arbitrary scopes of reporting is jurisdiction-defined and jurisdiction-managed, mostly using BallotStyles. The ways in which ReportingContexts overlap or include one another is entirely determined by the assignment of multiple ReportingContexts to BallotStyles and Ballots.

Attributes of ReportingContext:

Name
Human-readable identifier.

Tabulator Surrogate for real-world entity, e.g., a DRE or optical scanner, that may have associated ReportingContexts.

3.5.4 Named associations

Affiliation Identifies the Party to which a candidate claims allegiance. Does not necessarily have anything to do with Endorsements.

Alias Identifies an alternative Choice that for tabulation purposes is considered equivalent to a particular canonical Choice. Aliases will normally be variant spellings of a candidate’s name that appeared in write-in positions.

Endorsement Identifies a voter response that would be implied by a straight party vote for the endorsing Party. Does not necessarily have anything to do with Affiliation.

Attributes of Endorsement:

Value
Analogous to VoterInput Value, this is the vote recommended by the endorser.

In a 1-of-M or N-of-M Contest, an Endorsement with Value = 1 would exist for the single Choice or for each of the Choices endorsed by the Party.

In a Cumulative Contest, Value may take on values greater than 1. For example, if the Party recommended that voters cast two votes for the first Choice and one vote for the second, an Endorsement with Value = 2 would exist for the first Choice and an Endorsement with Value = 1 would exist for the second Choice.

In a Ranked order Contest, Value contains the ranking that the Party recommends that voters assign to each Choice.

VoterInput The response that a particular Ballot provides for a particular Choice.

Attributes of VoterInput:

Value
The response of the voter in some ballot position. The absence of a response is equivalent to a Value of 0 except in ranked order contests, where the behavior is implementation-defined.

In a 1-of-M or N-of-M Contest, a VoterInput with Value = 1 would exist for the single Choice or for each of the Choices for which the voter voted.

In a Cumulative Contest, Value may take on values greater than 1. For example, if a voter cast two votes for the first Choice and one vote for the second, a VoterInput with Value = 2 would exist for the first Choice and a VoterInput with Value = 1 would exist for the second Choice.

In a Ranked order Contest, Value contains the ranking that the voter assigns to each Choice.

3.5.5 Constraints

I.

For N-of-M and straight party selection Contests, the Value attribute of VoterInput or Endorsement must be 1. For cumulative Contests, 1 Value N. (Deliberately, there is no analogous constraint for ranked order Contests.)

II.

N > 0.

III.

0 MaxWriteIns N.

IV.

In Contests with CountingLogic = Straight party selection, N = 1 and MaxWriteIns = 0.

V.

Every Ballot must be associated with at least one ReportingContext either directly or through its BallotStyle. (Otherwise the Ballot would never be reported.)

VI.

A Ballot cannot have a VoterInput for a Choice in a Contest that does not appear in its BallotStyle.

VII.

A given BallotStyle may contain at most one Contest with CountingLogic = Straight party selection.

VIII.

A Contest with CountingLogic = Straight party selection cannot be straight-party-votable (i.e., there can be no Endorsements referring to its Choices).

IX.

In Contests with CountingLogic = Straight party selection, the Names of the Choices must match the Names of Parties.

X.

Party names must be unique.

XI.

A Ballot may not simultaneously have VoterInput for a Choice and an Alias of that Choice. (The handling of double votes for a given candidate resulting from write-in reconciliation is deliberately unspecified in the VVSG, so for testing purposes it is considered an error.)

XII.

A Ballot may not simultaneously have VoterInput in a straight-party-votable Contest and a straight party vote that implies votes in that same Contest. (Resolution of straight party overrides is deliberately unspecified in the VVSG, so for testing purposes they are considered to be errors.)

XIII.

The Choice that an Alias cites as canonical cannot be aliased. (Corollary: There can be no cycles or self-referential Aliases.)

XIV.

The Choice that an Alias cites as canonical must be in the same Contest.

XV.

The Choice referenced by an Endorsement must be canonical (it cannot be an Alias).

XVI.

A Ballot cannot have VoterInput for more write-in Choices in a given Contest than is allowed by the MaxWriteIns attribute of the Contest.

3.5.6 Usage for all standard voting variations

In-person voting No special requirements.

Absentee voting Absentee voting is implemented in several different ways in practice, and it can be implemented in several different ways using this model.

  1. Absentee Ballots can be tagged with the Absentee category and otherwise mingled with other Ballots.
  2. A separate ReportingContext can be created for absentee Ballots and applied to the individual absentee Ballots.
  3. A separate BallotStyle can be used for absentee Ballots.

While the first option is the least invasive, absentee Ballots are in practice sometimes processed as a separate precinct, which usually means both a separate ReportingContext and a separate BallotStyle.

Review-required ballots Use Categories and Accepted attributes of Ballot as needed.

Write-ins The number of write-ins permitted is an attribute of the Contest. If the write-in is new, a new Choice is created for it (with IsWriteIn = true). Votes are then associated with that Choice. Alias associations are created as applicable during write-in reconciliation.

Split precincts Ballots are associated with the ReportingContexts pertaining to the applicable Precinct and ElectionDistrict. If different BallotStyles are used for each split, the associations can be made on the BallotStyles. Otherwise, each Ballot must be individually associated.

Straight party voting A single Contest is created with CountingLogic = Straight party selection and Choice Names being equal to the Names of the available Parties. In every other Contest that is straight-party-votable, the straight party behaviors are configured by creating Endorsement associations between the Choices and the Parties.

Cross-party endorsement See straight party voting. Create additional Endorsement associations as needed for multiply endorsed Choices.

Ballot rotation Rotate is a Boolean attribute of Contest. The implementation of variable mapping between Choices and ballot positions is out of scope because ballot positions are abstracted out of the model. However, in paper-based systems, rotation may involve a proliferation of BallotStyles that would have to be added.

Primary elections Create BallotStyles and ReportingContexts as needed to support the different political parties and unaffiliated voters. Non-party-specific Contests appear in all BallotStyles while party-specific Contests only appear in those BallotStyles applicable to the relevant Party.

Closed primaries Assignment of BallotStyles to voters is procedural and out of scope.

Open primaries Assignment of BallotStyles to voters is procedural and out of scope.

Provisional / challenged ballots Use Categories and Accepted attributes of Ballot as needed.

1-of-M voting Set ContestCountingLogic = N-of-M and set N = 1.

N-of-M voting Set ContestCountingLogic = N-of-M and set N appropriately.

Cumulative voting Set ContestCountingLogic = Cumulative and set N appropriately.

Ranked order voting Set ContestCountingLogic = Ranked order and set N appropriately. VoterInput Values specify the rankings as provided on each Ballot.

3.6 Basic schema

The following transforms were used to render the UML model as SQL.

  1. At the most basic level, a table represents a class, the columns of the table represent the attributes of that class, and the rows of the table represent the instances of that class.
  2. Object identity (haecceity) is implemented either by using an existing identifier as primary key or by using a synthetic identifier of integer type, as convenient.
  3. Associations to at most 1 instance of another class are implemented using foreign keys within the relevant table with a not-null constraint if the minimum multiplicity is 1. Associations of higher multiplicity are reified as separate tables.
  4. Attributes of multiplicity greater than 1 are treated as associations and reified as separate tables.
  5. Enums are implemented using the names of the enum values as identifiers. Integrity is maintained by creating a table containing the enum values and making attributes of that enum type into foreign keys on that table.

The classes Tabulator, Precinct and ElectionDistrict are not represented. They were modelled only to clarify how the more general concept ReportingContext relates to the real world and are not needed by the test suite.

-- enum  
create table BallotCategory (  
  Name  Text  primary key  
);  
insert into BallotCategory values  
  (’Early’), (’Regular’), (’InPerson’), (’Absentee’), (’Provisional’),  
  (’Challenged’), (’NotRegistered’), (’WrongPrecinct’), (’IneligibleVoter’);  
 
 
-- enum  
create table ContestCountingLogic (  
  Name  Text  primary key  
);  
insert into ContestCountingLogic values  
  (’N-of-M’), (’Cumulative’), (’Ranked order’), (’Straight party selection’);  
 
 
-- class  
create table ReportingContext (  
  Name  Text  primary key  
);  
 
 
-- class  
create table Party (  
  Name  Text  primary key  
);  
 
 
-- class  
create table Contest (  
  ContestId      Integer  primary key,  
  Description    Text     not null,  
  CountingLogic  Text     not null references ContestCountingLogic,  
  N              Integer  not null check (N > 0),  
  MaxWriteIns    Integer  not null check (MaxWriteIns between 0 and N),  
  Rotate         Boolean  not null,  
 
  -- Straight party selections must be 1-of-M with no write-ins.  
  check (CountingLogic <> ’Straight party selection’ or  
          (N = 1 and MaxWriteIns = 0))  
);  
 
 
-- class  
create table Choice (  
  ChoiceId     Integer  primary key,  
  ContestId    Integer  not null references Contest,  
  Name         Text     not null,  
  Affiliation  Text     references Party,    -- named association  
  IsWriteIn    Boolean  not null  
);  
 
 
-- class  
create table BallotStyle (  
  StyleId  Integer  primary key,  
  Name     Text     not null  
);  
 
 
-- class  
create table Ballot (  
  BallotId  Integer  primary key,  
  StyleId   Integer  not null references BallotStyle,  
  Accepted  Boolean  not null  
);  
 
 
-- attribute Ballot::Categories  
create table BallotCategoryAssociation (  
  BallotId  Integer  references Ballot,  
  Category  Text     references BallotCategory,  
  primary key (BallotId, Category)  
);  
 
 
-- association class  
create table VoterInput (  
  BallotId  Integer  references Ballot,  
  ChoiceId  Integer  references Choice,  
  Value     Integer  not null check (Value > 0),  
  primary key (BallotId, ChoiceId)  
);  
 
 
-- association class  
create table Endorsement (  
  Party     Text     references Party,  
  ChoiceId  Integer  references Choice,  
  Value     Integer  not null check (Value > 0),  
  primary key (Party, ChoiceId)  
);  
 
 
-- named association  
create table Alias (  
  AliasId   Integer  primary key references Choice,  -- The unwanted alias  
  ChoiceId  Integer  not null references Choice,     -- The canonical choice  
  check (ChoiceId <> AliasId)                 -- Circular aliases are no good  
);  
 
 
-- unnamed association  
create table BallotStyleContestAssociation (  
  StyleId    Integer  references BallotStyle,  
  ContestId  Integer  references Contest,  
  primary key (StyleId, ContestId)  
);  
 
 
-- unnamed association  
create table BallotStyleReportingContextAssociation (  
  StyleId           Integer  references BallotStyle,  
  ReportingContext  Text     references ReportingContext,  
  primary key (StyleId, ReportingContext)  
);  
 
 
-- unnamed association  
create table BallotReportingContextAssociation (  
  BallotId          Integer  references Ballot,  
  ReportingContext  Text     references ReportingContext,  
  primary key (BallotId, ReportingContext)  
);

3.7 Basic test suite

The basic test suite contains 92 tests that exercise different voting variations in small, simple scenarios to isolate the conditions under which failures occur. The basic test suite is complemented by the volume test specified in Part 3 of the VVSG [1], which exercises all features together in a large, complex scenario where a significant volume of ballots is processed.

The variations identified in the test suite as AbsenteeVoting and AbsenteeByCategories both conform to the voting variation defined in the VVSG as Absentee voting. Tests tagged as AbsenteeByCategories require support for a capability that might not be present in all systems, while AbsenteeVoting tests use a more procedural approach to achieve the same goal. The documented assumption attached to test case 1-basic-AbsenteeByCategory.sql and other tests using the absentee-ballots-by-categories approach means that it is not applicable to Absentee voting systems that are limited to the procedural approach. See Section 3.5.6.2 for further discussion on this issue.

Table 2 provides the full list of tests, which breaks down as follows:

Several voting variations do not have designated tests:

Table 2: Basic test suite
Test case ID / file name
Applies to
Description




1-basic-1ofM.sql

Voting system

Small 1-of-M contest, no write-ins, no rejected ballots.




1-basic-AbsenteeByCategory.sql

Absentee voting2

Small 1-of-M contest with absentee ballots via categories.




1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql

Absentee voting2 Cross-party endorsement

Small straight party + 1-of-M contest with cross-party endorsement, three absentee ballots via categories.




1-basic-AbsenteeByCategory-Cumulative.sql

Absentee voting2 Cumulative voting

Small Cumulative contest, N=3, no write-ins, no rejected ballots, three absentee ballots via categories.




1-basic-AbsenteeByCategory-NofM.sql

Absentee voting2 N of M voting

Small 2-of-M contest, no write-ins, no rejected ballots, three absentee ballots via categories.




1-basic-AbsenteeByCategory-Provisional.sql

Absentee voting2 Provisional / challenged ballots

Small 1-of-M contest with absentee ballots via categories, accepted and rejected provisionals.




1-basic-AbsenteeByCategory-RankedOrder.sql

Absentee voting2 Ranked order voting

Small ranked order contest with absentee ballots via categories.




1-basic-AbsenteeByCategory-StraightParty.sql

Absentee voting2 Straight party voting

Small straight party + 1-of-M contest, absentee ballots via categories.




1-basic-AbsenteeByCategory-WriteIns.sql

Absentee voting2 Write-ins

Small 1-of-M contest with absentee ballots via categories and write-ins, no aliasing.




1-basic-AbsenteeBySpecialPrecinct.sql

Absentee voting

Small 1-of-M contest with absentee ballots via a special precinct and ballot style.




1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql

Absentee voting Cross-party endorsement

Small straight party + 1-of-M contest with cross-party endorsement, absentee ballots via a special precinct and ballot style.




1-basic-AbsenteeBySpecialPrecinct-Cumulative.sql

Absentee voting Cumulative voting

Small Cumulative contest, N=3, with absentee ballots via a special precinct and ballot style, no write-in, no rejected ballots.




1-basic-AbsenteeBySpecialPrecinct-NofM.sql

Absentee voting N of M voting

Small 3-of-M contest with absentee ballots via a special precinct and ballot style, no write-in, no rejected ballots.




1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql

Absentee voting N of M voting Provisional / challenged ballots

Small 3-of-M contest with absentee ballots via a special precinct, accepted and rejected provisionals, no write-ins.




1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

Absentee voting Provisional / challenged ballots

Small 1-of-M contest with absentee ballots via a special precinct and ballot style, accepted and rejected provisionals.




1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql

Absentee voting Ranked order voting

Small ranked order contest with absentee ballots via a special precinct and ballot style.




1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql

Absentee voting Split precincts

Small 1-of-M contest with absentee ballots via a special precinct and a split precinct.




1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

Absentee voting Straight party voting

Small straight party + 1-of-M contest, absentee ballots via a special precinct and ballot style.




1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql

Absentee voting Write-ins

Small 1-of-M contest with absentee ballots via a special precinct and write-ins.




1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql

Absentee voting

Small Yes-or-No contest with absentee ballots via a special precinct and ballot style.




1-basic-BallotRotation.sql

Ballot rotation

Small 1-of-M contest with ballot rotation.




1-basic-BallotRotation-AbsenteeByCategory.sql

Ballot rotation Absentee voting2

Small 1-of-M contest with ballot rotation and absentee ballots via categories.




1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql

Ballot rotation Absentee voting

Small 1-of-M contest with ballot rotation, absentee ballots via a special precinct.




1-basic-BallotRotation-CrossPartyEndorsement.sql

Ballot rotation Cross-party endorsement

Small straight party + 1-of-M contest with cross-party endorsement and ballot rotation.




1-basic-BallotRotation-Cumulative.sql

Ballot rotation Cumulative voting

Small cumulative voting contest, N=2, with ballot rotation, no write-ins, no rejected ballots.




1-basic-BallotRotation-NofM.sql

Ballot rotation N of M voting

Small 2-of-M contest, with ballot rotation.




1-basic-BallotRotation-Provisional.sql

Ballot rotation Provisional / challenged ballots

Small 1-of-M contest with ballot rotation, accepted and rejected provisionals.




1-basic-BallotRotation-RankedOrder.sql

Ballot rotation Ranked order voting

Small ranked order contest with ballot rotation.




1-basic-BallotRotation-StraightParty.sql

Ballot rotation Straight party voting

Small straight party + 1-of-M contest with ballot rotation.




1-basic-BallotRotation-WriteInsAliases.sql

Ballot rotation Write-ins

Small 1-of-M contest with write-ins and aliases and ballot rotation.




1-basic-CrossPartyEndorsement.sql

Cross-party endorsement

Small straight party + 1-of-M contest with cross-party endorsement.




1-basic-CrossPartyEndorsement-Cumulative.sql

Cross-party endorsement Cumulative voting

Small straight party + cumulative contest with cross-party endorsement, no write-ins, no rejected ballots.




1-basic-CrossPartyEndorsement-NofM.sql

Cross-party endorsement N of M voting

Small straight party + 2-of-M contest with cross-party endorsement.




1-basic-CrossPartyEndorsement-Provisional.sql

Cross-party endorsement Provisional / challenged ballots

Small straight party + 1-of-M contest with cross-party endorsement, accepted and rejected provisionals.




1-basic-CrossPartyEndorsement-WriteIns.sql

Cross-party endorsement Write-ins

Small straight party + 1-of-M contest with cross-party endorsement and write-ins.




1-basic-Cumulative.sql

Cumulative voting

Small cumulative voting contest, no write-ins, no rejected ballots.




1-basic-Cumulative-NofM.sql

Cumulative voting N of M voting

Small cumulative voting contest plus small N-of-M contest, no write-ins, no rejected ballots.




1-basic-Cumulative-Provisional.sql

Cumulative voting Provisional / challenged ballots

Small cumulative voting contest with accepted and rejected provisionals.




1-basic-Cumulative-RankedOrder.sql

Cumulative voting Ranked order voting

Small ranked order contest plus small cumulative contest, no special cases.




1-basic-NoBallots-1ofM.sql

Voting system

Small 1-of-M contest with no ballots cast.




1-basic-NoBallots-RankedOrder.sql

Ranked order voting

Small ranked order contest with no ballots cast.




1-basic-NoChoices-1ofM.sql

Write-ins

Small 1-of-M contest with no choices (write-ins only).




1-basic-NoChoicesNoBallots-1ofM.sql

Write-ins

Small 1-of-M contest with no choices (write-ins only) and no ballots.




1-basic-NofM.sql

N of M voting

Small 2-of-M contest, no write-ins, no rejected ballots.




1-basic-NofM-Provisional.sql

N of M voting Provisional / challenged ballots

Small 2-of-M contest with accepted and rejected provisionals.




1-basic-NofM-WriteIns.sql

N of M voting Write-ins

Small 2-of-M contest with write-ins, no aliasing.




1-basic-Primary.sql

Primary elections

Small primary election, no write-ins, no rejected ballots.




1-basic-Primary-AbsenteeByCategory.sql

Primary elections Absentee voting2

Small primary election with absentee ballots via categories, no write-ins, no rejected ballots.




1-basic-Primary-AbsenteeBySpecialPrecinct.sql

Primary elections Absentee voting

Small primary election with absentee ballots via a special precinct and ballot style, no write-ins, no rejected ballots.




1-basic-Primary-BallotRotation.sql

Primary elections Ballot rotation

Small primary election with ballot rotations, no write-ins, no rejected ballots.




1-basic-Primary-CrossPartyEndorsement.sql

Primary elections Cross-party endorsement

Small primary election with straight party voting and cross-party endorsement in a non-party-specific contest.




1-basic-Primary-Cumulative.sql

Primary elections Cumulative voting

Small primary election with cumulative voting, no write-ins, no rejected ballots.




1-basic-Primary-NofM.sql

Primary elections N of M voting

Small primary election with N-of-M voting, no write-ins, no rejected ballots.




1-basic-Primary-Provisional.sql

Primary elections Provisional / challenged ballots

Small primary election, no write-ins, with accepted and rejected provisionals.




1-basic-Primary-RankedOrder.sql

Primary elections Ranked order voting

Small primary election with ranked order voting, no write-ins, no rejected ballots.




1-basic-Primary-SplitPrecinct.sql

Primary elections Split precincts

Small primary election with a split precinct, no write-ins, no rejected ballots.




1-basic-Primary-StraightParty.sql

Primary elections Straight party voting

Small primary election with straight party voting in a non-party-specific contest.




1-basic-Primary-WriteIns.sql

Primary elections Write-ins

Small primary election with write-ins, no rejected ballots.




1-basic-Provisional.sql

Provisional / challenged ballots

Small 1-of-M contest with accepted and rejected provisionals.




1-basic-RankedOrder-1.sql

Ranked order voting

Small ranked order contest, N=1, M=4, no special cases.




1-basic-RankedOrder-2.sql

Ranked order voting

Small ranked order contest, N=2, M=4, no special cases.




1-basic-RankedOrder-NofM.sql

Ranked order voting N of M voting

Small ranked order contest plus small N-of-M contest, no special cases.




1-basic-RankedOrder-Provisional.sql

Ranked order voting Provisional / challenged ballots

Small ranked order contest, N=1, M=4, with accepted and rejected provisionals.




1-basic-RankedOrder-WriteIns.sql

Ranked order voting Write-ins

Small ranked order contest, N=1, M=4, with write-in.




1-basic-SplitPrecinct-1.sql

Split precincts

Small 1-of-M contest with a split precinct.




1-basic-SplitPrecinct-2.sql

Split precincts

Two districts, three precincts (one split), three contests, four ballot styles, forty ballots.




1-basic-SplitPrecinct-AbsenteeByCategory.sql

Split precincts Absentee voting2

Small 1-of-M contest with a split precinct and absentee ballots via categories.




1-basic-SplitPrecinct-BallotRotation.sql

Split precincts Ballot rotation

Like SplitPrecinct-2 except with ballot rotation.




1-basic-SplitPrecinct-CrossPartyEndorsement.sql

Split precincts Cross-party endorsement

Like SplitPrecinct-2 except with straight party voting and cross-party endorsement.




1-basic-SplitPrecinct-Cumulative.sql

Split precincts Cumulative voting

Small Cumulative contest, N=2, with a split precinct.




1-basic-SplitPrecinct-NofM.sql

Split precincts N of M voting

Small 3-of-M contest with a split precinct, no write-ins, no rejected ballots.




1-basic-SplitPrecinct-Provisional.sql

Split precincts Provisional / challenged ballots

Small 1-of-M contest with a split precinct and accepted and rejected provisionals.




1-basic-SplitPrecinct-RankedOrder.sql

Split precincts Ranked order voting

Like SplitPrecinct-2 except with ranked order contests at the district level.




1-basic-SplitPrecinct-StraightParty.sql

Split precincts Straight party voting

Like SplitPrecinct-2 except with straight party voting.




1-basic-SplitPrecinct-WriteIns.sql

Split precincts Write-ins

Small 1-of-M contest with split precinct and write-in.




1-basic-StraightParty.sql

Straight party voting

Small straight party + 1-of-M contest, no write-ins, no rejected ballots.




1-basic-StraightParty-Cumulative.sql

Straight party voting Cumulative voting

Small straight party + cumulative contest, no write-ins, no rejected ballots.




1-basic-StraightParty-NofM.sql

Straight party voting N of M voting

Small straight party + 2-of-M contest, no write-ins, no rejected ballots.




1-basic-StraightParty-Provisional.sql

Straight party voting Provisional / challenged ballots

Small straight party + 1-of-M contest with accepted and rejected provisionals.




1-basic-StraightParty-RankedOrder.sql

Straight party voting Ranked order voting

Small ranked order contest, N=1, M=4, with straight-party voting.




1-basic-StraightParty-WriteIns.sql

Straight party voting Write-ins

Small straight party + 1-of-M contest with write-ins.




1-basic-WriteIns.sql

Write-ins

Small 1-of-M contest with write-ins, no aliasing.




1-basic-WriteInsAliases.sql

Write-ins

Small 1-of-M contest with write-ins and aliases.




1-basic-WriteInsAliases-AbsenteeByCategory.sql

Write-ins Absentee voting2

Small 1-of-M contest with write-ins, aliases and absentee ballots via categories.




1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql

Write-ins Absentee voting

Small 1-of-M contest with write-ins, aliases, absentee ballots via a special precinct and ballot style.




1-basic-WriteInsAliases-Cumulative.sql

Write-ins Cumulative voting

Small Cumulative contest, N=2, with write-ins and aliases, no rejected ballots.




1-basic-WriteInsAliases-NofM.sql

Write-ins N of M voting

Small 2-of-M contest with write-ins and aliases, no rejected ballots.




1-basic-WriteInsAliases-Provisional.sql

Write-ins Provisional / challenged ballots

Small 1-of-M contest with write-ins, aliases, accepted and rejected provisionals.




1-basic-Yes-or-No.sql

Voting system

Small Yes-or-No contest, no rejected ballots.




1-basic-samples-AlleganyGeneral2004.sql

Write-ins N of M voting

Test spec based on Allegany County, MD sample ballot for congressional district 6, general election, 2004-11-02.




1-basic-samples-CecilRPrimary1998.sql

N of M voting

Test spec based on Cecil County, MD sample ballot for Republican primary election, 1st congressional district, legislative district 35, 1998-09-15. The generated test does not include anything specific to primary elections.




1-basic-samples-FairfaxGeneral2004.sql

Write-ins

Test spec based on Fairfax County, VA sample ballot for 8th district, general election, 2004-11-02.




3.8 Required test cases not included in the basic Votetest test suite

Some requirements that might logically be tested during the phase when Votetest is used do not have associated test cases because the behaviors in question are orthogonal to the Votetest data model and/or so dependent on the specifics of the implementation that only an abstract test script could be provided. Those requirements and descriptions of the needed test cases are shown in Table 3.

Table 3: Additional required test cases
Requirements
Test description


Realistic ballot styles [3, Part 1 Req. 7.2-A.1, A.4 and A.5]

Test a variety of sample ballot styles, such as those available on the NIST web site [6], to ensure that the voting system can handle the text of long ballot questions, complicated choice labels (such as for primary presidential delegation nominations), miscellaneous ballot text, and overall formatting and layout of ballot styles as used in practice.



Optical scan accuracy [3, Part 1 Req. 6.3.2-B and Section 7.7.5]

When test cases are realized for optical scan devices, the marks used should exercise the range of reliably detectable marks as defined by the vendor, from ideal marks to the standard mark specified in [3, Part 1 Req. 7.7.5-D]. However, to ensure that the tests are defensible, the relative frequency with which the different types of marks appear should be realistic. While both ideal marks and standard marks should be tested repeatedly, it would not be realistic for either extreme to dominate the input. The average mark should be typical of what an average voter would make. The ability of the scanner to ignore extraneous marks should also be tested ([3, Part 1 Req. 7.7.5-E]).



Marginal marks [3, Part 1 Req. 3.2.2.2-E and 7.7.3-C]

Test marks that are clearly within the marginal zone as defined by the vendor to verify that the behavior on marginal marks is as specified. Do not test marks that are near the boundaries, as the uncertainty of the boundaries is of no consequence (see [3, Part 1 Section 7.7.5.1]).



Respecting limits [3, Part 1 Req. 2.4-A.e, Req. 6.4.1.8-A.1 and Section 7.5.6]3 3Note on pending erratum. [3, Part 1 Section 7.1] is missing a requirement saying that the central EMS shall prevent the defining of any election that would cause the voting system to exceed design limits such as maximum number of choices in a contest, maximum number of contests on a ballot, etc. That requirement should be cited here if and when it is added.

Construct test cases as needed to satisfy [3, Part 3 Req. 5.2.3-B and C]. The test generator (Section 5.7) may be of use.



Definition reuse [3, Part 1 Req. 7.2-C]

Choose two test cases that use similar ballot styles. Execute the first as usual, but instead of clearing out all definitions between tests, attempt to construct the ballot styles for the second test based on the definitions retained from the first.



Ballot style mismatches [3, Part 1 Req. 7.7.1-A]

Attempt to execute a test case with mismatched ballot styles loaded on different devices and verify that the system prevents incorrect reports from being generated. (It may prevent mismatched ballot styles from being loaded in the first place.)



Ballot orientation [3, Part 1 Req. 7.7.1-B]

If the vendor specifies that the tabulator is capable of scanning ballots in more than one orientation, allow the orientation of fed ballots to vary during the execution of all test cases. If the vendor specifies one or more orientations as being incorrect, attempt to feed ballots in the unsupported orientations and verify that the ballots are rejected.



Validation of input [3, Part 1 Req. 6.4.1.8-A and A.1]

Since poor validation of input often creates an attack vector, this should be covered as part of security testing and evaluation.



Miscellaneous capabilities [3, Part 1 Req. 7.2-A.1, 7.2-A.5, 7.3.1-B, 7.7.3-A.3, 7.8.3.3-B.1 and many others]

The VVSG contains numerous requirements for miscellaneous voting system capabilities that are orthogonal to the Votetest data model. Since the general test template specified in [3, Part 3 Section 5.2.1.1] treats each test case as an entire election, many such capabilities will be tested incidentally during the execution of the basic test suite. Use the Voting Equipment User Documentation to determine how to exercise any capabilities that are not tested incidentally and then verify that they satisfy the applicable VVSG requirements.



System-specific functions

These must be tested in accordance with [3, Part 3 Req. 5.2.3-G].



3.9 Requirements trace

This section lists the tests that are traceable to each requirement in Chapter 7 of the VVSG [3].

7.1-A EMS, ballot definition

All Votetest tests are traceable to this requirement.

7.1-A.1 EMS, ballot definition details

All Votetest tests are traceable to this requirement.

7.1-B EMS, political and administrative subdivisions

All Votetest tests are traceable to this requirement.

7.1-C EMS, election districts

All Votetest tests are traceable to this requirement.

7.1-D EMS, voting variations

All Votetest tests are traceable to this requirement.

7.1-D.1 EMS, 1-of-M

The following tests are traceable to this requirement:

1-basic-1ofM.sql 1-basic-NoBallots-1ofM.sql 1-basic-Yes-or-No.sql 1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-StraightParty-WriteIns.sql 1-basic-AbsenteeByCategory.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-WriteIns.sql 1-basic-Provisional.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-Primary-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql 1-basic-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql 1-basic-samples-CecilRPrimary1998.sql

7.1-D.2 EMS, yes/no question

The following tests are traceable to this requirement:

1-basic-Yes-or-No.sql 1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql

7.1-D.3 EMS, indicate party affiliations and endorsements

The following tests are traceable to this requirement:

1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-StraightParty-Cumulative.sql 1-basic-StraightParty-WriteIns.sql 1-basic-StraightParty-NofM.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.1-D.4 EMS, primary elections, party-specific and non-party-specific contests

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.1-D.5 EMS, write-ins

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty-WriteIns.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-WriteIns.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql

7.1-D.6 EMS, straight party voting

The following tests are traceable to this requirement:

1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-StraightParty-Cumulative.sql 1-basic-StraightParty-WriteIns.sql 1-basic-StraightParty-NofM.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.1-D.7 EMS, cross-party endorsement

The following tests are traceable to this requirement:

1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql

7.1-D.8 EMS, split precincts, define precincts and election districts

The following tests are traceable to this requirement:

1-basic-SplitPrecinct-StraightParty.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql

7.1-D.9 EMS, N-of-M voting

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-StraightParty-NofM.sql 1-basic-RankedOrder-NofM.sql 1-basic-NofM.sql 1-basic-Primary-NofM.sql 1-basic-Cumulative-NofM.sql 1-basic-BallotRotation-NofM.sql 1-basic-AbsenteeByCategory-NofM.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-NofM.sql 1-basic-samples-CecilRPrimary1998.sql

7.1-D.10 EMS, cumulative voting

The following tests are traceable to this requirement:

1-basic-Cumulative-RankedOrder.sql 1-basic-StraightParty-Cumulative.sql 1-basic-Cumulative.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-AbsenteeByCategory-Cumulative.sql 1-basic-Primary-Cumulative.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-Cumulative.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-Cumulative-NofM.sql 1-basic-Cumulative-Provisional.sql

7.1-D.11 EMS, ranked order voting

The following tests are traceable to this requirement:

1-basic-NoBallots-RankedOrder.sql 1-basic-RankedOrder-1.sql 1-basic-RankedOrder-2.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-Primary-RankedOrder.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-AbsenteeByCategory-RankedOrder.sql 1-basic-Cumulative-RankedOrder.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-RankedOrder-NofM.sql 1-basic-RankedOrder-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql

7.1-E Election definition accuracy

All Votetest tests are traceable to this requirement.

7.1-F Voting options accuracy

All Votetest tests are traceable to this requirement.

7.1-G EMS, confirm recording of election definition

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.1-H EMS, election definition distribution

All Votetest tests are traceable to this requirement.

7.2-A EMS, define ballot styles

All Votetest tests are traceable to this requirement.

7.2-A.1 EMS, auto-format

All Votetest tests are traceable to this requirement.

7.2-A.2 EMS, include votable contests

All Votetest tests are traceable to this requirement.

7.2-A.3 EMS, exclude nonvotable contests

All Votetest tests are traceable to this requirement.

7.2-A.4 EMS, nonpartisan formatting

All Votetest tests are traceable to this requirement.

7.2-A.5 EMS, jurisdiction-dependent content

All Votetest tests are traceable to this requirement.

7.2-A.6 EMS, primary elections, associate configurations with parties

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.2-A.7 EMS, ballot rotation

The following tests are traceable to this requirement:

1-basic-BallotRotation-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-BallotRotation-NofM.sql 1-basic-BallotRotation-Provisional.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql

7.2-A.8 EMS, split precincts, associate ballot configurations

The following tests are traceable to this requirement:

1-basic-SplitPrecinct-StraightParty.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql

7.2-B EMS, ballot style distribution

All Votetest tests are traceable to this requirement.

7.2-B.1 EMS, ballot style identification

All Votetest tests are traceable to this requirement.

7.2-C EMS, ballot style reuse

This requirement is discussed in Section 3.8.

7.2-D EMS, ballot style protection

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.3.1-A Support L&A testing

All Votetest tests are traceable to this requirement.

7.3.1-B Built-in self-test and diagnostics

All Votetest tests are traceable to this requirement.

7.3.1-C Verify proper preparation of ballot styles

All Votetest tests are traceable to this requirement.

7.3.1-D Verify proper installation of ballot styles

All Votetest tests are traceable to this requirement.

7.3.1-E Verify compatibility between software and ballot styles

All Votetest tests are traceable to this requirement.

7.3.1-F Test ballots

All Votetest tests are traceable to this requirement.

7.3.1-G Test all ballot positions

All Votetest tests are traceable to this requirement.

7.3.1-H Paper-based tabulators, testing calibration

All Votetest tests are traceable to this requirement.

7.3.1-I Ballot marker readiness

All Votetest tests are traceable to this requirement.

7.3.1-J L&A testing, no side-effects

All Votetest tests are traceable to this requirement.

7.3.1-J.1 Isolate test ballots

All Votetest tests are traceable to this requirement.

7.4-A Programmed device, verify L&A performed

All Votetest tests are traceable to this requirement.

7.4-B Programmed device, disable untested devices

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.4-C Paper-based tabulator activation

All Votetest tests are traceable to this requirement.

7.4-D Paper-based tabulator, verify activation

All Votetest tests are traceable to this requirement.

7.4-E Programmed vote-capture device, open poll function

All Votetest tests are traceable to this requirement.

7.4-E.1 Programmed vote-capture device, protect open poll function

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.4-E.2 Programmed vote-capture device, enforce correct poll opening process

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.4-E.3 Programmed vote-capture device, verify activation

All Votetest tests are traceable to this requirement.

7.5.1.1-A Activation device, DRE, EBP, ballot activation

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.1-A.1 Activation device, DRE, EBP, credential issuance

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.1-A.2 Activation device, DRE, EBP, at most one cast ballot per session

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.1-B Activation device, contemporaneous record

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.1-C Activation device, DRE, EBP, control ballot configuration

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.1-C.1 Activation device, DRE, EBP, enable only applicable contests

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.1-C.2 Activation device, DRE, EBP, select ballot configuration for party in primary elections

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.2-A Activation device, ballot secrecy

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.2-A.1 DRE and EBP, open primaries, party selection should be private

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.2-A.2 Activation device, records preserve secrecy of the ballot

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.2-A.3 Activation device, ballot activation provisional voting

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.3-A Activation device, credentials and tokens

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.3-A.1 Activation device, token limited in capacity

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.3-A.2 Activation device, DRE, EPB, token de-activated after casting

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.3-A.3 Activation device, token should be non-reusable

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.3-A.4 Activation device, integrity and authenticity of ballot activation information

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-A Activation device, may access remote registration database

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-A.1 Activation device, cannot connect to multiple networks

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-A.2 Activation device, access to remote registration database configurable

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-A.3 Activation device, notification of access to remote registration database

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-A.4 Activation device, remote access failure backup capability

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-A.5 Activation device, connects to router/firewall

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.1.4-B Activation device, source code reviews

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.2-A No advertising

All Votetest tests are traceable to this requirement.

7.5.2-B Capture votes

All Votetest tests are traceable to this requirement.

7.5.3-A Vote-capture device, voting variations

All Votetest tests are traceable to this requirement.

7.5.3-A.1 Vote-capture device, 1-of-M

The following tests are traceable to this requirement:

1-basic-1ofM.sql 1-basic-NoBallots-1ofM.sql 1-basic-Yes-or-No.sql 1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-StraightParty-WriteIns.sql 1-basic-AbsenteeByCategory.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-WriteIns.sql 1-basic-Provisional.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-Primary-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql 1-basic-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql 1-basic-samples-CecilRPrimary1998.sql

7.5.3-A.2 Vote-capture device, yes/no question

The following tests are traceable to this requirement:

1-basic-Yes-or-No.sql 1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql

7.5.3-A.3 Vote-capture device, indicate party affiliations and endorsements

The following tests are traceable to this requirement:

1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-StraightParty-Cumulative.sql 1-basic-StraightParty-WriteIns.sql 1-basic-StraightParty-NofM.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.5.3-A.4 Vote-capture device, closed primaries

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.5.3-A.5 Vote-capture device, open primaries

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.5.3-A.6 Vote-capture device, write-ins

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty-WriteIns.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-WriteIns.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql

7.5.3-A.7 Vote-capture device, support write-in reconciliation

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty-WriteIns.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-WriteIns.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql

7.5.3-A.8 Vote-capture device, ballot rotation

The following tests are traceable to this requirement:

1-basic-BallotRotation-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-BallotRotation-NofM.sql 1-basic-BallotRotation-Provisional.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql

7.5.3-A.9 Ballot rotation, equal time for each contest choice

The following tests are traceable to this requirement:

1-basic-BallotRotation-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-BallotRotation-NofM.sql 1-basic-BallotRotation-Provisional.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql

7.5.3-A.10 Vote-capture device, straight party voting

The following tests are traceable to this requirement:

1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-StraightParty-Cumulative.sql 1-basic-StraightParty-WriteIns.sql 1-basic-StraightParty-NofM.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.5.3-A.11 Vote-capture device, cross-party endorsement

The following tests are traceable to this requirement:

1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql

7.5.3-A.12 Vote-capture device, split precincts

The following tests are traceable to this requirement:

1-basic-SplitPrecinct-StraightParty.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql

7.5.3-A.13 Vote-capture device, N-of-M voting

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-StraightParty-NofM.sql 1-basic-RankedOrder-NofM.sql 1-basic-NofM.sql 1-basic-Primary-NofM.sql 1-basic-Cumulative-NofM.sql 1-basic-BallotRotation-NofM.sql 1-basic-AbsenteeByCategory-NofM.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-NofM.sql 1-basic-samples-CecilRPrimary1998.sql

7.5.3-A.14 Vote-capture device, cumulative voting

The following tests are traceable to this requirement:

1-basic-Cumulative-RankedOrder.sql 1-basic-StraightParty-Cumulative.sql 1-basic-Cumulative.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-AbsenteeByCategory-Cumulative.sql 1-basic-Primary-Cumulative.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-Cumulative.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-Cumulative-NofM.sql 1-basic-Cumulative-Provisional.sql

7.5.3-A.15 Vote-capture device, ranked order voting

The following tests are traceable to this requirement:

1-basic-NoBallots-RankedOrder.sql 1-basic-RankedOrder-1.sql 1-basic-RankedOrder-2.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-Primary-RankedOrder.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-AbsenteeByCategory-RankedOrder.sql 1-basic-Cumulative-RankedOrder.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-RankedOrder-NofM.sql 1-basic-RankedOrder-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql

7.5.3-A.16 Vote-capture device, provisional-challenged ballots

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.5.3-A.17 DRE, categorize provisional ballots

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.5.3-A.18 Vote-capture device, review-required ballots

Since the reasons for which a ballot might be flagged or separated for review are jurisdiction-dependent, the list of relevant tests will vary.

7.5.4-A Record votes as voted

All Votetest tests are traceable to this requirement.

7.5.4-A.1 Records consistent with feedback to voter

All Votetest tests are traceable to this requirement.

7.5.4-B DRE, confirm votes recorded

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.5.4-C Casting

All Votetest tests are traceable to this requirement.

7.5.4-C.1 Equipment allows each eligible voter to vote

All Votetest tests are traceable to this requirement.

7.5.4-C.2 Paper-based, must have secure ballot boxes

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.5.4-D DRE, cast is committed

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.5.5-A DRE, at least two separate copies of CVR

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.5.5-A.1 DRE, redundant CVRs on physically separate media

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.5.6-A Tabulator, prevent counter overflow

This requirement is discussed in Section 3.8.

7.5.6-A.1 DRE, stop when full

This requirement is discussed in Section 3.8.

7.6-A DRE, no CVRs before close of polls

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.6-B Programmed vote-capture devices, poll-closing function

All Votetest tests are traceable to this requirement.

7.6-B.1 Programmed vote-capture devices, no voting when polls are closed

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.6-B.2 DRE, no ballot casting when polls are closed

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.6-B.3 Programmed vote-capture devices, poll closing integrity check

All Votetest tests are traceable to this requirement.

7.6-B.4 Programmed vote-capture devices, report on poll closing process

All Votetest tests are traceable to this requirement.

7.6-B.5 Programmed vote-capture devices, prevent reopening polls

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.6-C Precinct EMS, post-election reports

All Votetest tests are traceable to this requirement.

7.7.1-A Detect and prevent ballot style mismatches

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.7.1-B Detect and reject ballots that are oriented incorrectly

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.7.2-A Tabulator, voting variations

All Votetest tests are traceable to this requirement.

7.7.2-A.1 Tabulator, 1-of-M

The following tests are traceable to this requirement:

1-basic-1ofM.sql 1-basic-NoBallots-1ofM.sql 1-basic-Yes-or-No.sql 1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-StraightParty-WriteIns.sql 1-basic-AbsenteeByCategory.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-WriteIns.sql 1-basic-Provisional.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-Primary-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql 1-basic-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql 1-basic-samples-CecilRPrimary1998.sql

7.7.2-A.2 Tabulator, yes/no question

The following tests are traceable to this requirement:

1-basic-Yes-or-No.sql 1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql

7.7.2-A.3 Tabulator, absentee voting

The following tests are traceable to this requirement:

1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-AbsenteeByCategory-RankedOrder.sql 1-basic-AbsenteeByCategory.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-AbsenteeByCategory-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-NofM.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql 1-basic-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.7.2-A.4 Tabulator, provisional-challenged ballots

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.7.2-A.5 Tabulator, accept or reject provisional-challenged ballots individually

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.7.2-A.6 Tabulator, accept or reject provisional-challenged ballots by category

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.7.2-A.7 Tabulator, primary elections

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.7.2-A.8 Tabulator, write-ins

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty-WriteIns.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-WriteIns.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql

7.7.2-A.9 Tabulator, support write-in reconciliation

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty-WriteIns.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-WriteIns.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql

7.7.2-A.10 Tabulator, ballot rotation

The following tests are traceable to this requirement:

1-basic-BallotRotation-StraightParty.sql 1-basic-BallotRotation.sql 1-basic-Primary-BallotRotation.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-BallotRotation-NofM.sql 1-basic-BallotRotation-Provisional.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql

7.7.2-A.11 Tabulator, straight party voting

The following tests are traceable to this requirement:

1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-StraightParty-Cumulative.sql 1-basic-StraightParty-WriteIns.sql 1-basic-StraightParty-NofM.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.7.2-A.12 Tabulating straight party votes

The following tests are traceable to this requirement:

1-basic-StraightParty.sql 1-basic-Primary-StraightParty.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-BallotRotation-StraightParty.sql 1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-SplitPrecinct-StraightParty.sql 1-basic-StraightParty-Cumulative.sql 1-basic-StraightParty-WriteIns.sql 1-basic-StraightParty-NofM.sql 1-basic-StraightParty-Provisional.sql 1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.7.2-A.13 Tabulator, cross-party endorsement

The following tests are traceable to this requirement:

1-basic-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-BallotRotation-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql

7.7.2-A.14 Tabulator, split precincts

The following tests are traceable to this requirement:

1-basic-SplitPrecinct-StraightParty.sql 1-basic-SplitPrecinct-1.sql 1-basic-SplitPrecinct-2.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-SplitPrecinct-BallotRotation.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-SplitPrecinct-CrossPartyEndorsement.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql

7.7.2-A.15 Tabulator, N-of-M voting

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-StraightParty-NofM.sql 1-basic-RankedOrder-NofM.sql 1-basic-NofM.sql 1-basic-Primary-NofM.sql 1-basic-Cumulative-NofM.sql 1-basic-BallotRotation-NofM.sql 1-basic-AbsenteeByCategory-NofM.sql 1-basic-SplitPrecinct-NofM.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-NofM.sql 1-basic-samples-CecilRPrimary1998.sql

7.7.2-A.16 Tabulator, cumulative voting

The following tests are traceable to this requirement:

1-basic-Cumulative-RankedOrder.sql 1-basic-StraightParty-Cumulative.sql 1-basic-Cumulative.sql 1-basic-CrossPartyEndorsement-Cumulative.sql 1-basic-AbsenteeByCategory-Cumulative.sql 1-basic-Primary-Cumulative.sql 1-basic-BallotRotation-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-Cumulative.sql 1-basic-SplitPrecinct-Cumulative.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-Cumulative-NofM.sql 1-basic-Cumulative-Provisional.sql

7.7.2-A.17 Tabulator, ranked order voting

The following tests are traceable to this requirement:

1-basic-NoBallots-RankedOrder.sql 1-basic-RankedOrder-1.sql 1-basic-RankedOrder-2.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-Primary-RankedOrder.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-AbsenteeByCategory-RankedOrder.sql 1-basic-Cumulative-RankedOrder.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-RankedOrder-NofM.sql 1-basic-RankedOrder-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql

7.7.3-A Central paper tabulator, ballot separation

This requirement is discussed in Section 3.8.

7.7.3-A.1 Central paper tabulator, unreadable ballots

This requirement specifies a “fail safe” behavior for a condition that, ideally, would not be reproducible by a test lab. The method to reproduce it, if there were one, would be specific to a particular voting system. Thus there is no test in Votetest that attempts to create the conditions under which the requirement would apply. For more information, see the discussion of Part 3 Req. 5.2.3-A in the VVSG.

7.7.3-A.2 Central paper tabulator, write-ins

Since the reasons for which a ballot might be flagged or separated for review are jurisdiction-dependent, the list of relevant tests will vary.

7.7.3-A.3 Central paper tabulator, overvotes, undervotes, blank ballots

This requirement is discussed in Section 3.8.

7.7.3-B Precinct paper tabulator, write-ins

Since the reasons for which a ballot might be flagged or separated for review are jurisdiction-dependent, the list of relevant tests will vary.

7.7.3-C ECOS, react to marginal marks and overvotes

This requirement is discussed in Section 3.8.

7.7.4-A Paper-based tabulator, ability to clear misfeed

This requirement specifies a “fail safe” behavior for a condition that, ideally, would not be reproducible by a test lab. The method to reproduce it, if there were one, would be specific to a particular voting system. Thus there is no test in Votetest that attempts to create the conditions under which the requirement would apply. For more information, see the discussion of Part 3 Req. 5.2.3-A in the VVSG.

7.7.4-B Paper-based tabulator, indicate status of misfed ballot

This requirement specifies a “fail safe” behavior for a condition that, ideally, would not be reproducible by a test lab. The method to reproduce it, if there were one, would be specific to a particular voting system. Thus there is no test in Votetest that attempts to create the conditions under which the requirement would apply. For more information, see the discussion of Part 3 Req. 5.2.3-A in the VVSG.

7.7.5-A Optical scanner, ignore unmarked voting targets

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.7.5-B ECOS, accurately detect marks

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.7.5-C MCOS, accurately detect perfect marks

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.7.5-D MCOS, accurately detect imperfect marks

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.7.5-E Paper-based tabulators, ignore extraneous outside voting targets

This requirement is discussed in Section 3.8.

7.7.5-F Optical scanner, ignore extraneous inside voting targets

This requirement is discussed in Section 3.8.

7.7.5-G MCOS, ignore hesitation marks

This requirement is discussed in Section 3.8.

7.7.5-H MCOS, marginal marks, no bias

This requirement is discussed in Section 3.8.

7.7.5-I MCOS, marginal marks, repeatability

This requirement is discussed in Section 3.8.

7.7.6-A Precinct EMS consolidation

All Votetest tests are traceable to this requirement.

7.7.6-A.1 DRE, consolidate in 5 minutes

All Votetest tests are traceable to this requirement.

7.8.1-A Reports are time stamped

All Votetest tests are traceable to this requirement.

7.8.1-B Timestamps should be ISO 8601 compliant

All Votetest tests are traceable to this requirement.

7.8.1-C Reporting is non-destructive

This requirement does not specify functional testing as an applicable test method, so it is out of scope for Votetest.

7.8.2-A Audit reports

All Votetest tests are traceable to this requirement.

7.8.2-B Pre-election reports

All Votetest tests are traceable to this requirement.

7.8.2-C Status reports

All Votetest tests are traceable to this requirement.

7.8.2-D Readiness reports, per polling place

All Votetest tests are traceable to this requirement.

7.8.2-E Readiness reports, precinct tabulator

All Votetest tests are traceable to this requirement.

7.8.2-F Readiness reports, central tabulator

All Votetest tests are traceable to this requirement.

7.8.2-G Readiness reports, public network test ballots

All Votetest tests are traceable to this requirement.

7.8.3.1-A Reporting, ability to produce text

All Votetest tests are traceable to this requirement.

7.8.3.1-B Report all votes cast

All Votetest tests are traceable to this requirement.

7.8.3.1-C Account for all cast ballots and all valid votes

All Votetest tests are traceable to this requirement.

7.8.3.1-D Vote data reports, discrepancies can’t happen

All Votetest tests are traceable to this requirement.

7.8.3.1-D.1 Discrepancies that happen anyway must be flagged

This requirement specifies a “fail safe” behavior for a condition that, ideally, would not be reproducible by a test lab. The method to reproduce it, if there were one, would be specific to a particular voting system. Thus there is no test in Votetest that attempts to create the conditions under which the requirement would apply. For more information, see the discussion of Part 3 Req. 5.2.3-A in the VVSG.

7.8.3.1-D.2 Discrepancies that happen anyway must be explainable

This requirement specifies a “fail safe” behavior for a condition that, ideally, would not be reproducible by a test lab. The method to reproduce it, if there were one, would be specific to a particular voting system. Thus there is no test in Votetest that attempts to create the conditions under which the requirement would apply. For more information, see the discussion of Part 3 Req. 5.2.3-A in the VVSG.

7.8.3.1-E Reporting, combined precincts

This requirement is discussed in Section 3.8.

7.8.3.1-F Precinct tabulators, no tallies before close of polls

This requirement falls within the scope of security assessment, so it is out of scope for Votetest.

7.8.3.2-A Report cast ballots

All Votetest tests are traceable to this requirement.

7.8.3.2-B Report read ballots

All Votetest tests are traceable to this requirement.

7.8.3.2-B.1 Report read ballots, multi-page

All Votetest tests are traceable to this requirement.

7.8.3.2-B.2 Report read ballots by party

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.8.3.2-B.3 Report read provisional ballots

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.8.3.2-C Report counted ballots

All Votetest tests are traceable to this requirement.

7.8.3.2-C.1 Report counted ballots by party

The following tests are traceable to this requirement:

1-basic-Primary-StraightParty.sql 1-basic-Primary.sql 1-basic-Primary-RankedOrder.sql 1-basic-Primary-BallotRotation.sql 1-basic-Primary-SplitPrecinct.sql 1-basic-Primary-WriteIns.sql 1-basic-Primary-Cumulative.sql 1-basic-Primary-CrossPartyEndorsement.sql 1-basic-Primary-NofM.sql 1-basic-Primary-Provisional.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-samples-CecilRPrimary1998.sql

7.8.3.2-C.2 Report counted provisional ballots

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.8.3.2-C.3 Report blank ballots

All Votetest tests are traceable to this requirement.

7.8.3.2-D Report counted ballots by contest

All Votetest tests are traceable to this requirement.

7.8.3.3-A Report votes for each contest choice

All Votetest tests are traceable to this requirement.

7.8.3.3-B Report overvotes for each contest

All Votetest tests are traceable to this requirement.

7.8.3.3-B.1 Reporting overvotes, ad hoc queries

This requirement is discussed in Section 3.8.

7.8.3.3-C Report undervotes for each contest

All Votetest tests are traceable to this requirement.

7.8.3.3-D Ranked order voting, report results

The following tests are traceable to this requirement:

1-basic-NoBallots-RankedOrder.sql 1-basic-RankedOrder-1.sql 1-basic-RankedOrder-2.sql 1-basic-StraightParty-RankedOrder.sql 1-basic-Primary-RankedOrder.sql 1-basic-BallotRotation-RankedOrder.sql 1-basic-AbsenteeByCategory-RankedOrder.sql 1-basic-Cumulative-RankedOrder.sql 1-basic-SplitPrecinct-RankedOrder.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-RankedOrder-NofM.sql 1-basic-RankedOrder-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql

7.8.3.3-E Include in-person votes

All Votetest tests are traceable to this requirement.

7.8.3.3-F Include absentee votes

The following tests are traceable to this requirement:

1-basic-AbsenteeByCategory-StraightParty.sql 1-basic-AbsenteeByCategory-RankedOrder.sql 1-basic-AbsenteeByCategory.sql 1-basic-AbsenteeByCategory-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-AbsenteeByCategory-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-Cumulative.sql 1-basic-AbsenteeBySpecialPrecinct-CrossPartyEndorsement.sql 1-basic-AbsenteeByCategory-NofM.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Yes-or-No.sql 1-basic-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeBySpecialPrecinct.sql 1-basic-Primary-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-SplitPrecinct.sql 1-basic-SplitPrecinct-AbsenteeByCategory.sql 1-basic-BallotRotation-AbsenteeBySpecialPrecinct.sql 1-basic-BallotRotation-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql 1-basic-AbsenteeBySpecialPrecinct-NofM.sql 1-basic-AbsenteeBySpecialPrecinct-RankedOrder.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-StraightParty.sql

7.8.3.3-G Include write-in votes

The following tests are traceable to this requirement:

1-basic-samples-AlleganyGeneral2004.sql 1-basic-samples-FairfaxGeneral2004.sql 1-basic-StraightParty-WriteIns.sql 1-basic-RankedOrder-WriteIns.sql 1-basic-NoChoices-1ofM.sql 1-basic-NoChoicesNoBallots-1ofM.sql 1-basic-WriteIns.sql 1-basic-WriteInsAliases.sql 1-basic-Primary-WriteIns.sql 1-basic-BallotRotation-WriteInsAliases.sql 1-basic-AbsenteeByCategory-WriteIns.sql 1-basic-SplitPrecinct-WriteIns.sql 1-basic-WriteInsAliases-Cumulative.sql 1-basic-NofM-WriteIns.sql 1-basic-WriteInsAliases-NofM.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-CrossPartyEndorsement-WriteIns.sql 1-basic-AbsenteeBySpecialPrecinct-WriteIns.sql 1-basic-WriteInsAliases-AbsenteeBySpecialPrecinct.sql 1-basic-WriteInsAliases-AbsenteeByCategory.sql

7.8.3.3-H Include accepted provisional-challenged votes

The following tests are traceable to this requirement:

1-basic-StraightParty-Provisional.sql 1-basic-Provisional.sql 1-basic-Primary-Provisional.sql 1-basic-RankedOrder-Provisional.sql 1-basic-BallotRotation-Provisional.sql 1-basic-Cumulative-Provisional.sql 1-basic-AbsenteeByCategory-Provisional.sql 1-basic-SplitPrecinct-Provisional.sql 1-basic-WriteInsAliases-Provisional.sql 1-basic-NofM-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-NofM-Provisional.sql 1-basic-CrossPartyEndorsement-Provisional.sql 1-basic-AbsenteeBySpecialPrecinct-Provisional.sql

7.8.3.3-I Include accepted reviewed votes

Since the reasons for which a ballot might be flagged or separated for review are jurisdiction-dependent, the list of relevant tests will vary.

4 Advanced schema

The schema for core requirements is designed only for testing. It does not respond to the security, privacy, accessibility, or usability requirements of the VVSG.

The schema is built in five layers:

  1. Translation of the data model. This layer contains all of the tables and data. The other layers are comprised entirely of views.
  2. Conveniences defined over the data model.
  3. Adaptation layer. This layer translates the raw voter inputs per the data model into the effective voter inputs required by the logic model.
  4. Data integrity checks.
  5. Translation of the logic model.

The schema was developed with PostgreSQL [7] running on a GNU/Linux operating system. It uses extensions to the SQL standard [2] that might not function as intended with other databases.

Layer 1, the translation of the data model, was covered in Section 3.6. The following subsections cover the other four layers.

4.1 Conveniences

All assertions have as a precondition the assumption that all of the constraints are satisfied (see Section 3.5.5).

4.1.1 FilteredBallotContestAssociation

The view FilteredBallotContestAssociation identifies all Contests that appear on a given Ballot, excluding ranked order Contests.

create view FilteredBallotContestAssociation (BallotId, ContestId) as  
  select BallotId, ContestId  
    from Ballot  
      natural join BallotStyleContestAssociation  
      natural join Contest  
    where CountingLogic <> ’Ranked order’;

Assertion 1 For each Ballot, FilteredBallotContestAssociation contains exactly one row for each non-ranked-order Contest appearing in the BallotStyle identified by Ballot.StyleId, and zero rows for any ranked order Contests.

  1. For each Ballot in table Ballot, the result of Ballot natural join BallotStyleContestAssociation contains one row for each Contest appearing in the BallotStyle identified by Ballot.StyleId. The primary key constraints on Ballot and BallotStyleContestAssociation ensure that there cannot be more than one such row.
  2. The primary key constraint on table Contest and the foreign key constraint on table BallotStyleContestAssociation ensure that the natural join of the previous result with table Contest will not drop rows. Consequently, for each Ballot, there is still one row for each Contest appearing in the BallotStyle identified by Ballot.StyleId.
  3. The where clause removes rows pertaining to ranked order Contests.

Assertion 2 If the BallotStyle contains zero Contests, BallotStyleContestAssociation contains no rows with that BallotId.

If BallotStyleContestAssociation contains no rows with a StyleId matching Ballot.StyleId, meaning that the BallotStyle contains no Contests, then the natural join of Ballot and BallotStyleContestAssociation produces no rows for that Ballot. The subsequent natural join with Contest cannot add back a BallotId that was dropped, so FilteredBallotContestAssociation correctly contains no rows for that Ballot.

4.1.2 ReportingContextAssociationMerge

The view ReportingContextAssociationMerge merges ReportingContexts inherited from the BallotStyle with ReportingContexts specified on Ballot instances. Duplicates are suppressed.

create view ReportingContextAssociationMerge (BallotId, ReportingContext) as  
    select BallotId, ReportingContext  
      from BallotReportingContextAssociation  
  union  
    select BallotId, ReportingContext  
      from Ballot natural join BallotStyleReportingContextAssociation;

Assertion 3 For each Ballot, ReportingContextAssociationMerge contains exactly one row for each relevant ReportingContext.

  1. The only two ways by which a ReportingContext may be relevant to a Ballot are by association with a Ballot’s BallotStyle or by association with the Ballot itself.
  2. If a ReportingContext is associated with the BallotStyle, a corresponding (BallotId, ReportingContext) tuple will be projected from the result of Ballot natural join BallotStyleReportingContextAssociation.
  3. If a ReportingContext is associated with the Ballot itself, a corresponding (BallotId, ReportingContext) tuple will be selected from BallotReportingContextAssociation.
  4. Duplicate (BallotId, ReportingContext) tuples are suppressed by the union operator.

Assertion 4 For each Ballot, ReportingContextAssociationMerge contains at least one row.

The case where no ReportingContext is relevant to a given Ballot is prohibited by Constraint V and is detected by the integrity view UnreportedBallots (see Section 4.3).

4.1.3 VotableChoices

The view VotableChoices identifies all canonical Choices for which a valid VoterInput could exist (those contained in the applicable BallotStyles), excluding Aliases.

create view VotableChoices (BallotId, ChoiceId) as  
  select BallotId, ChoiceId  
    from Ballot  
      natural join BallotStyleContestAssociation  
      natural join Choice  
    where ChoiceId not in  
      (select AliasId from Alias);

Assertion 5 For each Ballot, VotableChoices contains exactly one row for each canonical Choice for which the Ballot could contain a vote.

  1. For each Ballot in table Ballot, the result of Ballot natural join BallotStyleContestAssociation contains one row for each Contest appearing in the BallotStyle identified by Ballot.StyleId. The primary key constraints on Ballot and BallotStyleContestAssociation ensure that there cannot be more than one such row.
  2. For each Ballot, joining Choice with the previous result produces exactly one row for each Choice pertaining to any Contest appearing on the Ballot. The primary key constraint on Choice ensures that there cannot be more than one such row.
  3. By definition, a canonical Choice does not appear in the AliasId column of table Alias, so the where clause does not eliminate any canonical Choices.

Assertion 6 VotableChoices contains no rows pertaining to any non-canonical Choices (Aliases).

The where clause eliminates rows pertaining to non-canonical Choices (those appearing in the AliasId column of table Alias).

Assertion 7 If the BallotStyle of a given Ballot contains zero Contests, VotableChoices contains no rows with that BallotId.

If BallotStyleContestAssociation contains no rows with a StyleId matching Ballot.StyleId, meaning that the BallotStyle contains no Contests, then the natural join of Ballot and BallotStyleContestAssociation produces no rows for that Ballot. The subsequent natural join with Choice cannot add back a BallotId that was dropped, so VotableChoices correctly contains no rows for that Ballot.

Assertion 8 If the BallotStyle of a given Ballot contains only Contests having zero Choices, VotableChoices contains no rows with that BallotId.

If the BallotStyle of a given Ballot contains only Contests having zero Choices, then the natural join with Choice will eliminate all rows containing that BallotId.

4.1.4 ReportingContextContestAssociation

The view ReportingContextContestAssociation identifies all Contests that are relevant in a given ReportingContext. This includes those appearing in a BallotStyle associated with the ReportingContext and those appearing in a Ballot associated with the ReportingContext. A BallotStyle association can make a Contest relevant even if there are no applicable Ballots.

create view ReportingContextContestAssociation (ReportingContext, ContestId) as  
    select ReportingContext, ContestId  
      from BallotStyleReportingContextAssociation  
        natural join BallotStyleContestAssociation  
  union  
    select ReportingContext, ContestId  
      from BallotReportingContextAssociation  
        natural join Ballot  
        natural join BallotStyleContestAssociation;

Assertion 9 For each ReportingContext, ReportingContextContestAssociation contains exactly one row for each Contest that is relevant in that ReportingContext.

  1. The relevance of a Contest within a ReportingContext happens through an intermediary BallotStyle. The association of Contests with BallotStyles is specified by the table BallotStyleContestAssociation.
  2. A BallotStyle can become relevant to a ReportingContext in two ways: directly, via BallotStyleReportingContextAssociation, or indirectly, via BallotReportingContextAssociation and Ballot.StyleId.
  3. If a BallotStyle is directly relevant to a ReportingContext, a corresponding (ReportingContext, ContestId) tuple will be projected from the natural join of BallotStyleReportingContextAssociation and BallotStyleContestAssociation.
  4. If a BallotStyle is indirectly relevant to a ReportingContext, there must exist a Ballot having that BallotStyle that is associated with that ReportingContext via BallotReportingContextAssociation. BallotReportingContextAssociation natural join Ballot will therefore contain one row identifying that Ballot and that ReportingContext. The subsequent natural join with BallotStyleContestAssociation is on the column StyleId; constraints ensure that this join will not drop rows. Consequently, a (ReportingContext, ContestId) tuple corresponding to the indirect association between the ReportingContext and the Contest will be projected from the three-way join.
  5. Duplicate (ReportingContext, ContestId) tuples are suppressed by the union operator.

4.1.5 FilteredContextContestAssociation

The view FilteredContextContestAssociation is the same as ReportingContextContestAssociation except it excludes ranked order Contests.

create view FilteredContextContestAssociation (ReportingContext, ContestId) as  
  select ReportingContext, ContestId  
    from ReportingContextContestAssociation  
      natural join Contest  
    where CountingLogic <> ’Ranked order’;

Assertion 10 For each ReportingContext, FilteredContextContestAssociation contains exactly one row for each non-ranked-order Contest that is relevant in that ReportingContext, and zero rows for each ranked-order Contest.

Per Assertion 9, for each ReportingContext, ReportingContextContestAssociation contains exactly one row for each Contest that is relevant in that ReportingContext. Constraints ensure that the natural join with Contest will not drop rows. The only difference from ReportingContextContestAssociation therefore is the elimination of ranked order Contests by the where clause.

4.1.6 FilteredContextChoiceAssociation

The view FilteredContextChoiceAssociation identifies all Choices that are relevant in a given ReportingContext, excluding Aliases and Choices from ranked order Contests.

create view FilteredContextChoiceAssociation (ReportingContext, ChoiceId) as  
  select ReportingContext, ChoiceId  
    from FilteredContextContestAssociation  
      natural join Choice  
    where ChoiceId not in  
      (select AliasId from Alias);

Assertion 11 For each ReportingContext, FilteredContextChoiceAssociation contains exactly one row for each canonical Choice in each non-ranked-order Contest that is relevant in that ReportingContext, and zero rows for any other Choice.

Per Assertion 10, for each ReportingContext, FilteredContextContestAssociation contains exactly one row for each non-ranked-order Contest that is relevant in that ReportingContext. For each ReportingContext, the result of FilteredContextContestAssociation natural join Choice contains exactly one row for each Choice in each non-ranked-order Contest that is relevant in that ReportingContext. The where clause eliminates rows pertaining to non-canonical Choices (Aliases).

4.1.7 BallotCounts

The view BallotCounts produces the count of the number of read and counted Ballots for each ReportingContext.

create view BallotCounts (ReportingContext, Read, Counted) as  
  select Name, count(BallotId), count (nullif (Accepted, false))  
    from Ballot  
      natural join ReportingContextAssociationMerge  
      right outer join ReportingContext on (Name = ReportingContext)  
    group by Name;

Assertion 12 For each ReportingContext, BallotCounts contains exactly one row giving the number of relevant Ballots (in the Read column) and the number of accepted Ballots (in the Counted column).

  1. Using Assertion 3, for each ReportingContext, the natural join of Ballot and ReportingContextAssociationMerge contains one row for each relevant Ballot.
  2. For each ReportingContext having zero relevant Ballots, the right outer join with ReportingContext generates a single row having a nulls in the BallotId and Accepted columns. In all other cases, the right outer join has the effect of duplicating the ReportingContext column in the Name column and leaving the other columns unchanged.
  3. In the three-way join, there is at least one row for each ReportingContext. Grouping by Name therefore yields one row for each ReportingContext.
  4. The count operation does not include nulls. Therefore, for each ReportingContext having one or more relevant Ballots, count(BallotId) yields the number of such Ballots, and count (nullif (Accepted, false)) yields the number of those that were accepted.
  5. For each ReportingContext having zero relevant Ballots, the three-way join contains a single row with nulls in both the BallotId and Accepted columns, so both counts yield 0.

4.1.8 BallotCountsByConfiguration

The view BallotCountsByConfiguration produces the count of the number of read and counted Ballots broken down by BallotStyle within each ReportingContext. Rows pertaining to combinations of ReportingContext and BallotStyle that have no applicable Ballots are suppressed.

create view BallotCountsByConfiguration (ReportingContext, StyleId,  
                                         Read, Counted) as  
  select ReportingContext, StyleId, count(*), count (nullif (Accepted, false))  
    from Ballot natural join ReportingContextAssociationMerge  
    group by ReportingContext, StyleId;

Assertion 13 For each combination of ReportingContext and BallotStyle having relevant Ballots, BallotCountsByConfiguration contains exactly one row giving the number of relevant Ballots (in the Read column) and the number of accepted Ballots (in the Counted column).

  1. Using Assertion 3, for each ReportingContext, the natural join of Ballot and ReportingContextAssociationMerge contains one row for each relevant Ballot.
  2. Grouping by ReportingContext and StyleId yields exactly one row for each combination of ReportingContext and BallotStyle having relevant Ballots.
  3. count(*) and count (nullif (Accepted, false)) yield the number of Ballots and the number of accepted Ballots within each group.

Assertion 14 BallotCountsByConfiguration contains no rows for combinations of ReportingContext and BallotStyle that have no relevant Ballots.

The natural join of Ballot with ReportingContextAssociationMerge cannot generate a row with a particular combination of ReportingContext and BallotStyle unless there exists a Ballot of that BallotStyle that is relevant in that ReportingContext.

4.1.9 BallotCountsByCategory
create view BallotCountsByCategory (ReportingContext, Category,  
                                    Read, Counted) as  
  select ReportingContext, Category, count(*), count (nullif (Accepted, false))  
    from Ballot  
      natural join ReportingContextAssociationMerge  
      natural join BallotCategoryAssociation  
    group by ReportingContext, Category;

Assertion 15 For each combination of ReportingContext and BallotCategory having relevant Ballots, BallotCountsByCategory contains exactly one row giving the number of relevant Ballots (in the Read column) and the number of accepted Ballots (in the Counted column).

  1. Using Assertion 3, for each ReportingContext, the natural join of Ballot and ReportingContextAssociationMerge contains one row for each relevant Ballot.
  2. For each ReportingContext, for each relevant Ballot, the natural join of the previous result with BallotCategoryAssociation yields a row for each associated BallotCategory.
  3. Grouping by ReportingContext and Category yields exactly one row for each combination of ReportingContext and BallotCategory having relevant Ballots.
  4. count(*) and count (nullif (Accepted, false)) yield the number of Ballots and the number of accepted Ballots within each group.

Assertion 16 BallotCountsByCategory contains no rows for combinations of ReportingContext and BallotCategory that have no relevant Ballots.

The natural join of (Ballot natural join ReportingContextAssociationMerge) with BallotCategoryAssociation cannot generate a row with a particular combination of ReportingContext and BallotCategory unless there exists a Ballot of that BallotCategory that is relevant in that ReportingContext.

4.1.10 BallotCountsByCategoryAndConfiguration
create view BallotCountsByCategoryAndConfiguration (ReportingContext, StyleId,  
                                                    Category, Read, Counted) as  
  select ReportingContext, StyleId, Category, count(*),  
         count (nullif (Accepted, false))  
    from Ballot  
      natural join ReportingContextAssociationMerge  
      natural join BallotCategoryAssociation  
    group by ReportingContext, StyleId, Category;

The assertions and discussion for BallotCountsByCategoryAndConfiguration are analogous to those of BallotCountsByConfiguration and BallotCountsByCategory.

4.1.11 BlankBallot
create view BlankBallot (BallotId, StyleId, Accepted) as  
  select BallotId, StyleId, Accepted  
    from Ballot natural left outer join VoterInput  
    where Value is null;

Assertion 17 BlankBallot contains exactly one row for each Ballot having no associated votes.

Ballot natural left outer join VoterInput produces one row with a non-null Value column for each vote (possibly many such rows with the same BallotId), and exactly one row with a null Value column for each Ballot having no associated votes. The where clause selects only the latter rows.

4.1.12 BlankBallotCounts
create view BlankBallotCounts (ReportingContext, Read, Counted) as  
  select Name, count(BallotId), count (nullif (Accepted, false))  
    from BlankBallot  
      natural join ReportingContextAssociationMerge  
      right outer join ReportingContext on (Name = ReportingContext)  
    group by Name;

The assertion and discussion for BlankBallotCounts are parallel to those of BallotCounts, substituting BlankBallot for Ballot.

4.1.13 BlankBallotCountsByConfiguration
create view BlankBallotCountsByConfiguration (ReportingContext, StyleId,  
                                              Read, Counted) as  
  select ReportingContext, StyleId, count(*), count (nullif (Accepted, false))  
    from BlankBallot natural join ReportingContextAssociationMerge  
    group by ReportingContext, StyleId;

The assertions and discussion for BlankBallotCountsByConfiguration are parallel to those of BallotCountsByConfiguration, substituting BlankBallot for Ballot.

4.2 Adaptation

Converting the raw voter inputs into the effective voter inputs required by the logic model involves Alias reconciliation, implementation of straight party voting, and generation of default (0) values for ballot positions that were not voted.

The VoterInput table has a primary key on (BallotId, ChoiceId), so there is at most one row for any given ballot position on any given Ballot. Deliberately, the adaptation views do not preserve this constraint in the event that double votes result from Alias reconciliation or straight party voting. Both of these cases are treated as errors for testing purposes, and the errors are most easily located by looking for duplicate keys. This is done by the integrity view DoubleVotes (see Section 4.3).

All assertions have as a precondition the assumption that all of the constraints are satisfied (see Section 3.5.5).

4.2.1 AntiAliasedVoterInput

AntiAliasedVoterInput provides a view of VoterInput in which all Choices have been “canonicalized.”

create view AntiAliasedVoterInput (BallotId, ChoiceId, Value) as  
  select BallotId, coalesce (Alias.ChoiceId, VoterInput.ChoiceId), Value  
    from VoterInput left outer join Alias  
      on VoterInput.ChoiceId = Alias.AliasId;

Assertion 18 AntiAliasedVoterInput contains exactly one row for each row in VoterInput, with any non-canonical Choices replaced by the associated canonical Choices.

  1. Alias.AliasId is a primary key, so there can be at most one row in Alias matching any given row of VoterInput on VoterInput.ChoiceId = Alias.AliasId.
  2. If there is a row in Alias matching a row of VoterInput, the left outer join generates exactly one row with the canonical equivalent of VoterInput.ChoiceId in the column Alias.ChoiceId.
  3. If there is no row in Alias matching a row of VoterInput, the left outer join generates exactly one row with a null in the column Alias.ChoiceId.
  4. coalesce (Alias.ChoiceId, VoterInput.ChoiceId) substitutes the canonical Choice in the case where a matching row in Alias exists, and retains the original Choice in the case where no such row exists and Alias.ChoiceId is null.

4.2.2 VoterInputMerge

VoterInputMerge provides a view over AntiAliasedVoterInput in which the side-effects implied by straight party votes have been incorporated. If a straight party selection Contest is overvoted, it has no side-effects.

VoterInputMerge depends on two intervening views, ValidStraightPartyVotes and ImpliedStraightPartyVotes.

create view ValidStraightPartyVotes (BallotId, Party) as  
  select BallotId, max(Name)      -- There can be only one.  See below.  
    from AntiAliasedVoterInput  
      natural join Choice  
      natural join Contest  
    where CountingLogic = ’Straight party selection’  
    group by BallotId  
    having sum(Value) = 1;        -- There can be only one.

Assertion 19 ValidStraightPartyVotes contains exactly one row for each Ballot containing a vote in a straight party selection Contest, excluding those that overvoted the straight party selection Contest.

  1. The primary key on VoterInput and Assertion 18 ensure that AntiAliasedVoterInput natural join Choice will have the same number of rows as VoterInput.
  2. The natural join of the previous result with Contest again adds columns but yields the same number of rows as VoterInput.
  3. The where clause eliminates all rows pertaining to Contests that are not straight party selection Contests.
  4. Constraint VII states that a given BallotStyle may contain at most one Contest with CountingLogic = Straight party selection.
  5. Straight party Contests are implicitly 1-of-M Contests.
  6. Constraint I states that any remaining rows must have a VoterInput.Value of 1.
  7. The having clause therefore eliminates rows pertaining to straight party Contests that were overvoted (having two or more associated votes).
  8. There can be at most one row remaining for a given BallotId. If such a row exists for a given Ballot, max(Name) retrieves the name of the Party that was selected in the straight party selection Contest. (The name cannot be selected directly due to the intervening group by operation.)

Note that ValidStraightPartyVotes does not filter out Ballots that are not accepted.

create view ImpliedStraightPartyVotes (BallotId, ChoiceId, Value) as  
  select BallotId, ChoiceId, Value  
    from VotableChoices  
      natural join Endorsement  
      natural join ValidStraightPartyVotes;

Assertion 20 ImpliedStraightPartyVotes contains exactly one row for each vote that is implied by a straight party vote.

  1. Per Assertion 5, for each Ballot, VotableChoices contains exactly one row for each canonical Choice for which the Ballot could contain a vote.
  2. The primary key on Endorsement ensures that there is at most one row for a given combination of Party and ChoiceId.
  3. Constraint XV states that the Choice referenced by an Endorsement must be canonical.
  4. For each Ballot, VotableChoices natural join Endorsement contains one row for each vote implied by any possible straight party vote.
  5. The natural join of the previous result with ValidStraightPartyVotes eliminates all rows except those pertaining to actual, non-overvoted straight party votes.

Note that ImpliedStraightPartyVotes does not do anything about the possibility that endorsements may be ill-formed (e.g., containing overvotes).

VoterInputMerge simply concatenates the contents of the previous two views. VoterInputMerge does not inherently prevent there from being more than one row with the same (BallotId, ChoiceId). This case violates Constraint XII and is detected by the integrity view StraightPartyOverrides (see Section 4.3).

create view VoterInputMerge (BallotId, ChoiceId, Value) as  
    select BallotId, ChoiceId, Value from AntiAliasedVoterInput  
  union all  
    select BallotId, ChoiceId, Value from ImpliedStraightPartyVotes;

Assertion 21 VoterInputMerge contains exactly one row for each row in VoterInput, with any non-canonical Choices replaced by the associated canonical Choices, plus exactly one row for each vote that is implied by a straight party vote.

The assertion follows from Assertion 18, Assertion 20 and the definition of the union all operator.

Assertion 22 VoterInputMerge contains at most one row for a given combination of (BallotId, ChoiceId). The Value column contains either (1) the Value derived from a vote for that Choice, (2) the Value derived from a vote for an Alias of that Choice, or (3) the Value derived from a vote for that Choice implied by a straight party vote.

  1. By Assertion 18, Assertion 20, Constraint XII and Constraint XIV, it is not possible for AntiAliasedVoterInput and ImpliedStraightPartyVotes to both contain votes in a given Contest for a given Ballot.
  2. Table Choice is defined such that a Choice is uniquely associated with exactly one Contest.
  3. Consequently, AntiAliasedVoterInput and ImpliedStraightPartyVotes cannot both contain votes with a given combination of (BallotId, ChoiceId).
  4. If a given combination of (BallotId, ChoiceId) appears in AntiAliasedVoterInput, the Value column of VoterInputMerge will contain the Value derived from a vote for the Choice or an Alias of that Choice, satisfying (1) or (2).
  5. If a given combination of (BallotId, ChoiceId) appears in ImpliedStraightPartyVotes, the Value column of VoterInputMerge will contain the Value derived from a vote for that Choice implied by a straight party vote, satisfying (3).

4.2.3 EffectiveInput

Finally, the view EffectiveInput generates zeroes for ballot positions that were not voted. This is appropriate for all Contest types except ranked order. Ranked order tabulators should instead access VoterInputMerge directly.

create view EffectiveInput (BallotId, ChoiceId, Value) as  
  select BallotId, ChoiceId, coalesce (Value, 0)  
    from VotableChoices natural left outer join VoterInputMerge;

Assertion 23 For each Ballot, EffectiveInput contains exactly one row for each canonical Choice for which the Ballot could contain a vote. The Value column contains either (1) the Value derived from a vote for that Choice, (2) the Value derived from a vote for an Alias of that Choice, (3) the Value derived from a vote for that Choice implied by a straight party vote, or (4) the default value of zero.

  1. Per Assertion 5, for each Ballot, VotableChoices contains exactly one row for each canonical Choice for which the Ballot could contain a vote.
  2. Per Assertion 22, VoterInputMerge contains at most one row for a given combination of (BallotId, ChoiceId).
  3. Consequently, VotableChoices natural left outer join VoterInputMerge contains the same number of rows as VotableChoices.
  4. Since VotableChoices does not have a Value column, the Value column of the join will come from VoterInputMerge when a matching row exists and be null when no matching row exists.
  5. If Value is not null, then it came from VoterInputMerge. Per Assertion 22, this Value will satisfy one of (1), (2), or (3).
  6. coalesce (Value, 0) has the effect of replacing nulls with zeroes, satisfying (4).

4.3 Integrity checks

For those integrity constraints that are too complex to code directly as SQL constraints within the tables, a series of views exists to look for problems. All of the integrity checking views should always be empty. If data appear in any of the views, the input was invalid and the results of the model will be invalid. The integrity views are listed in Table 4 but their definitions have been elided. Interested readers can find them in the Votetest distribution, in the file Infrastructure-VoteSchema.sql.


Table 4: Integrity checks

Constraint
Integrity view(s)


Constraint I OutOfRangeVoterInputs, OutOfRangeEndorsements


Constraint II N/A, enforced by SQL check constraint


Constraint III N/A, enforced by SQL check constraint


Constraint IV N/A, enforced by SQL check constraint


Constraint V UnreportedBallots


Constraint VI ExtraneousInputs


Constraint VII MoreThanOneStraightPartyContest


Constraint VIII CircularStraightPartyEndorsements


Constraint IX NonExistentParties


Constraint X N/A, enforced by SQL primary key constraint


Constraint XI DoubleVotes


Constraint XII StraightPartyOverrides


Constraint XIII DoubleIndirectAliases


Constraint XIV CrossContestAliases


Constraint XV EndorsedAliases


Constraint XVI TooManyWriteIns



4.4 Translation of logic model

The following transforms are used to render the logic model as SQL.

  1. Each function is replaced by a view in which the parameters form the primary key and the last column is the value of the function.
  2. Time parameters (t) are factored out. All views implicitly project results for the time t corresponding to the current state of the database.
  3. When a function takes both a Contest and a Choice as parameters, the Contest parameter is omitted. With the data model used here, the Contest can be inferred from the Choice.
  4. Logic is translated into those SQL constructs that are most transparently equivalent.
  5. Ranked order Contests, which are not handled by the logic model, are suppressed.
  6. Irrelevant values, such as zero tallies for Choices that do not appear in the applicable BallotStyle or Contests that are not relevant in the applicable ReportingContext, are suppressed.

The following subsections first quote relevant portions of the logic model, then describe their analogs in the schema. Some terms from the logic model are elided from this discussion. For complete information on the logic model, please refer to the VVSG [1].

All assertions have as a precondition the assumption that all of the constraints are satisfied (see Section 3.5.5).

4.4.1 S(c,r,t,v)

Ballot v’s vote with respect to contest choice c in contest r as of time t. For checkboxes and the like, the value is 1 (selected) or 0 (not selected). For cumulative voting, the value is the number of votes that v gives to contest choice c in contest r. If the applicable ballot style does not include contest r, S(c,r,t,v) = 0.

Assertion 24 The relevant case of the quaternary function S is implemented by the view EffectiveInput. For each Ballot, for each canonical Choice appearing on that Ballot, column Value contains the value specified by the definition of S(c,r,t,v) for c = ChoiceId, r = Choice.ContestId, t as of the state of the database, and v = BallotId.

Follows from Assertion 23. Rows are not generated for the irrelevant case where S(c,r,t,v) is defined to be zero. Note that EffectiveInput does not eliminate inputs for ranked order Contests.

4.4.2 S(r,t,v)

The total number of votes that ballot v has in contest r as of time t.

          ∑
S(r,t,v) =    S(c,r,t,v)
        c∈C(r,t)

The ternary function S is implemented by the view S. The current value of S(r,t,v) is obtained by selecting S_val where ContestId = r and BallotId = v. The view S contains rows only for Contests that actually appear on the Ballot according to its BallotStyle. All others are defined to be 0.

create view S (ContestId, BallotId, S_val) as  
  select ContestId, BallotId, coalesce (sum (Value), 0)  
    from FilteredBallotContestAssociation  
      natural left outer join Choice  
      natural left outer join EffectiveInput  
    group by ContestId, BallotId;

Assertion 25 For each Ballot, for each non-ranked-order Contest appearing on that Ballot, column S_val of S contains the value specified by the definition of S(r,t,v) for r = ContestId, t as of the state of the database, and v = BallotId.

  1. Per Assertion 1, for each Ballot, FilteredBallotContestAssociation contains exactly one row for each non-ranked-order Contest appearing in the BallotStyle identified by Ballot.StyleId, and zero rows for any ranked order Contests.
  2. Per Assertion 23, for each Ballot, EffectiveInput contains exactly one row for each canonical Choice for which the Ballot could contain a vote.
  3. For each Ballot, FilteredBallotContestAssociation natural left outer join Choice contains exactly one row for each Choice in each non-ranked-order Contest on the Ballot, plus exactly one row for each non-ranked-order Contest on the Ballot that has zero associated Choices.
  4. For each Ballot, the natural left outer join of the previous result with EffectiveInput contains (1) exactly one row for each canonical Choice in each non-ranked-order Contest on the Ballot, with Value from EffectiveInput, plus (2) exactly one row for each non-canonical Choice in each non-ranked-order Contest on the Ballot, with null Value, plus (3) exactly one row for each non-ranked-order Contest on the Ballot that has zero associated Choices, with null Value.
  5. For Contests having Choices, the value specified by the definition of S(r,t,v) follows directly by summing the Value column while grouping by ContestId and BallotId. The null values for non-canonical Choices are ignored by the summation operator. Constraint XIII and Constraint XIV prevent any Contest from having only Aliases as Choices.
  6. For Contests with zero associated Choices, the summation of a single null value returns null and coalesce (sum (Value), 0) substitutes the value zero.

VotesByContestAndContext is a convenience to retrieve all of the S_val vote counts for each relevant combination of ReportingContext and Contest. For each relevant combination of ReportingContext and Contest that contains no Ballots, there is a single row with nulls in the last three columns.

create view VotesByContestAndContext (ContestId, N, ReportingContext,  
                                      BallotId, Accepted, S_val) as  
  select ContestId, N, ReportingContext, BallotId, Accepted, S_val  
    from FilteredContextContestAssociation  
      natural join Contest  
      natural left outer join (S natural join ReportingContextAssociationMerge)  
      natural left outer join Ballot;

The discussion for the following two assertions is combined.

Assertion 26 For each relevant combination of ReportingContext and Contest (excluding ranked order), VotesByContestAndContext contains a row for each Ballot that contains that Contest and that is reported in that ReportingContext. Column Accepted is as specified in the table Ballot. Column S_val contains the value specified by the definition of S(r,t,v) for r = ContestId, t as of the state of the database, and v = BallotId.

Assertion 27 For each relevant combination of ReportingContext and Contest (excluding ranked order) where there does not exist a Ballot that contains that Contest and that is reported in that ReportingContext, VotesByContestAndContext contains a single row with nulls in the BallotId, Accepted, and S_val columns.

  1. Per Assertion 10, for each ReportingContext, FilteredContextContestAssociation contains exactly one row for each non-ranked-order Contest that is relevant in that ReportingContext, and zero rows for each ranked-order Contest.
  2. The natural join with Contest adds the column N but does not change the number of rows.
  3. Per Assertion 3, for each Ballot, ReportingContextAssociationMerge contains exactly one row for each relevant ReportingContext. Equivalently, for each ReportingContext, ReportingContextAssociationMerge lists every Ballot that is reported in that ReportingContext.
  4. Per Assertion 25, for each Ballot, the view S contains exactly one row for each non-ranked-order Contest appearing on that Ballot, with S_val as described above.
  5. For each Ballot, S natural join ReportingContextAssociationMerge yields the Cartesian product of the S rows (one for each non-ranked-order Contest appearing on that Ballot) with the ReportingContextAssociationMerge rows (one for each ReportingContext relevant to that Ballot).
  6. For each relevant combination of ReportingContext and Contest (excluding ranked order), the natural left outer join of (FilteredContextContestAssociation natural join Contest) and (S natural join ReportingContextAssociationMerge) contains a row for each Ballot that contains that Contest and that is reported in that ReportingContext. For each relevant combination of ReportingContext and Contest (excluding ranked order) where there does not exist a Ballot that contains that Contest and that is reported in that ReportingContext, the result contains a single row with nulls in the BallotId and S_val columns.
  7. The natural left outer join with Ballot adds the Accepted column but does not change the number of rows. Where BallotId is null, Accepted is also null.

4.4.3 S(c,r,t,v)

Ballot v’s vote with respect to contest choice c in contest r as accepted for counting purposes (i.e., valid votes only), as of time t.

                      { S(c,r,D (v ),v)   if S(r,D(v),v) ≤ N (r) ∧ A(t,v)
t ≥ tE → S′(c,r,t,v) =
                        0               otherwise

The quaternary function Sis implemented by the view SPrime. The current value of S(c,r,t,v) is obtained by selecting SPrime_val where ChoiceId = c and BallotId = v.

create view SPrime (ChoiceId, BallotId, SPrime_val) as  
  select ChoiceId, BallotId,  
    case  
      when S_val <= N and Accepted then Value  
      else 0  
    end  
    from EffectiveInput  
      natural join Choice  
      natural join Contest  
      natural join Ballot  
      natural join S;

Assertion 28 For each Ballot, for each canonical Choice for which that Ballot could contain a vote, excluding ranked order Contests, column SPrime_val of SPrime contains the value specified by the definition of S(c,r,t,v) for c = ChoiceId, r = Choice.ContestId, t as of the state of the database, and v = BallotId.

  1. Per Assertion 24, the quaternary function S is implemented by the view EffectiveInput. Per Assertion 23, EffectiveInput contains exactly one row for each canonical Choice for which the Ballot could contain a vote.
  2. The natural joins with Choice, then Contest, then Ballot add columns but do not change the number of rows.
  3. The natural join with S eliminates rows pertaining to Choices in ranked order Contests and adds the S_val column (providing S(r,t,v)) to the others.
  4. For each Ballot, for each canonical Choice for which the Ballot could contain a vote, the case statement generates the value of S(c,r,t,v) as specified above.

4.4.4 T(c,j,r,t)

The vote total for contest choice c in contest r and reporting context j as of time t. This does not include votes that are invalid due to overvoting or votes from ballots for which A(t,v) is false.

t ≥ t →  T (c,j,r,t) = ∑ S′(c,r,t  ,v )
    E              v∈V(j,t)     E
                        E

The quaternary function T is implemented by the view T. The current value of T(c,j,r,t) is obtained by selecting T_val where ChoiceId = c and ReportingContext = j.

create view T (ChoiceId, ReportingContext, T_val) as  
  select ChoiceId, ReportingContext, coalesce (sum (SPrime_val), 0)  
    from FilteredContextChoiceAssociation  
      natural left outer join  
        (SPrime natural join ReportingContextAssociationMerge)  
    group by ChoiceId, ReportingContext;

Assertion 29 For each ReportingContext, for each canonical Choice in each non-ranked-order Contest that is relevant in that ReportingContext, column T_val of T contains the value specified by the definition of T(c,j,r,t) for c = ChoiceId, j = ReportingContext, r = Choice.ContestId, and t as of the state of the database.

  1. Per Assertion 11, for each ReportingContext, FilteredContextChoiceAssociation contains exactly one row for each canonical Choice in each non-ranked-order Contest that is relevant in that ReportingContext.
  2. Per Assertion 28, for each Ballot, for each canonical Choice for which that Ballot could contain a vote, excluding ranked order Contests, column SPrime_val of SPrime contains the value specified by the definition of S(c,r,t,v).
  3. Per Assertion 3, for each Ballot, ReportingContextAssociationMerge contains exactly one row for each relevant ReportingContext.
  4. For each Ballot, SPrime natural join ReportingContextAssociationMerge yields the Cartesian product of the SPrime rows with the ReportingContextAssociationMerge rows.
  5. For each ReportingContext, the natural left outer join of FilteredContextChoiceAssociation with the previous result adds a single row with a null in the SPrime_val column for each canonical Choice in each non-ranked-order Contest for which there were no relevant Ballots. The rows already existing from the previous result are not changed.
  6. For each ReportingContext, for each canonical Choice in each non-ranked-order Contest that is relevant in that ReportingContext and for which at least one relevant Ballot exists, the value specified by the definition of T(c,j,r,t) follows directly by summing the SPrime_val column while grouping by ChoiceId and ReportingContext.
  7. For the case in which no relevant Ballot exists, the null that is returned by the summation operation on the single null value is changed to zero by coalesce (sum (SPrime_val), 0).

TSum is a convenience that sums T_val by Contest. Note that TSum does not eliminate ranked order contests but rather provides a value of zero for them in the TSum_val column.

create view TSum (ContestId, ReportingContext, TSum_val) as  
  select ContestId, ReportingContext, coalesce (sum (T_val), 0)  
    from ReportingContextContestAssociation  
      natural left outer join Choice  
      natural left outer join T  
    group by ContestId, ReportingContext;

Assertion 30 For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, column TSum_val of TSum contains the value c∈C(r,t)T(c,j,r,t) for j = ReportingContext, r = ContestId and t as of the state of the database.

  1. Per Assertion 9, for each ReportingContext, ReportingContextContestAssociation contains exactly one row for each Contest that is relevant in that ReportingContext.
  2. For each ReportingContext, ReportingContextContestAssociation natural left outer join Choice contains one row for each Choice in each Contest that is relevant in that ReportingContext, plus one row with null in the ChoiceId column for each Contest that is relevant in that ReportingContext that has no associated Choices.
  3. The natural left outer join of the previous result with T, using both the ChoiceId and ReportingContext columns, has the same number of rows as the previous result. Each row pertaining to a Choice in some non-ranked-order Contest acquires T_val supplying the value of T(c,j,r,t). Each row pertaining to a ranked order Contest or a Contest with no associated Choices acquires T_val containing a null value.
  4. For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext and that has at least one associated Choice, the value specified by c∈C(r,t)T(c,j,r,t) follows directly by summing the T_val column while grouping by ContestId and ReportingContext.

  5. For ranked order Contests and Contests having no associated Choices, the null that is returned by the summation operation on the single null value is changed to zero by coalesce (sum (T_val), 0).

4.4.5 O(j,r,t)

For a given contest and reporting context, the number of overvotes in read ballots for which A(t,v) is true as of time t. Each ballot in which contest r is overvoted contributes N(r) to O(j,r,t).

                        {
                   ∑       N (r)  if S(r,D (v),v) > N (r)∧ A(t,v)
t ≥ tE → O(j,r,t) =         0      otherwise
                 v∈V (j,tE)

The ternary function O is implemented by the view O. The current value of O(j,r,t) is obtained by selecting O_val where ContestId = r and ReportingContext = j.

create view O (ContestId, ReportingContext, O_val) as  
  select ContestId, ReportingContext, sum (  
      case  
        when S_val > N and Accepted then N  
        else 0  
      end                                 )  
    from VotesByContestAndContext  
    group by ContestId, ReportingContext;

Assertion 31 For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, column O_val of O contains the value specified by the definition of O(j,r,t) for j = ReportingContext, r = ContestId, and t as of the state of the database.

  1. Per Assertion 26, for each relevant combination of ReportingContext and Contest (excluding ranked order), VotesByContestAndContext contains a row for each Ballot that contains that Contest and that is reported in that ReportingContext. Column Accepted is as specified in the table Ballot. Column S_val contains the value specified by the definition of S(r,t,v) for r = ContestId, t as of the state of the database, and v = BallotId.
  2. Per Assertion 27, for each relevant combination of ReportingContext and Contest (excluding ranked order) where there does not exist a Ballot that contains that Contest and that is reported in that ReportingContext, VotesByContestAndContext contains a single row with nulls in the BallotId, Accepted, and S_val columns.
  3. For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, the value specified by the definition of O(j,r,t) follows directly by summing the result of the case statement for each row while grouping by ContestId and ReportingContext. In the case where Accepted and S_val are null, i.e., where there does not exist a Ballot that contains that Contest and that is reported in that ReportingContext, the case statement returns 0.

4.4.6 U(j,r,t)

For a given contest and reporting context, the number of undervotes in read ballots for which A(t,v) is true as of time t. A given ballot contributes at most N(r) to U(j,r,t). Ballot styles that do not include contest r do not contribute to this total.

                        {
                   ∑       N (r)- S(r,D (v),v)   if S(r,D(v),v) ≤ N (r)∧ A(t,v)
t ≥ tE → U(j,r,t) =        0                    otherwise
                 v∈V(j,tE)

The ternary function U is implemented by the view U. The current value of U(j,r,t) is obtained by selecting U_val where ContestId = r and ReportingContext = j.

create view U (ContestId, ReportingContext, U_val) as  
  select ContestId, ReportingContext, sum (  
      case  
        when S_val <= N and Accepted then N - S_val  
        else 0  
      end                                 )  
    from VotesByContestAndContext  
    group by ContestId, ReportingContext;

Assertion 32 For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, column U_val of U contains the value specified by the definition of U(j,r,t) for j = ReportingContext, r = ContestId, and t as of the state of the database.

The argument is parallel to that of Assertion 31, substituting U for O.

4.4.7 K(j,r,t)

For a given contest and reporting context, the number of read ballots for which A(t,v) is true as of time t (i.e., the number of ballots that should be counted). Ballot styles that do not include contest r do not contribute to this total.

The ternary function K is implemented by the view K. The current value of K(j,r,t) is obtained by selecting K_val where ContestId = r and ReportingContext = j.

create view K (ContestId, ReportingContext, K_val) as  
  select ContestId, ReportingContext,  
    (select count(*)  
       from Ballot  
         natural join ReportingContextAssociationMerge  
         natural join BallotStyleContestAssociation  
       where ReportingContextAssociationMerge.ReportingContext  
         = FilteredContextContestAssociation.ReportingContext  
       and BallotStyleContestAssociation.ContestId  
         = FilteredContextContestAssociation.ContestId  
       and Accepted)  
    from FilteredContextContestAssociation;

Assertion 33 For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, column K_val of K contains the value specified by the definition of K(j,r,t) for j = ReportingContext, r = ContestId, and t as of the state of the database.

  1. Per Assertion 10, for each ReportingContext, FilteredContextContestAssociation contains exactly one row for each non-ranked-order Contest that is relevant in that ReportingContext, and zero rows for each ranked-order Contest.
  2. Per Assertion 3, for each Ballot, ReportingContextAssociationMerge contains exactly one row for each relevant ReportingContext.
  3. For each Ballot, Ballot natural join ReportingContextAssociationMerge contains exactly one row for each relevant ReportingContext.
  4. For each Ballot, for each relevant ReportingContext, the natural join of the previous result with BallotStyleContestAssociation contains exactly one row for each Contest appearing on the Ballot. If the BallotStyle has no associated Contests, there are zero such rows.
  5. For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, the value specified by the definition of K(j,r,t) follows directly from counting the number of rows in the previous three-way join that have a matching ReportingContext and ContestId, and where Accepted is true.

4.4.8 Balance

Every vote must be accounted for.

t ≥ t →  ∑  T (c,j,r,t)+ O (j,r,t)+ U (j,r,t) = K (j,r,t)× N (r)
    E
        c∈C (r,t)

A check for this assertion is implemented by the view Balance. The current difference between c∈C(r,t)T(c,j,r,t) + O(j,r,t) + U(j,r,t) and K(j,r,t) ×N(r) is obtained by selecting Discrepancy where ContestId = r and ReportingContext = j. Discrepancy should always be zero.

create view Balance (ContestId, ReportingContext, Discrepancy) as  
  select ContestId, ReportingContext, K_val * N - (TSum_val + O_val + U_val)  
    from K  
      natural join TSum  
      natural join O  
      natural join U  
      natural join Contest;

Assertion 34

For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, column Discrepancy of Balance contains the value K(j,r,t) × N(r) - (∑                                     )
   c∈C (r,t)T (c,j,r,t)+ O (j,r,t)+ U (j,r,t) for j = ReportingContext, r = ContestId, and t as of the state of the database.

  1. Per Assertion 30, Assertion 31, Assertion 32 and Assertion 33, the views K, TSum, O and U each provide one of the needed values for each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext. (TSum additionally provides rows for ranked order Contests that will be eliminated.)
  2. The successive natural joins of K, TSum, O and U all occur on the columns ContestId and ReportingContext. Each join adds a column but does not change the number of rows. The rows in TSum pertaining to ranked order contests are eliminated by the first join.
  3. The natural join with Contest (on the column ContestId) adds the column N but does not change the number of rows.
  4. For each ReportingContext, for each non-ranked-order Contest that is relevant in that ReportingContext, the value specified above follows directly from the expression K_val * N - (TSum_val + O_val + U_val).

5 Advanced test development environment

5.1 Software prerequisites

All software, tools and materials were developed on a GNU/Linux operating system.

The following packages are required in order to build and run the programs in Votetest:

Name Short name Version tested Source




PostgreSQL postgres 8.3.74 [7]
Class Library for Numbers CLN 1.2.2 [8]
GNU Compiler Collection g++ 4.3.3 [9]
Flex: Fast Lexical Analyzer flex 2.5.35 [10]
Bison: GNU parser generator bison 2.3 [11]

Votetest uses extensions to the SQL standard [2] and the C++ standard [12] that might not function as intended with other databases and compilers.

Some help in configuring PostgreSQL is provided in Section 5.9.

5.2 Hardware prerequisites

Votetest was developed on a PC having a 3.6 GHz Pentium 4 processor, 1 GiB of RAM, and an 80 GB SATA hard drive. The resources of this PC were more than adequate for all tests in the basic test suite, and if necessary a lesser configuration should be usable. Performance limitations became obvious only with the large and complex scenarios generated for the scalability testing described in Section 5.8.

5.3 File listing

Files pertaining to the advanced test development environment are described in Table 5.

Table 5: Advanced files in the Votetest distribution
Files
Description
Details



runTest

Shell script to execute a test case.

Section 5.5.1



runAllTests

Shell script to execute all test cases and save output.

Section 5.5.2



output/

Empty subdirectory used to store the output of runAllTests.

Section 5.5.2



output_kill-overvotes/

Empty subdirectory used to store the output of runAllTests when the –kill-overvotes option is used.

Section 5.5.2



0-integrity-description.sql

SQL, test suite integrity checks (15 files).

Section 5.6



Infrastructure-Features.sql

SQL, create table mapping test cases to system capabilities.

Section 5.5.4



Infrastructure-IntegrityChecks.sql

SQL, show contents of all integrity views. This is invoked automatically by test cases and need not be used directly.

N/A



Infrastructure-KillOvervotes.sql

SQL, transform a test case into one that is executable on a system that prevents overvoting. This is invoked automatically by test cases and need not be used directly.

N/A



Infrastructure-PairsCoverage.pgcc

Source code of coverage checking utility.

Section 5.5.5



Infrastructure-PairsCoverage.sql

SQL, data needed by coverage checking utility.

Section 5.5.5



Infrastructure-TestFooter.sql

SQL, print “END TEST CASE OUTPUT” footer. This is invoked automatically by test cases and need not be used directly.

N/A



Infrastructure-TestHeader.sql

SQL, print “BEGIN TEST CASE OUTPUT” and timestamp and configure verbosity of output for all test cases. This is invoked automatically by test cases and need not be used directly.

N/A



Infrastructure-TestHook.sql

SQL, support the optional invocation of a test transformation script (e.g., Infrastructure-KillOvervotes.sql). This is invoked automatically by test cases and need not be used directly.

N/A



Infrastructure-VoteSchema.sql

SQL, create the schema. This is invoked automatically by test cases and need not be used directly.

Section 3.6
Section 4



ReportGenerator/

Subdirectory containing the source code of the advanced test development environment’s report generator. This is invoked automatically by test cases and need not be used directly.

Section 5.5.3



TestGenerator/

Subdirectory containing the source code of the advanced test development environment’s test generator.

Section 5.7



test_specs/

Subdirectory containing example input files for the test generator.

Section 5.7.3



Makefile.am
Makefile.in
aclocal.m4
configure
configure.ac
depcomp
install-sh
missing

Files having to do with the automake build process.

Section 5.4



INSTALL

Text file containing generic instructions on the use of the configure script.

Section 5.4



AUTHORS
NEWS
README

Unused files required by GNU standard.

N/A



5.4 Installation

Votetest is packaged with GNU automake [13], so all usual GNU tricks should work. Help on configuration options can be found in the INSTALL file or obtained by entering ./configure --help.

Normally, one should only need to do the following to compile ReportGenerator and TestGenerator.

bash-3.1$ ./configure  
bash-3.1$ make

However, in the event that PostgreSQL and/or CLN are installed in nonstandard locations, an invocation such as the following might be required.

bash-3.1$ ./configure \  
> CPPFLAGS="-I/usr/local/pgsql/include -I/usr/local/cln-1.1.13/include" \  
> LDFLAGS="-L/usr/local/pgsql/lib -L/usr/local/cln-1.1.13/lib"  
bash-3.1$ make

5.5 Infrastructure

5.5.1 runTest

The script runTest is used to run an SQL test case against the database and report the results from the Votetest environment.

A test case is executed by changing the current working directory to the directory containing the test suite and invoking the runTest script with the file name of the test case. The runTest script resets the database to an initial state and then feeds the test case to the SQL interpreter. No database named votetest other than the one created by the test suite should exist or it will be destroyed without warning.

Usage: ./runTest [--kill-overvotes] test-file-name.sql

Some test cases involve overvoting, which means they cannot be executed as-is on a system that prevents overvoting. If the –kill-overvotes switch is used, the test case is transformed into one that can be executed on a system that prevents overvoting. Otherwise, overvotes are processed and reported as they would be in a system that supports overvoting.

If a ballot overvotes a contest, –kill-overvotes removes all of that ballot’s votes in that contest, effectively converting overvotes into undervotes. This of course changes the expected results of the test case. The expected results in the normal configuration and with –kill-overvotes enabled are saved in the subdirectories sample_output and sample_output_kill-overvotes respectively.

5.5.2 runAllTests

The script runAllTests invokes runTest for each test case and directs the output into a file in the subdirectory named “output.” It then invokes runTest –kill-overvotes for each test case and directs the output into a file in the subdirectory named “output_kill-overvotes.” These results may then be compared with the contents of the sample_output and sample_output_kill-overvotes subdirectories to ensure that the test suite is operating as expected.

5.5.3 ReportGenerator

Usage: ReportGenerator [-v] context-name [context-name...]. A no-frills, plain-ASCII post-voting report for each specified ReportingContext is sent to standard output. As a convenience to test labs, the report total volume needed for the accuracy test protocol of the VVSG is also calculated and reported. A sample report is shown in Figure 9.

The verbose flag (-v) is only useful in ranked order contests. It causes the state of the ranked order logic (with many ballot images) to be output for each round of voting.



Figure 9: Sample report
         Report for context Precinct 1 generated 2007-03-21 09:19-0400  
 
                                          BALLOT COUNTS  
 
         Configuration                                  Read    Counted  
         -------------                                  ----    -------  
         Total                                            13         13  
                                            Blank          1          1  
         Precinct 1 Style                                 13         13  
                                            Blank          1          1  
 
                                           VOTE TOTALS  
 
         Straight party, vote for at most 1  
         Bipartisan Party                                  1  
         Moderate Party                                    1  
         Overvotes                                         1  
         Undervotes                                       10  
         Counted ballots                                  13  
         Balance                                           0  
 
         President, vote for at most 1  
         Car Tay Fower                                     4