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.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; /** * 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 /**extends TestCase**/ { private Collection 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 implements FutureCallback{ 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> { public List messages; @Override public void onSuccess(List 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 * @param tags List * @return integer that represent the amount of messages with wanted tags */ private int countMessagesWithTags(List messages, List 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 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 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 tags = new ArrayList(){{ 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 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 tags = new ArrayList(){{ 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 testAddToGroup() throws InterruptedException, SignatureException { DummyRegistryCallBackHandler handler = new DummyRegistryCallBackHandler<>(); String voterId = generateString(); String groupId = generateString(); VoterRegistry.VoterRegistryMessage voterInfo = VoterRegistry.VoterRegistryMessage.newBuilder() .setVoterID(VoterID.newBuilder().setId(voterId)) .addGroupID(GroupID.newBuilder().setId(groupId)).build(); AsyncRegistry registry = GetRegistry(); registry.setVoterGroups(voterInfo, handler); jobSemaphore.acquire(); assertEquals("The callback handler hasn't been called yet", 1, handler.counter); List tags = new ArrayList(){{add(RegistryTags.ADD_TO_GROUP_TAG);}}; DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags); jobSemaphore.acquire(); tags.clear(); tags.add(RegistryTags.ID_TAG + voterId); tags.add(RegistryTags.GROUP_ID_TAG + groupId); int counter = countMessagesWithTags(bulletinHandler.messages, tags); assert counter == 1 : "The server don't have the new user added to 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 { DummyRegistryCallBackHandler handler = new DummyRegistryCallBackHandler<>(); String voterId = generateString(); String groupId = generateString(); VoterRegistry.VoterRegistryMessage voterInfo = VoterRegistry.VoterRegistryMessage.newBuilder() .setVoterID(VoterID.newBuilder().setId(voterId)) .addGroupID(GroupID.newBuilder().setId(groupId)).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> groupsHandler = new DummyRegistryCallBackHandler<>(); registry.getGroups(VoterID.newBuilder().setId(groupId).build(), groupsHandler); jobSemaphore.acquire(1); List userGroups = groupsHandler.data; assert userGroups.contains(groupId) : "The simple voter registry object does not retrieved right user groups"; } /** * Test that the personal data outputted about the user is right */ @Test public void testGetVoter() throws InterruptedException, SignatureException { DummyRegistryCallBackHandler 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 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 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 personalHandler = new DummyRegistryCallBackHandler<>(); registry.hasVoted(VoterID.newBuilder().setId(id).build(), personalHandler); jobSemaphore.acquire(1); assertTrue("The voter hasn't voted yet.", personalHandler.data); } }