import com.google.protobuf.InvalidProtocolBufferException; import junit.framework.TestCase; import meerkat.SimpleRegistry; import meerkat.VoterRegistryMessage; import meerkat.bulletinboard.SimpleBulletinBoardClient; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.concrete.ECElGamalUtils; import meerkat.protobuf.BulletinBoardAPI; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Voting; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; import util.RegistryTags; import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; import java.util.List; import static util.CollectionMessagesUtils.ConvertToVoterRegistryMessages; import static util.CollectionMessagesUtils.GetUnsignedBulletinBoardMessages; /** * 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 ECElGamalEncryption signatory; private SimpleBulletinBoardClient communicator; private static String BULLETIN_BOARD_SERVER_ADDRESS = "http://localhost:8081"; private SecureRandom random = new SecureRandom(); private List> votersData; /** * Creates the ElGamal encryption object */ private void ElGamalSetup() { try { ECGroup group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, random); ECElGamal.SK key = new ECElGamal.SK(group, sk); ConcreteCrypto.ElGamalPublicKey serializedPk = ECElGamalUtils.serializePk(group, key); signatory = new ECElGamalEncryption(); signatory.init(serializedPk); } catch (InvalidKeySpecException e) { assertTrue(false); } } /** * Creates the communication object (the bulletinBoardClient) */ private void CommunicatorSetup() { communicator = new SimpleBulletinBoardClient(); communicator.init(Voting.BulletinBoardClientParams.newBuilder() .addBulletinBoardAddress(BULLETIN_BOARD_SERVER_ADDRESS) .setMinRedundancy((float) 1.0) .build()); } private SimpleRegistryCallBackHandlers RegistryAnswersHandlerSetup() { return new SimpleRegistryCallBackHandlers(); } /** * Initialize SimpleRegistry object */ public void setUp() { ElGamalSetup(); CommunicatorSetup(); votersData = null; } /** * Checks if the creation of the registry have been successful */ public void testSimpleRegistryCreation() { try { new SimpleRegistry(signatory, communicator); } catch (Exception e) { assert false : "While creating the SimpleRegistry exception have been thrown " + e; } } /** * Creates list of lists of strings for different testing purposes * @param actionDataNumber number of string in a list * @param numberOfInstances number of lists in a list * @return */ private void setActionsData(int actionDataNumber, int numberOfInstances) { System.out.println("- Creating "+ numberOfInstances +" ids and personal data strings for adding different voters."); if (votersData != null){ return; } votersData = new ArrayList<>(); for (int i = 0 ; i < numberOfInstances ; i++ ){ List data = new ArrayList<>(); for (int j = 0 ; j < actionDataNumber ; j++){ data.add(new BigInteger(130, random).toString(32)); } votersData.add(data); } } /** * Counts the amount of posted messaages that have their tags in voterData * @param votersData List> of information about voters (tags etc...) * @param tags List of tags * @return int * @throws InvalidProtocolBufferException */ private int countActualAddedMessages(List> votersData, List tags, SimpleRegistry registry) throws InvalidProtocolBufferException { System.out.println("- Check that the server have the new voters data:"); BulletinBoardAPI.MessageFilterList filters = registry.GetRelevantMessagesFilters(tags); List messages = ConvertToVoterRegistryMessages(GetUnsignedBulletinBoardMessages(communicator.readMessages(filters))); assert messages.size() > 0 : " The filtered messages are empty ( wrong filtering or server down)"; int addedMessagesCounter = 0; for (List voterData : votersData) { for (VoterRegistryMessage message : messages) { String addedVoterId = message.GetWantedTagFromBasicMessage(RegistryTags.ID_TAG); String addedVoterData = new String(message.base.getData().toByteArray()); if (voterData.size() == 2 && addedVoterId.contains(voterData.get(0)) && addedVoterData.contains(voterData.get(1))) { addedMessagesCounter++; } else if (addedVoterId.contains(voterData.get(0)) ){ addedMessagesCounter++; } } } return addedMessagesCounter; } /** * Call methodToCheck voterData as list of params * @param methodToCheck the name of the wanted method * @param numberOfParamsWithoutHandler the amount of params to pass to the wanted method * @param handler object which method will be called as callback from SimpleRegistry * @param registry the simpleRegistry object * @param voterData List of string which is the params to pass to the wantedMethod */ private void CallWantedMethod(String methodToCheck, int numberOfParamsWithoutHandler, SimpleRegistryCallBackHandlers handler, SimpleRegistry registry, List voterData) { try { if (numberOfParamsWithoutHandler == 1) { java.lang.reflect.Method method = registry.getClass().getMethod(methodToCheck,String.class, RegistryCallBack.class); method.invoke(registry, voterData.get(0), handler); assertTrue(handler.ActionSucceed); }else { java.lang.reflect.Method method = registry.getClass().getMethod( methodToCheck, String.class, String.class, RegistryCallBack.class); method.invoke(registry, voterData.get(0), voterData.get(1), handler); assertTrue(handler.ActionSucceed); } } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } } /** * Creates new Registry information then sends it to the server then checks the server * have all sent data * @param methodToCheck the name of the method we want to call in SimpleRegistry * @param numberOfParamsToPass the number of params to pass to the methodToCheck * @param numberOfChecks the amount of checks to run * @param tags list of String that represent the tags to filter on the messages * @return Returns the information that was send in the created messages * @throws InvalidProtocolBufferException */ private List> checkMessagesPostedSuccessfully(String methodToCheck, int numberOfParamsToPass, int numberOfChecks, List tags) throws InvalidProtocolBufferException { SimpleRegistryCallBackHandlers handler = RegistryAnswersHandlerSetup(); System.out.println("Starting testing the " + methodToCheck + " capability."); setActionsData(numberOfParamsToPass, numberOfChecks); SimpleRegistry registry = new SimpleRegistry(signatory, communicator); System.out.println("- Check that all the callbacks have been called successfully after voters adding:"); for (List voterData : votersData) { CallWantedMethod(methodToCheck, numberOfParamsToPass, handler, registry, voterData); } System.out.println("- Check that for every data added, the callback have been called:"); assertEquals(numberOfChecks, handler.counter); int addedMessagesCounter = countActualAddedMessages(votersData, tags, registry); assert addedMessagesCounter == numberOfChecks : "The number of added messages actually is " + addedMessagesCounter; System.out.println("Ended addVoter testing."); return votersData; } /** * Test that add voter creates new correct bulletin board message and adds the voter */ public void testAddVoter() throws InvalidProtocolBufferException { checkMessagesPostedSuccessfully("AddVoter", 2, 3, new ArrayList(){{add(RegistryTags.VOTER_ENTRY_TAG.toString());}}); } /** * Test that set voted posts creates correct bulletin board message and sets that the user have been voted */ public void testSetVoted() throws InvalidProtocolBufferException { checkMessagesPostedSuccessfully("SetVoted", 1, 3, new ArrayList(){{add(RegistryTags.VOTE_ACTION_TAG.toString());}}); } /** * Test that add to group creates correct bulletin board message and adds a user to a group */ public void testRemoveFromGroup() throws InvalidProtocolBufferException { checkMessagesPostedSuccessfully("RemoveFromGroup", 2, 3, null); } /** * Test that get groups retrieves the right groups the user are in */ public void testAddToGroup() throws InvalidProtocolBufferException { checkMessagesPostedSuccessfully("AddToGroup", 2, 4, null); } /** * Test that remove from group creates correct bulletin board message and removes the user from a group */ public void testGetGroups() throws InvalidProtocolBufferException, InterruptedException { System.out.println("Starting testing the GetGroups capability."); List> votersData = checkMessagesPostedSuccessfully("AddToGroup", 2, 3, null); SimpleRegistry registry = new SimpleRegistry(signatory, communicator); SimpleRegistryCallBackHandlers handler = RegistryAnswersHandlerSetup(); System.out.println("- Checks that every group id we added to every voter really exists:"); for (List voterData : votersData){ registry.GetGroups(voterData.get(1), handler); assert handler.ActionSucceed : " The SimpleRegistry could not complete the GetGroups action "; assert handler.WantedInformation.contains(RegistryTags.GROUP_ID_TAG + voterData.get(1)) : " The SimpleRegistry cloud not get the right group of the user " + voterData.get(1); } System.out.println("Ended GetGroups testing."); } /** * Test that the personal data outputted about the user is right */ public void testGetPersonalIDDetails() throws InvalidProtocolBufferException, InterruptedException { System.out.println("Starting testing the GetPersonIDDetails capability:"); List> addedVotersInformation = checkMessagesPostedSuccessfully("AddVoter", 2, 3, new ArrayList(){{add(RegistryTags.VOTER_ENTRY_TAG.toString());}}); SimpleRegistry registry = new SimpleRegistry(signatory, communicator); SimpleRegistryCallBackHandlers handler = RegistryAnswersHandlerSetup(); System.out.println("- Check that every added voter can be retrieved by SimpleRegistry:"); for (List voterInformation : addedVotersInformation) { registry.GetPersonIDDetails(voterInformation.get(0), handler); assert handler.ActionSucceed : " Getting personal data for voter with id : " + voterInformation.get(0) + " failed"; assert handler.WantedInformation.get(0).contains(voterInformation.get(0)) : " Voter with id " + voterInformation.get(0) + " have bot been added to the voter db."; } assert handler.counter == 3 : " The callback method have not been called 3 times"; System.out.println("Ended the GetPersonIDDetails capability"); } }