View Javadoc
1   package civitas.bboard.server.controllers.tests;
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  import org.mockito.Mock;
16  
17  import civitas.bboard.server.BoardRepository;
18  import civitas.bboard.server.GetBoardForId;
19  import civitas.bboard.server.controllers.CloseBoardController;
20  import civitas.bboard.server.controllers.CommunicableException;
21  import civitas.common.board.BoardClosedContentCommitment;
22  import civitas.common.board.tests.BoardClosedContentCommitmentTestData;
23  import civitas.common.tests.EnvironmentState;
24  import civitas.common.tests.RandomAwareTestBase;
25  import civitas.crypto.messagedigest.CryptoHash;
26  import civitas.crypto.rsapublickey.VerifyPublicKeySignature;
27  import civitas.crypto.signature.tests.SignatureTestData;
28  
29  class CloseBoardControllerTest extends RandomAwareTestBase
30  		implements BoardClosedContentCommitmentTestData, SignatureTestData {
31  
32  	@InjectMocks
33  	CloseBoardController closeBoardController;
34  
35  	@Mock
36  	GetBoardForId getBoardForId;
37  
38  	@Mock
39  	VerifyPublicKeySignature verifyPublicKeySignature;
40  
41  	@Mock
42  	BoardRepository boardRepository;
43  
44  	@Mock
45  	CryptoHash cryptoHash;
46  
47  	@Test
48  	@DisplayName(
49  			"""
50  			closes the board
51  			- verifies the signature based on the owner key stored for the bulletin board
52  			- marks the board closed
53  			- calculates the BoardClosedContentCommitment for all voter block
54  			- posts the BoardClosedContentCommitment for the election master
55  			""")
56  	void test() throws CommunicableException, CryptoException {
57  		closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, NUM_VOTER_BLOCKS, SIGNATURE_OF_AUTH_NONCE_WITH_KEY);
58  		verify(getBoardForId).apply(BULLETIN_BOARD_ID, true);
59  		verify(verifyPublicKeySignature).apply(SIGNATURE_OF_AUTH_NONCE_WITH_KEY, PUBLIC_KEY, BULLETIN_BOARD_ID);
60  		verify(boardRepository).save(BULLETIN_BOARD);
61  		verify(cryptoHash).apply(BULLETIN_BOARD_ID.getBytes(), "voterSubmission-voterBlock0".getBytes());
62  		verify(cryptoHash).apply(BULLETIN_BOARD_ID.getBytes(), "voterSubmission-voterBlock1".getBytes());
63  		verify(GetRestTemplateStub.restTemplate)
64  				.postForObject(ELECTION_ID.uriBase() + "/post", BOARD_CLOSED_CONTENT_COMMITMENT, Boolean.class);
65  	}
66  
67  	@Test
68  	@DisplayName("if the signature does not verify, does nothing")
69  	void test2() throws CommunicableException {
70  		closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, NUM_VOTER_BLOCKS, SIGNATURE_OF_AUTH_NONCE_WITH_KEY2);
71  		verify(boardRepository, times(0)).save(BULLETIN_BOARD);
72  		verifyNoInteractions(cryptoHash);
73  		verifyNoInteractions(GetRestTemplateStub.restTemplate);
74  	}
75  
76  	@Test
77  	@DisplayName("if the election is null, a NullPointerException is thrown")
78  	void test3() {
79  		assertThrows(
80  				NullPointerException.class,
81  				() -> closeBoardController.apply(
82  						BULLETIN_BOARD_ID, null, NUM_VOTER_BLOCKS, SIGNATURE_OF_AUTH_NONCE_WITH_KEY));
83  	}
84  
85  	@Test
86  	@DisplayName("if the signature is null, a NullPointerException is thrown")
87  	void test4() {
88  		assertThrows(
89  				NullPointerException.class,
90  				() -> closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, NUM_VOTER_BLOCKS, null));
91  	}
92  
93  	@Test
94  	@DisplayName("if the number of voter blocks is negative, an IllegalArgumentException is thrown")
95  	void test5() {
96  		assertThrows(
97  				IllegalArgumentException.class,
98  				() -> closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, -1, SIGNATURE_OF_AUTH_NONCE_WITH_KEY));
99  	}
100 
101 	@Test
102 	@DisplayName("if the number of voter blocks is zero, the BoardClosedContentCommitment posted has empty hashes")
103 	void test6() throws CommunicableException {
104 		closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, 0, SIGNATURE_OF_AUTH_NONCE_WITH_KEY);
105 		verify(GetRestTemplateStub.restTemplate)
106 				.postForObject(
107 						ELECTION_ID.uriBase() + "/post",
108 						new BoardClosedContentCommitment(ELECTION_ID, BULLETIN_BOARD_ID, new ArrayList<>()),
109 						Boolean.class);
110 	}
111 
112 	@Test
113 	@DisplayName("if the election server is unreachable, an IOException is thrown and the board is not closed")
114 	void test7() {
115 		given(EnvironmentState.ELECTION_SERVER_IS_UNREACHEABLE);
116 		assertThrows(
117 				IOException.class,
118 				() -> closeBoardController.apply(BULLETIN_BOARD_ID, ELECTION_ID, 0, SIGNATURE_OF_AUTH_NONCE_WITH_KEY));
119 		verify(boardRepository, times(0)).save(BULLETIN_BOARD);
120 	}
121 }