meerkat-java/voter-registry/src/test/java/SimpleRegistryTest.java

385 lines
14 KiB
Java

import com.google.common.util.concurrent.FutureCallback;
import meerkat.AsyncRegistry;
import meerkat.bulletinboard.AsyncBulletinBoardClient;
import meerkat.bulletinboard.ThreadedBulletinBoardClient;
import meerkat.crypto.DigitalSignature;
import meerkat.crypto.concrete.ECDSASignature;
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
import meerkat.protobuf.BulletinBoardAPI.MessageFilterList;
import meerkat.protobuf.VoterRegistry;
import meerkat.protobuf.VoterRegistry.GroupID;
import meerkat.protobuf.VoterRegistry.VoterID;
import meerkat.protobuf.VoterRegistry.VoterInfo;
import meerkat.protobuf.Voting;
import meerkat.registry.MessageCollectionUtils;
import meerkat.registry.RegistryTags;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Semaphore;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static meerkat.util.BulletinBoardUtils.findTagWithPrefix;
import static meerkat.util.BulletinBoardUtils.getLatestMessage;
/**
* TODO: add logs prints for the tests to be clear what they are
*/
/**
* Created by Vladimir Eliezer Tokarev on 1/16/2016.
* Tests the Simple registry contents
* NOTE: for most of this tests to pass there should run BulletinBoardServer
* that should be reachable on BULLETIN_BOARD_SERVER_ADDRESS
*/
public class SimpleRegistryTest {
private Collection<DigitalSignature> signers;
private AsyncBulletinBoardClient bulletinBoardClient;
private InputStream certStream;
private SecureRandom random = new SecureRandom();
public static String KEYFILE_EXAMPLE = "/certs/enduser-certs/user1-key-with-password-secret.p12";
public static String CERT1_PEM_EXAMPLE = "/certs/enduser-certs/user1.crt";
public static String KEYFILE_PASSWORD = "secret";
Semaphore jobSemaphore;
class DummyRegistryCallBackHandler<T> implements FutureCallback<T>{
public int counter;
public T data;
public DummyRegistryCallBackHandler()
{
counter=0;
}
@Override
public void onSuccess(T result) {
counter++;
data = result;
jobSemaphore.release();
}
@Override
public void onFailure(Throwable throwable) {
System.out.print(throwable);
}
}
public class DummyBulletinBoardCallBackHandler implements FutureCallback<List<BulletinBoardMessage>> {
public List<BulletinBoardMessage> messages;
@Override
public void onSuccess(List<BulletinBoardMessage> msg)
{
messages = msg;
jobSemaphore.release();
}
@Override
public void onFailure(Throwable t){
messages = null;
jobSemaphore.release();
}
}
private void CommunicatorSetup() {
bulletinBoardClient = new ThreadedBulletinBoardClient();
String BULLETIN_BOARD_SERVER_ADDRESS = "http://localhost:8081/";
bulletinBoardClient.init(Voting.BulletinBoardClientParams.newBuilder()
.addBulletinBoardAddress(BULLETIN_BOARD_SERVER_ADDRESS)
.setMinRedundancy((float) 1.0)
.build());
}
private void SetSigner(){
try {
signers = new ArrayList<>();
ECDSASignature signer = new ECDSASignature();
InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE);
char[] password = KEYFILE_PASSWORD.toCharArray();
KeyStore.Builder keyStore = signer.getPKCS12KeyStoreBuilder(keyStream, password);
signer.loadSigningCertificate(keyStore);
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
keyStream.close();
signers.add(signer);
}
catch (Exception e){
assert false : "The signers creation failed ";
}
}
/**
* Initialize registry object
*/
@Before
public void setUp() {
SetSigner();
CommunicatorSetup();
jobSemaphore = new Semaphore(0);
}
private AsyncRegistry GetRegistry()
{
AsyncRegistry registry = new AsyncRegistry();
registry.init(signers, bulletinBoardClient);
return registry;
}
private String generateString()
{
return new BigInteger(130, random).toString(32);
}
/**
* Checks if the creation of the registry have been successful
*/
@Test
public void simpleRegistryCreation() {
try {
AsyncRegistry registry = GetRegistry();
} catch (Exception e) {
assert false : "While creating the registry exception have been thrown " + e;
}
}
/**
* Counts the amount of messages from messages that have all the wanted tags inside
* @param messages List<VoterRegistryMessage>
* @param tags List<RegistryTags>
* @return integer that represent the amount of messages with wanted tags
*/
private int countMessagesWithTags(List<BulletinBoardMessage> messages, List<String> tags)
{
int counter = 0 ;
for (BulletinBoardMessage message : messages) {
int wantedTagsCounter = 0;
for (String tag : tags) {
if(findTagWithPrefix(message, tag)!=null){
wantedTagsCounter++;
}
}
if(wantedTagsCounter == tags.size())
{
counter++;
}
}
return counter;
}
/**
* Reads messages from bulletinBoardClient by given tags and return the callback handler
* object
*
* @param tags list of strings that represents tags
* @return DummyBulletinBoardCallBackHandler which method will be called
*/
private DummyBulletinBoardCallBackHandler readMessagesByTags(List<String> tags)
{
MessageFilterList filters = MessageCollectionUtils.generateFiltersFromTags(tags);
DummyBulletinBoardCallBackHandler bulletinHandler = new DummyBulletinBoardCallBackHandler();
bulletinBoardClient.readMessages(filters, bulletinHandler);
return bulletinHandler;
}
/**
* Test that add voter creates new correct bulletin board message and adds the voter
*/
@Test
public void testAddVoter() throws InterruptedException, SignatureException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String id = generateString();
String data = generateString();
VoterInfo voterInfo = VoterInfo.newBuilder().setId(VoterID.newBuilder().setId(id)).setInfo(data).build();
AsyncRegistry registry = GetRegistry();
registry.addVoter(voterInfo, handler);
jobSemaphore.acquire();
assertEquals(1, handler.counter );
List<String> tags = new ArrayList<String>(){{ add(RegistryTags.VOTER_ENTRY_TAG);}};
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
jobSemaphore.acquire();
tags.clear();
tags.add(RegistryTags.ID_TAG + id);
int counter = countMessagesWithTags(bulletinHandler.messages, tags);
assert counter == 1 : "The server don't have the new user data.";
}
/**
* Test that set voted posts creates correct bulletin board message and sets that the user have been voted
*/
@Test
public void testSetVoted() throws InterruptedException, SignatureException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String id = generateString();
VoterID voterInfo = VoterID.newBuilder().setId(id).build();
AsyncRegistry registry = GetRegistry();
registry.setVoted(voterInfo, handler);
jobSemaphore.acquire();
assertEquals(1, handler.counter );
List<String> tags = new ArrayList<String>(){{ add(RegistryTags.VOTE_ACTION_TAG);}};
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
jobSemaphore.acquire();
tags.clear();
tags.add(RegistryTags.ID_TAG + id);
int counter = countMessagesWithTags(bulletinHandler.messages, tags);
assert counter == 1 : "The server don't have the new user id.";
}
/**
* Test that get groups retrieves the right groups the user are in
*/
@Test
public void testSetVoterGroups() throws InterruptedException, SignatureException, IOException, ClassNotFoundException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String voterId = generateString();
String groupId1 = generateString();
VoterRegistry.VoterRegistryMessage voterInfo = VoterRegistry.VoterRegistryMessage.newBuilder()
.setVoterID(VoterID.newBuilder().setId(voterId))
.addGroupID(GroupID.newBuilder().setId(groupId1)).build();
AsyncRegistry registry = GetRegistry();
registry.setVoterGroups(voterInfo, handler);
jobSemaphore.acquire();
assertEquals("The callback handler hasn't been called yet", 1, handler.counter);
List<String> tags = new ArrayList<String>(){{add(RegistryTags.ADD_TO_GROUP_TAG);
add(RegistryTags.ID_TAG + voterId);}};
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
jobSemaphore.acquire();
BulletinBoardMessage latestMessage = getLatestMessage(bulletinHandler.messages);
assert findTagWithPrefix(latestMessage, RegistryTags.ID_TAG).equals(voterId) :
"The latest message recieved is not of our voter";
VoterRegistry.VoterRegistryMessage voterRegistryMessage =
VoterRegistry.VoterRegistryMessage.parseFrom(latestMessage.getMsg().getData());
List<GroupID> groupsIds = voterRegistryMessage.getGroupIDList();
assert groupsIds.get(0).getId().equals(groupId1) : "The latest message doesn't have the voter group";
}
/**
* Test that remove from group creates correct bulletin board message and removes the user from a group
*/
@Test
public void testGetGroups() throws InterruptedException, SignatureException, IOException {
DummyRegistryCallBackHandler<Boolean> handler =
new DummyRegistryCallBackHandler<>();
String voterId = generateString();
String groupId1 = generateString();
String groupId2 = generateString();
VoterRegistry.VoterRegistryMessage voterInfo = VoterRegistry.VoterRegistryMessage.newBuilder()
.setVoterID(VoterID.newBuilder().setId(voterId))
.addGroupID(GroupID.newBuilder().setId(groupId1))
.addGroupID(GroupID.newBuilder().setId(groupId2)).build();
this.certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE);
AsyncRegistry registry = GetRegistry();
registry.setVoterGroups(voterInfo, handler);
jobSemaphore.acquire();
assertEquals("The callback handler hasn't been called yet", 1, handler.counter );
DummyRegistryCallBackHandler<List<GroupID>> groupsHandler = new DummyRegistryCallBackHandler<>();
registry.getGroups(VoterID.newBuilder().setId(voterId).build(), groupsHandler);
jobSemaphore.acquire(1);
List<GroupID> userGroups = groupsHandler.data;
assert userGroups.contains(GroupID.newBuilder().setId(groupId1).build()) :
"The simple voter registry object does not retrieved the first user groups";
assert userGroups.contains(GroupID.newBuilder().setId(groupId2).build()) :
"The simple voter registry object does not retrieved the second user groups";
}
/**
* Test that the personal data outputted about the user is right
*/
@Test
public void testGetVoter() throws InterruptedException, SignatureException {
DummyRegistryCallBackHandler<Boolean> handler =
new DummyRegistryCallBackHandler<>();
String id = generateString();
String data = generateString();
VoterInfo voterInfo = VoterInfo.newBuilder().
setId(VoterID.newBuilder().setId(id)).setInfo(data).build();
AsyncRegistry registry = GetRegistry();
registry.addVoter(voterInfo, handler);
jobSemaphore.acquire();
assertEquals("The callback handler hasn't been called yet", 1, handler.counter );
DummyRegistryCallBackHandler<VoterInfo> personalHandler = new DummyRegistryCallBackHandler<>();
registry.getVoter(VoterID.newBuilder().setId(id).build(), personalHandler);
jobSemaphore.acquire(1);
assertEquals("The voter id doesn't match the created on ",
id, personalHandler.data.getId().getId());
String personalData = personalHandler.data.getInfo();
assertTrue("The voter personal data can't be found.", data.equals(personalData));
}
/**
* Tests that the hasVoted method of registry works
* @throws InterruptedException
*/
@Test
public void testHasVoted () throws InterruptedException, SignatureException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String id = generateString();
VoterID voterInfo = VoterID.newBuilder().setId(id).build();
AsyncRegistry registry = GetRegistry();
registry.setVoted(voterInfo, handler);
jobSemaphore.acquire();
assertEquals("The callback handler hasn't been called yet", 1, handler.counter);
DummyRegistryCallBackHandler<Boolean> personalHandler = new DummyRegistryCallBackHandler<>();
registry.hasVoted(VoterID.newBuilder().setId(id).build(), personalHandler);
jobSemaphore.acquire(1);
assertTrue("The voter hasn't voted yet.", personalHandler.data);
}
}