View Javadoc
1   package civitas.common.ballotdesign;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertThrows;
5   import static org.mockito.Mockito.verify;
6   
7   import org.junit.jupiter.api.DisplayName;
8   import org.junit.jupiter.api.Test;
9   import org.mockito.InjectMocks;
10  
11  import civitas.common.RandomAwareTestBase;
12  import civitas.common.votersubmission.VoterSubmission;
13  import civitas.common.votersubmission.VoterSubmissionTestData;
14  import civitas.crypto.oneoflreencryption.ElGamal1OfLReencryptionTestData;
15  
16  class DecomposeBallotTest extends RandomAwareTestBase
17  		implements VoterSubmissionTestData, ElGamal1OfLReencryptionTestData {
18  
19  	@InjectMocks
20  	DecomposeBallot decomposeBallot;
21  
22  	@Test
23  	@DisplayName(
24  			"""
25  			Decomposes a ballot into a VoterSubmission
26  			- calculates the length of the ballot based on the number of candidates
27  			- for each pair i,j:
28  			- calculates their position in the matrix
29  			- computes the encrypted choice by constructing an 1 of L reeencryption
30  			- encrypts the capability from the map
31  			- constructs a vote proof using all the above
32  			- creates a verifiable vote using the context, the encryted capability and choice and the proof
33  			- returns a voter submission for the voter block with the verifiable votes
34  			""")
35  	void test() {
36  		VoterSubmission actual = decomposeBallot.apply(
37  				BALLOTDESIGN,
38  				BALLOT,
39  				VOTER_BLOCK,
40  				EL_GAMAL_PUBLIC_KEY_E,
41  				CIPHERTEXT_LIST,
42  				ADDITIONALENV,
43  				CAPABILITY_MAP);
44  		assertEquals(VOTER_SUBMISSION, actual);
45  		verify(decomposeBallot.calculateBallotLength).apply(BALLOT.k);
46  		CalculatePositionInBallot posStub = CalculatePositionInBallotStub.stub();
47  		for (int i = 0; i < NUM_CANDIDATES; i++) {
48  			for (int j = i + 1; j < NUM_CANDIDATES; j++) {
49  				Integer pos = posStub.apply(i, j, NUM_CANDIDATES);
50  				verify(decomposeBallot.encryptCapability).apply(EL_GAMAL_PUBLIC_KEY_E, CAPABILITY_MAP, CONTEXT_0);
51  				verify(decomposeBallot.encryptChoice).apply(EL_GAMAL_PUBLIC_KEY_E, CIPHERTEXT_LIST, BALLOT.matrix, pos);
52  				verify(decomposeBallot.calculatePositionInBallot).apply(i, j, NUM_CANDIDATES);
53  
54  				verify(decomposeBallot.constructProofVote)
55  						.apply(
56  								EL_GAMAL_PARAMETERS,
57  								ENCRYPTED_SIGNED_VOTE_CAPABILITIES.get(pos),
58  								EL_GAMAL_1_OF_L_REENCRYPTION_MAP
59  										.get(BALLOT.matrix[pos])
60  										.m(),
61  								CONTEXT_MAP.get(pos),
62  								ELGAMAL_REENCRYPT_FACTOR_E,
63  								ELGAMAL_REENCRYPT_FACTOR_EPRIME);
64  			}
65  		}
66  	}
67  
68  	@Test
69  	@DisplayName("if the key is null, IllegalArgumentException is thrown")
70  	void test1() {
71  		assertThrows(
72  				IllegalArgumentException.class,
73  				() -> decomposeBallot.apply(
74  						BALLOTDESIGN, BALLOT, VOTER_BLOCK, null, CIPHERTEXT_LIST, ADDITIONALENV, CAPABILITY_MAP));
75  	}
76  
77  	@Test
78  	@DisplayName("if the number of candidates in the ballot does not match the number of candidates,"
79  			+ "IllegalArgumentException is thrown")
80  	void test2() {
81  		assertThrows(
82  				IllegalArgumentException.class,
83  				() -> decomposeBallot.apply(
84  						BALLOTDESIGN,
85  						BALLOT_2_CANDIDATES,
86  						VOTER_BLOCK,
87  						EL_GAMAL_PUBLIC_KEY_E,
88  						CIPHERTEXT_LIST,
89  						ADDITIONALENV,
90  						CAPABILITY_MAP));
91  	}
92  
93  	@Test
94  	@DisplayName("if the matrix length in the ballot does not match the number of candidates,"
95  			+ "IllegalArgumentException is thrown")
96  	void test3() {
97  		assertThrows(
98  				IllegalArgumentException.class,
99  				() -> decomposeBallot.apply(
100 						BALLOTDESIGN,
101 						BALLOT_SHORT_MATRIX,
102 						VOTER_BLOCK,
103 						EL_GAMAL_PUBLIC_KEY_E,
104 						CIPHERTEXT_LIST,
105 						ADDITIONALENV,
106 						CAPABILITY_MAP));
107 	}
108 }