1 package civitas.bboard.server.controllers;
2
3 import static org.junit.jupiter.api.Assertions.assertThrows;
4 import static org.mockito.Mockito.times;
5 import static org.mockito.Mockito.verify;
6 import static org.mockito.Mockito.verifyNoInteractions;
7
8 import java.io.IOException;
9 import java.util.ArrayList;
10
11 import org.bouncycastle.crypto.CryptoException;
12 import org.junit.jupiter.api.DisplayName;
13 import org.junit.jupiter.api.Test;
14 import org.mockito.InjectMocks;
15
16 import civitas.common.EnvironmentState;
17 import civitas.common.RandomAwareTestBase;
18 import civitas.common.board.BoardClosedContentCommitment;
19 import civitas.common.board.BoardClosedContentCommitmentTestData;
20 import civitas.crypto.signature.SignatureTestData;
21
22 class CloseBoardControllerTest extends RandomAwareTestBase
23 implements BoardClosedContentCommitmentTestData, SignatureTestData {
24
25 @InjectMocks
26 CloseBoardController closeBoardController;
27
28 @Test
29 @DisplayName(
30 """
31 closes the board
32 - verifies the signature based on the owner key stored for the bulletin board
33 - marks the board closed
34 - calculates the BoardClosedContentCommitment for all voter block
35 - posts the BoardClosedContentCommitment for the election master
36 """)
37 void test() throws CommunicableException, CryptoException {
38 closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, NUM_VOTER_BLOCKS, SIGNATURE_OF_AUTH_NONCE_WITH_KEY);
39 verify(closeBoardController.getBoardForId).apply(BULLETIN_BOARD_ID, true);
40 verify(closeBoardController.verifyPublicKeySignature)
41 .apply(SIGNATURE_OF_AUTH_NONCE_WITH_KEY, PUBLIC_KEY, BULLETIN_BOARD_ID);
42 verify(closeBoardController.boardRepository).save(BULLETIN_BOARD);
43 verify(closeBoardController.cryptoHash)
44 .apply(BULLETIN_BOARD_ID.getBytes(), "voterSubmission-voterBlock0".getBytes());
45 verify(closeBoardController.cryptoHash)
46 .apply(BULLETIN_BOARD_ID.getBytes(), "voterSubmission-voterBlock1".getBytes());
47 verify(closeBoardController.getRestTemplate.restTemplate)
48 .postForObject(ELECTION_ID.uriBase() + "/post", BOARD_CLOSED_CONTENT_COMMITMENT, Boolean.class);
49 }
50
51 @Test
52 @DisplayName("if the signature does not verify, does nothing")
53 void test2() throws CommunicableException {
54 closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, NUM_VOTER_BLOCKS, SIGNATURE_OF_AUTH_NONCE_WITH_KEY2);
55 verify(closeBoardController.boardRepository, times(0)).save(BULLETIN_BOARD);
56 verifyNoInteractions(closeBoardController.cryptoHash);
57 verifyNoInteractions(closeBoardController.getRestTemplate.restTemplate);
58 }
59
60 @Test
61 @DisplayName("if the election is null, a NullPointerException is thrown")
62 void test3() {
63 assertThrows(
64 NullPointerException.class,
65 () -> closeBoardController.apply(
66 BULLETIN_BOARD_ID, null, NUM_VOTER_BLOCKS, SIGNATURE_OF_AUTH_NONCE_WITH_KEY));
67 }
68
69 @Test
70 @DisplayName("if the signature is null, a NullPointerException is thrown")
71 void test4() {
72 assertThrows(
73 NullPointerException.class,
74 () -> closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, NUM_VOTER_BLOCKS, null));
75 }
76
77 @Test
78 @DisplayName("if the number of voter blocks is negative, an IllegalArgumentException is thrown")
79 void test5() {
80 assertThrows(
81 IllegalArgumentException.class,
82 () -> closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, -1, SIGNATURE_OF_AUTH_NONCE_WITH_KEY));
83 }
84
85 @Test
86 @DisplayName("if the number of voter blocks is zero, the BoardClosedContentCommitment posted has empty hashes")
87 void test6() throws CommunicableException {
88 closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, 0, SIGNATURE_OF_AUTH_NONCE_WITH_KEY);
89 verify(closeBoardController.getRestTemplate.restTemplate)
90 .postForObject(
91 ELECTION_ID.uriBase() + "/post",
92 new BoardClosedContentCommitment(ELECTION_ID, BULLETIN_BOARD_ID, new ArrayList<>()),
93 Boolean.class);
94 }
95
96 @Test
97 @DisplayName("if the election server is unreachable, an IOException is thrown and the board is not closed")
98 void test7() {
99 given(EnvironmentState.ELECTION_SERVER_IS_UNREACHEABLE);
100 assertThrows(
101 IOException.class,
102 () -> closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, 0, SIGNATURE_OF_AUTH_NONCE_WITH_KEY));
103 verify(closeBoardController.boardRepository, times(0)).save(BULLETIN_BOARD);
104 }
105 }