Compare commits
81 Commits
master
...
Voter-Regi
Author | SHA1 | Date |
---|---|---|
Vladimir Eliezer Tokarev | 7fc0af2b1f | |
Vladimir Eliezer Tokarev | 47f68acae4 | |
Vladimir Eliezer Tokarev | 630588ca5b | |
Vladimir Eliezer Tokarev | 53fc701444 | |
Vladimir Eliezer Tokarev | 14d6759803 | |
Vladimir Eliezer Tokarev | 25781f40f7 | |
Vladimir Eliezer Tokarev | 1bf5861808 | |
Vladimir Eliezer Tokarev | 01874f7d1c | |
Vladimir Eliezer Tokarev | 7f39badaf7 | |
Vladimir Eliezer Tokarev | 259b4c2ae5 | |
Vladimir Eliezer Tokarev | f3ec49acc7 | |
Vladimir Eliezer Tokarev | 5398d5adc3 | |
Vladimir Eliezer Tokarev | b8cc12dfc1 | |
Vladimir Eliezer Tokarev | 8140dcd516 | |
Vladimir Eliezer Tokarev | c767d8af58 | |
Vladimir Eliezer Tokarev | 37002a7f1e | |
Vladimir Eliezer Tokarev | b4661d0fed | |
Vladimir Eliezer Tokarev | a9d96e59b2 | |
Vladimir Eliezer Tokarev | 4fac4bbb8c | |
Vladimir Eliezer Tokarev | 6d807cdd4d | |
Vladimir Eliezer Tokarev | 4d72d6083e | |
Vladimir Eliezer Tokarev | da614c13ab | |
Vladimir Eliezer Tokarev | 4b31e87d07 | |
Vladimir Eliezer Tokarev | 2d72822405 | |
Vladimir Eliezer Tokarev | 9828832553 | |
Vladimir Eliezer Tokarev | d9272c9f94 | |
Vladimir Eliezer Tokarev | 9c52eff109 | |
Vladimir Eliezer Tokarev | 6359f74a7b | |
Vladimir Eliezer Tokarev | fea0e8880f | |
Vladimir Eliezer Tokarev | 843d50c276 | |
Vladimir Eliezer Tokarev | 5c4b5a2150 | |
Vladimir Eliezer Tokarev | 687c2c6d7e | |
Vladimir Eliezer Tokarev | 311d1e8e8e | |
Vladimir Eliezer Tokarev | 87420a9d7d | |
Vladimir Eliezer Tokarev | 5169c935bf | |
Vladimir Eliezer Tokarev | 097aad4e7b | |
Vladimir Eliezer Tokarev | 64a9356dc2 | |
Vladimir Eliezer Tokarev | 230dfe6d3f | |
Vladimir Eliezer Tokarev | c8e747285c | |
Vladimir Eliezer Tokarev | 16a3102ca4 | |
Vladimir Eliezer Tokarev | 20d2b3e68c | |
Vladimir Eliezer Tokarev | 6ec0d4a668 | |
Vladimir Eliezer Tokarev | 3347a6c42d | |
Vladimir Eliezer Tokarev | 8c0e7f57bb | |
Vladimir Eliezer Tokarev | 64ccaff508 | |
Vladimir Eliezer Tokarev | 298dd5bf6e | |
Vladimir Eliezer Tokarev | bb4cc5b087 | |
Vladimir Eliezer Tokarev | 91e41af7a0 | |
Vladimir Eliezer Tokarev | 414452db84 | |
Vladimir Eliezer Tokarev | c4177cf487 | |
Vladimir Eliezer Tokarev | 003720839c | |
Vladimir Eliezer Tokarev | 6020ed3ab8 | |
Vladimir Eliezer Tokarev | 68caeee114 | |
Vladimir Eliezer Tokarev | c30ea072f2 | |
Vladimir Eliezer Tokarev | 7a167639db | |
Vladimir Eliezer Tokarev | 01604d1acb | |
Vladimir Eliezer Tokarev | 89bac8d346 | |
Vladimir Eliezer Tokarev | dfc5bf4b24 | |
Vladimir Eliezer Tokarev | 1815863746 | |
Vladimir Eliezer Tokarev | 0d8e522e93 | |
Vladimir Eliezer Tokarev | 4324bdeecd | |
Vladimir Eliezer Tokarev | d4d2d2f5b6 | |
Vladimir Eliezer Tokarev | e75317efa9 | |
Vladimir Eliezer Tokarev | 5971e8c16e | |
Vladimir Eliezer Tokarev | de835a8c13 | |
Vladimir Eliezer Tokarev | 109135ae1b | |
Vladimir Eliezer Tokarev | 7734ba8c91 | |
Vladimir Eliezer Tokarev | 8546a347ca | |
Vladimir Eliezer Tokarev | 65bc8bc160 | |
Vladimir Eliezer Tokarev | 36d94b41ab | |
Vladimir Eliezer Tokarev | 87e8ad9470 | |
Vladimir Eliezer Tokarev | 717c2e6e65 | |
Vladimir Eliezer Tokarev | 51b9f9decd | |
Vladimir Eliezer Tokarev | 05871a2ea7 | |
Vladimir Eliezer Tokarev | 070b851203 | |
Vladimir Eliezer Tokarev | 4aa6c25c0f | |
Vladimir Eliezer Tokarev | 84555f0639 | |
Vladimir Eliezer Tokarev | 42bc35cbe8 | |
Vladimir Eliezer Tokarev | f9d7b4b1ce | |
Vladimir Eliezer Tokarev | 25eefc4b16 | |
Arbel Deutsch Peled | a12685d757 |
|
@ -1,16 +1,20 @@
|
||||||
.gradle
|
/SQLiteDBTest.db
|
||||||
.idea
|
/Wombat Code And Documentation Conventions
|
||||||
build
|
/bulletin-board-server/trace.db/h2datasource.trace.db
|
||||||
bin
|
/bulletin-board-server/SQLiteDBTest.db
|
||||||
.settings
|
.gradle
|
||||||
.classpath
|
.idea
|
||||||
.project
|
build
|
||||||
out
|
bin
|
||||||
*.iml
|
.settings
|
||||||
*.ipr
|
.classpath
|
||||||
*.iws
|
.project
|
||||||
**/*.swp
|
out
|
||||||
*.prefs
|
*.iml
|
||||||
*.project
|
*.ipr
|
||||||
*.classpath
|
*.iws
|
||||||
bulletin-board-server/local-instances/meerkat.db
|
**/*.swp
|
||||||
|
*.prefs
|
||||||
|
*.project
|
||||||
|
*.classpath
|
||||||
|
bulletin-board-server/local-instances/meerkat.db
|
||||||
|
|
Binary file not shown.
|
@ -1,15 +1,52 @@
|
||||||
package meerkat.util;
|
package meerkat.util;
|
||||||
|
|
||||||
import meerkat.protobuf.BulletinBoardAPI.*;
|
import meerkat.crypto.DigitalSignature;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.UnsignedBulletinBoardMessage;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.security.SignatureException;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Arbel Deutsch Peled on 16-Feb-16.
|
* Created by Arbel Deutsch Peled on 16-Feb-16.
|
||||||
*/
|
*/
|
||||||
public class BulletinBoardUtils {
|
public class BulletinBoardUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates BulletinBoardMessage with UnsignedBulletinBoardMessage and its signature
|
||||||
|
* signed by all given DigitalSignatures
|
||||||
|
*
|
||||||
|
* @param unsignedMessage BasicMessage
|
||||||
|
* @param signer collection of DigitalSignature which will sign the
|
||||||
|
* UnsignedBulletinBoardMessage message
|
||||||
|
* @return BulletinBoardMessage
|
||||||
|
*/
|
||||||
|
public static BulletinBoardMessage signBulletinBoardMessage(UnsignedBulletinBoardMessage unsignedMessage,
|
||||||
|
DigitalSignature signer) throws SignatureException {
|
||||||
|
BulletinBoardMessage.Builder bulletinBoardMessage = BulletinBoardMessage.newBuilder();
|
||||||
|
bulletinBoardMessage.setMsg(unsignedMessage);
|
||||||
|
signer.updateContent(unsignedMessage);
|
||||||
|
Crypto.Signature signature = signer.sign();
|
||||||
|
bulletinBoardMessage.addSig(signature);
|
||||||
|
return bulletinBoardMessage.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the latest message from collection of messages (BulletinBoardMessage) based on timestamp
|
||||||
|
* @param messages List of BulletinBoardMessage
|
||||||
|
* @return BulletinBoardMessage
|
||||||
|
*/
|
||||||
|
public static BulletinBoardMessage getLatestMessage(Collection<BulletinBoardMessage> messages){
|
||||||
|
return Collections.max(messages, new Comparator<BulletinBoardMessage>() {
|
||||||
|
@Override
|
||||||
|
public int compare(BulletinBoardMessage o1, BulletinBoardMessage o2) {
|
||||||
|
TimestampComparator comparator = new TimestampComparator();
|
||||||
|
return comparator.compare(o1.getMsg().getTimestamp(), o2.getMsg().getTimestamp());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the tags in the message for one that begins with given prefix
|
* Searches the tags in the message for one that begins with given prefix
|
||||||
* @param message is the message to search
|
* @param message is the message to search
|
||||||
|
@ -17,7 +54,6 @@ public class BulletinBoardUtils {
|
||||||
* @return the tag without the prefix, if found, or null if not found
|
* @return the tag without the prefix, if found, or null if not found
|
||||||
*/
|
*/
|
||||||
public static String findTagWithPrefix(BulletinBoardMessage message, String prefix) {
|
public static String findTagWithPrefix(BulletinBoardMessage message, String prefix) {
|
||||||
|
|
||||||
for (String tag : message.getMsg().getTagList()){
|
for (String tag : message.getMsg().getTagList()){
|
||||||
if (tag.startsWith(prefix)) {
|
if (tag.startsWith(prefix)) {
|
||||||
return tag.substring(prefix.length());
|
return tag.substring(prefix.length());
|
||||||
|
@ -28,6 +64,22 @@ public class BulletinBoardUtils {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets list of tags values from given messages (tagName values)
|
||||||
|
* @param messages list of messages from which we want to retrieve specific tag values
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
public static List<String> GetListOfTags(List<BulletinBoardMessage> messages, String tagName) {
|
||||||
|
List<String> tagsValues = new ArrayList<>(messages.size());
|
||||||
|
for ( int i = 0 ; i < messages.size() ; i++ ){
|
||||||
|
BulletinBoardMessage message = messages.get(i);
|
||||||
|
tagsValues.add(findTagWithPrefix(message, tagName));
|
||||||
|
}
|
||||||
|
return tagsValues;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the tags in a message for tags that do not contain a given list of prefixes
|
* Searches the tags in a message for tags that do not contain a given list of prefixes
|
||||||
* @param message is the message to search
|
* @param message is the message to search
|
||||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Comparator;
|
||||||
/**
|
/**
|
||||||
* Created by Arbel Deutsch Peled on 20-Feb-16.
|
* Created by Arbel Deutsch Peled on 20-Feb-16.
|
||||||
*/
|
*/
|
||||||
public class TimestampComparator implements Comparator<com.google.protobuf.Timestamp> {
|
public class TimestampComparator implements Comparator<Timestamp> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(Timestamp o1, Timestamp o2) {
|
public int compare(Timestamp o1, Timestamp o2) {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package meerkat;
|
||||||
|
|
||||||
|
option java_package = "meerkat.protobuf";
|
||||||
|
|
||||||
|
message VoterID{
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoterInfo{
|
||||||
|
VoterID id = 1;
|
||||||
|
string info = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GroupID{
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoterRegistryMessage{
|
||||||
|
VoterID voterID = 1;
|
||||||
|
repeated GroupID groupID = 2;
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
include 'meerkat-common'
|
include 'meerkat-common'
|
||||||
include 'voting-booth'
|
include 'voting-booth'
|
||||||
include 'bulletin-board-server'
|
include 'voter-registry'
|
||||||
include 'polling-station'
|
include 'bulletin-board-server'
|
||||||
include 'restful-api-common'
|
include 'polling-station'
|
||||||
include 'bulletin-board-client'
|
include 'restful-api-common'
|
||||||
include 'distributed-key-generation'
|
include 'bulletin-board-client'
|
||||||
|
include 'distributed-key-generation'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
/bin/
|
||||||
|
*.db
|
||||||
|
/src/main/java/meerkat/manualTests.java
|
||||||
|
/.gitignore
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id "us.kirchmeier.capsule" version "1.0.1"
|
||||||
|
id 'com.google.protobuf' version '0.7.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'eclipse'
|
||||||
|
apply plugin: 'idea'
|
||||||
|
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
|
// Uncomment the lines below to define an application
|
||||||
|
// (this will also allow you to build a "fatCapsule" which includes
|
||||||
|
// the entire application, including all dependencies in a single jar)
|
||||||
|
//apply plugin: 'application'
|
||||||
|
//mainClassName='your.main.ApplicationClass'
|
||||||
|
|
||||||
|
|
||||||
|
// Is this a snapshot version?
|
||||||
|
ext { isSnapshot = false }
|
||||||
|
|
||||||
|
ext {
|
||||||
|
groupId = 'org.factcenter.meerkat'
|
||||||
|
nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/"
|
||||||
|
|
||||||
|
// Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing)
|
||||||
|
// Should be set in ${HOME}/.gradle/gradle.properties
|
||||||
|
nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : ""
|
||||||
|
nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "Meerkat Voter registry application"
|
||||||
|
|
||||||
|
// Your project version
|
||||||
|
version = "0.0"
|
||||||
|
|
||||||
|
version += "${isSnapshot ? '-SNAPSHOT' : ''}"
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Meerkat common
|
||||||
|
compile project(':meerkat-common')
|
||||||
|
compile project(':bulletin-board-client')
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
compile 'org.slf4j:slf4j-api:1.7.7'
|
||||||
|
runtime 'ch.qos.logback:logback-classic:1.1.2'
|
||||||
|
runtime 'ch.qos.logback:logback-core:1.1.2'
|
||||||
|
|
||||||
|
// Google protobufs
|
||||||
|
compile 'com.google.protobuf:protobuf-java:3.+'
|
||||||
|
|
||||||
|
// Depend on test resources from meerkat-common
|
||||||
|
testCompile project(path: ':meerkat-common', configuration: 'testOutput')
|
||||||
|
|
||||||
|
testCompile 'junit:junit:4.+'
|
||||||
|
|
||||||
|
runtime 'org.codehaus.groovy:groovy:2.4.+'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*==== You probably don't have to edit below this line =======*/
|
||||||
|
|
||||||
|
protobuf {
|
||||||
|
// Configure the protoc executable
|
||||||
|
protoc {
|
||||||
|
// Download from repositories
|
||||||
|
artifact = 'com.google.protobuf:protoc:3.+'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
project.sourceSets.each { sourceSet ->
|
||||||
|
|
||||||
|
def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java"
|
||||||
|
|
||||||
|
// add protobuf generated sources to generated source dir.
|
||||||
|
if ("test".equals(sourceSet.name)) {
|
||||||
|
testSourceDirs += file(srcDir)
|
||||||
|
} else {
|
||||||
|
sourceDirs += file(srcDir)
|
||||||
|
}
|
||||||
|
generatedSourceDirs += file(srcDir)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't exclude build directory
|
||||||
|
excludeDirs -= file(buildDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===================================
|
||||||
|
* "Fat" Build targets
|
||||||
|
*===================================*/
|
||||||
|
|
||||||
|
|
||||||
|
if (project.hasProperty('mainClassName') && (mainClassName != null)) {
|
||||||
|
|
||||||
|
task mavenCapsule(type: MavenCapsule) {
|
||||||
|
description = "Generate a capsule jar that automatically downloads and caches dependencies when run."
|
||||||
|
applicationClass mainClassName
|
||||||
|
destinationDir = buildDir
|
||||||
|
}
|
||||||
|
|
||||||
|
task fatCapsule(type: FatCapsule) {
|
||||||
|
description = "Generate a single capsule jar containing everything. Use -Pfatmain=... to override main class"
|
||||||
|
|
||||||
|
destinationDir = buildDir
|
||||||
|
|
||||||
|
def fatMain = hasProperty('fatmain') ? fatmain : mainClassName
|
||||||
|
|
||||||
|
applicationClass fatMain
|
||||||
|
|
||||||
|
def testJar = hasProperty('test')
|
||||||
|
|
||||||
|
if (hasProperty('fatmain')) {
|
||||||
|
appendix = "fat-${fatMain}"
|
||||||
|
} else {
|
||||||
|
appendix = "fat"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testJar) {
|
||||||
|
from sourceSets.test.output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*===================================
|
||||||
|
* Repositories
|
||||||
|
*===================================*/
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
|
||||||
|
// Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral)
|
||||||
|
maven {
|
||||||
|
url nexusRepository
|
||||||
|
|
||||||
|
if (isSnapshot) {
|
||||||
|
credentials { username
|
||||||
|
password
|
||||||
|
|
||||||
|
username nexusUser
|
||||||
|
password nexusPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use local maven repository
|
||||||
|
mavenLocal()
|
||||||
|
|
||||||
|
// Use 'maven central' for other dependencies.
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
task "info" << {
|
||||||
|
println "Project: ${project.name}"
|
||||||
|
println "Description: ${project.description}"
|
||||||
|
println "--------------------------"
|
||||||
|
println "GroupId: $groupId"
|
||||||
|
println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})"
|
||||||
|
println ""
|
||||||
|
}
|
||||||
|
info.description 'Print some information about project parameters'
|
||||||
|
|
||||||
|
|
||||||
|
/*===================================
|
||||||
|
* Publishing
|
||||||
|
*===================================*/
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenJava(MavenPublication) {
|
||||||
|
groupId project.groupId
|
||||||
|
pom.withXml {
|
||||||
|
asNode().appendNode('description', project.description)
|
||||||
|
}
|
||||||
|
from project.components.java
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}"
|
||||||
|
credentials { username
|
||||||
|
password
|
||||||
|
|
||||||
|
username nexusUser
|
||||||
|
password nexusPassword
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../gradlew
|
|
@ -0,0 +1,129 @@
|
||||||
|
package meerkat;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import meerkat.bulletinboard.SubscriptionAsyncBulletinBoardClient;
|
||||||
|
import meerkat.crypto.DigitalSignature;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.UnsignedBulletinBoardMessage;
|
||||||
|
import meerkat.protobuf.VoterRegistry.VoterID;
|
||||||
|
import meerkat.protobuf.VoterRegistry.VoterInfo;
|
||||||
|
import meerkat.protobuf.VoterRegistry.VoterRegistryMessage;
|
||||||
|
import meerkat.registry.AsyncRegistryCallbacks.GetGroupsCallback;
|
||||||
|
import meerkat.registry.AsyncRegistryCallbacks.GetVoterCallback;
|
||||||
|
import meerkat.registry.AsyncRegistryCallbacks.HasVotedCallback;
|
||||||
|
import meerkat.registry.MessageCollectionUtils;
|
||||||
|
import meerkat.registry.RegistryTags;
|
||||||
|
import meerkat.util.BulletinBoardUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static meerkat.util.BulletinBoardUtils.signBulletinBoardMessage;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO : add ability to use DB of certificates
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer Tokarev on 1/8/2016.
|
||||||
|
* Gives the ability to synchronously manage voters information
|
||||||
|
*/
|
||||||
|
public class AsyncRegistry implements VoterRegistry{
|
||||||
|
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
protected DigitalSignature signer;
|
||||||
|
protected SubscriptionAsyncBulletinBoardClient cachedBulletinBoardClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(DigitalSignature signer, SubscriptionAsyncBulletinBoardClient communicator) {
|
||||||
|
logger.debug("Initialized AsyncRegistry: ", new java.util.Date().getTime());
|
||||||
|
this.signer = signer;
|
||||||
|
this.cachedBulletinBoardClient = communicator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addVoter(VoterInfo voterInfo, FutureCallback<Boolean> callback) throws SignatureException {
|
||||||
|
UnsignedBulletinBoardMessage basicMessage =
|
||||||
|
UnsignedBulletinBoardMessage.newBuilder()
|
||||||
|
.addTag(RegistryTags.ID_TAG + voterInfo.getId().getId())
|
||||||
|
.addTag(RegistryTags.VOTER_ENTRY_TAG)
|
||||||
|
.setData(voterInfo.toByteString())
|
||||||
|
.setTimestamp(BulletinBoardUtils.getCurrentTimestampProto())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
cachedBulletinBoardClient.postMessage(signBulletinBoardMessage(basicMessage, signer), callback);
|
||||||
|
logger.debug("Added voter : ", RegistryTags.ID_TAG, new java.util.Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVoterGroups(VoterRegistryMessage voterRegistryMessage, FutureCallback<Boolean> callback) throws SignatureException, IOException {
|
||||||
|
UnsignedBulletinBoardMessage.Builder basicMessage =
|
||||||
|
UnsignedBulletinBoardMessage.newBuilder()
|
||||||
|
.addTag(RegistryTags.ID_TAG + voterRegistryMessage.getVoterID().getId())
|
||||||
|
.addTag(RegistryTags.ADD_TO_GROUP_TAG)
|
||||||
|
.setData(voterRegistryMessage.toByteString())
|
||||||
|
.setTimestamp(BulletinBoardUtils.getCurrentTimestampProto());
|
||||||
|
|
||||||
|
cachedBulletinBoardClient.postMessage(signBulletinBoardMessage(basicMessage.build(), signer), callback);
|
||||||
|
|
||||||
|
logger.debug("Set voter groups to be : ", new java.util.Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVoted(VoterID voterId, FutureCallback<Boolean> callback) throws SignatureException {
|
||||||
|
UnsignedBulletinBoardMessage basicMessage =
|
||||||
|
UnsignedBulletinBoardMessage.newBuilder()
|
||||||
|
.addTag(RegistryTags.ID_TAG + voterId.getId())
|
||||||
|
.addTag(RegistryTags.VOTE_ACTION_TAG)
|
||||||
|
.setTimestamp(BulletinBoardUtils.getCurrentTimestampProto())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
cachedBulletinBoardClient.postMessage(signBulletinBoardMessage(basicMessage, signer), callback);
|
||||||
|
|
||||||
|
logger.debug("Next voter has voted : ", voterId.getId(), new java.util.Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getGroups(VoterID voterID, FutureCallback<List<meerkat.protobuf.VoterRegistry.GroupID>> callback) {
|
||||||
|
List<String> GroupsActionsTags = new ArrayList<String>(2) {{
|
||||||
|
add(RegistryTags.ADD_TO_GROUP_TAG);
|
||||||
|
add(RegistryTags.ID_TAG + voterID.getId());
|
||||||
|
}};
|
||||||
|
|
||||||
|
cachedBulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(GroupsActionsTags, logger),
|
||||||
|
new GetGroupsCallback(callback));
|
||||||
|
|
||||||
|
logger.debug("Trying to retrieve next user groups : ",
|
||||||
|
voterID.getId(),
|
||||||
|
new java.util.Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getVoter(VoterID voterID, FutureCallback<VoterInfo> callback) {
|
||||||
|
List<String> addVoterTags = new ArrayList<String>(2) {{
|
||||||
|
add(RegistryTags.ID_TAG + voterID.getId());
|
||||||
|
add(RegistryTags.VOTER_ENTRY_TAG);
|
||||||
|
}};
|
||||||
|
|
||||||
|
cachedBulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(addVoterTags, logger),
|
||||||
|
new GetVoterCallback(callback));
|
||||||
|
|
||||||
|
logger.debug("Trying to retrieve next user information : ", voterID.getId(), new java.util.Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hasVoted(VoterID voterId, FutureCallback<Boolean> callBack) {
|
||||||
|
List<String> setVotedTags = new ArrayList<String>(2) {{
|
||||||
|
add(RegistryTags.ID_TAG + voterId.getId());
|
||||||
|
add(RegistryTags.VOTE_ACTION_TAG);
|
||||||
|
}};
|
||||||
|
|
||||||
|
cachedBulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(setVotedTags, logger),
|
||||||
|
new HasVotedCallback(callBack));
|
||||||
|
|
||||||
|
logger.debug("Trying to check if next has voted : ", voterId.getId(), new java.util.Date().getTime());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package meerkat;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import meerkat.bulletinboard.SubscriptionAsyncBulletinBoardClient;
|
||||||
|
import meerkat.crypto.DigitalSignature;
|
||||||
|
import meerkat.protobuf.VoterRegistry.VoterID;
|
||||||
|
import meerkat.protobuf.VoterRegistry.VoterInfo;
|
||||||
|
import meerkat.protobuf.VoterRegistry.VoterRegistryMessage;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer Tokarev on 1/22/2016.
|
||||||
|
* provides voters management options
|
||||||
|
*/
|
||||||
|
public interface VoterRegistry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the voter registry
|
||||||
|
* @param signer object which sign the outputed message
|
||||||
|
* @param communicator the object which communicates with the BulletinBoardServer
|
||||||
|
*/
|
||||||
|
void init(DigitalSignature signer, SubscriptionAsyncBulletinBoardClient communicator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds new voter to the bulletin-board
|
||||||
|
* Passes true to callback.OnSuccess if the actions succeeded else
|
||||||
|
* call the onFailure method of the callback with the arisen error
|
||||||
|
*
|
||||||
|
* @param voterInfo protobuff object that represents voter information
|
||||||
|
* @param callBack when the adding voter done callback.OnSuccess will be called
|
||||||
|
* @throws SignatureException
|
||||||
|
*/
|
||||||
|
void addVoter(VoterInfo voterInfo, FutureCallback<Boolean> callBack) throws SignatureException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adding given voter to given group
|
||||||
|
* Passes the group to callback.OnSuccess if the actions succeeded else
|
||||||
|
* call the onFailure method of the callback with the arisen error
|
||||||
|
*
|
||||||
|
* @param voterRegistryMessage protobuff object that is coupling of voterId to groupId
|
||||||
|
* @param callBack when the adding voter done callback.OnSuccess will be called
|
||||||
|
* @throws SignatureException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
void setVoterGroups(VoterRegistryMessage voterRegistryMessage, FutureCallback<Boolean> callBack) throws SignatureException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets that the voter have voted
|
||||||
|
* Passes true to callback.OnSuccess if the actions succeeded else
|
||||||
|
* call the onFailure method of the callback with the arisen error
|
||||||
|
*
|
||||||
|
* @param voterId protobuff object that represent the voter that have voted
|
||||||
|
* @param callBack when the adding voter done callback.OnSuccess will be called
|
||||||
|
* @throws SignatureException
|
||||||
|
*/
|
||||||
|
void setVoted(VoterID voterId, FutureCallback<Boolean> callBack) throws SignatureException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests all the groups that the given id voter is in
|
||||||
|
* Passes wanted groups to callback.handleResult if the actions succeeded else
|
||||||
|
* call the onFailure method of the callback with the arisen error
|
||||||
|
*
|
||||||
|
* @param voterID protobuff object that represent the voter
|
||||||
|
* @param callBack when the adding voter done callback.OnSuccess will be called
|
||||||
|
*/
|
||||||
|
void getGroups(VoterID voterID, FutureCallback<List<meerkat.protobuf.VoterRegistry.GroupID>> callBack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves VoterInfo protobuff that represents voter
|
||||||
|
* Passes wanted data to callback.handleResult if the actions succeeded else
|
||||||
|
* call the onFailure method of the callback with the arisen error
|
||||||
|
*
|
||||||
|
* @param voterID protobuff object that represent the voter
|
||||||
|
* @param callBack when the adding voter done callback.OnSuccess will be called
|
||||||
|
*/
|
||||||
|
void getVoter(VoterID voterID, FutureCallback<VoterInfo> callBack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given voter (by his id) have already voted
|
||||||
|
* passes true of the voter have been voted or not else
|
||||||
|
* call the onFailure method of the callback with the arisen error
|
||||||
|
*
|
||||||
|
* @param voterID protobuff object that represent the voter
|
||||||
|
* @param callBack method that will be called with the when the result will be found
|
||||||
|
*/
|
||||||
|
void hasVoted(VoterID voterID, FutureCallback<Boolean> callBack);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package meerkat.registry.AsyncRegistryCallbacks;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
|
||||||
|
import meerkat.protobuf.VoterRegistry;
|
||||||
|
import meerkat.registry.RegistryTags;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static meerkat.util.BulletinBoardUtils.findTagWithPrefix;
|
||||||
|
import static meerkat.util.BulletinBoardUtils.getLatestMessage;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer on 3/12/2016.
|
||||||
|
* AsyncRegistry getGroups creates this callback to list of groups the voter in
|
||||||
|
*/
|
||||||
|
public class GetGroupsCallback implements FutureCallback<List<BulletinBoardMessage>> {
|
||||||
|
protected FutureCallback<List<VoterRegistry.GroupID>> callback;
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
public GetGroupsCallback(FutureCallback<List<VoterRegistry.GroupID>> callback){
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets List of GroupId objects from given message
|
||||||
|
* @param message BulletinBoardMessage which contains all groups ids of voter
|
||||||
|
* @return list of GroupId
|
||||||
|
* @throws IOException
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
private List<VoterRegistry.GroupID> getVoterGroups(BulletinBoardMessage message) throws IOException, ClassNotFoundException {
|
||||||
|
logger.debug("Initialized GetGroupsCallback : ", new java.util.Date().getTime());
|
||||||
|
VoterRegistry.VoterRegistryMessage voterRegistryMessage =
|
||||||
|
VoterRegistry.VoterRegistryMessage.parseFrom(message.getMsg().getData());
|
||||||
|
|
||||||
|
return voterRegistryMessage.getGroupIDList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<BulletinBoardMessage> messages) {
|
||||||
|
if (messages.isEmpty()){
|
||||||
|
callback.onFailure(new NotFoundException("Voter permissions not found in database"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BulletinBoardMessage message = getLatestMessage(messages);
|
||||||
|
try {
|
||||||
|
|
||||||
|
logger.debug("Wanted voter groups been retrieved: ",
|
||||||
|
findTagWithPrefix(message, RegistryTags.ID_TAG),
|
||||||
|
new java.util.Date().getTime());
|
||||||
|
|
||||||
|
callback.onSuccess(getVoterGroups(message));
|
||||||
|
} catch (IOException | ClassNotFoundException e) {
|
||||||
|
logger.error("Error occurred while trying to get voter groups ",
|
||||||
|
new java.util.Date().getTime(),
|
||||||
|
e);
|
||||||
|
callback.onFailure(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
logger.error("Error occurred while trying to get voter groups ",
|
||||||
|
new java.util.Date().getTime(),
|
||||||
|
t);
|
||||||
|
this.callback.onFailure(t);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package meerkat.registry.AsyncRegistryCallbacks;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
|
||||||
|
import meerkat.registry.RegistryTags;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static meerkat.util.BulletinBoardUtils.findTagWithPrefix;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer Tokarev on 3/12/2016.
|
||||||
|
* AsyncRegistry hasVoted creates this callback to check if wanted user has voted
|
||||||
|
*/
|
||||||
|
public class HasVotedCallback implements FutureCallback<List<BulletinBoardMessage>>{
|
||||||
|
protected FutureCallback<Boolean> callback;
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
public HasVotedCallback(FutureCallback<Boolean> callback){
|
||||||
|
logger.debug("Initialized HasVotedCallback : ", new java.util.Date().getTime());
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<BulletinBoardMessage> messages) {
|
||||||
|
if (messages.isEmpty()){
|
||||||
|
callback.onSuccess(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("The next voter has voted: ",
|
||||||
|
findTagWithPrefix(messages.get(0), RegistryTags.ID_TAG),
|
||||||
|
new java.util.Date().getTime());
|
||||||
|
callback.onSuccess(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
logger.error("Error occurred while trying to check if voter has voted: ",
|
||||||
|
new java.util.Date().getTime(),
|
||||||
|
t);
|
||||||
|
this.callback.onFailure(t);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package meerkat.registry.AsyncRegistryCallbacks;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
|
||||||
|
import meerkat.protobuf.VoterRegistry;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static meerkat.util.BulletinBoardUtils.getLatestMessage;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer on 3/12/2016.
|
||||||
|
* AsyncRegistry getVoter creates this callback to get voterInfo protobuff
|
||||||
|
*/
|
||||||
|
public class GetVoterCallback implements FutureCallback<List<BulletinBoardMessage>> {
|
||||||
|
protected FutureCallback<VoterRegistry.VoterInfo> callback;
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
public GetVoterCallback(FutureCallback<VoterRegistry.VoterInfo> callback){
|
||||||
|
logger.debug("Initialized GetVoterCallback : ", new java.util.Date().getTime());
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(List<BulletinBoardMessage> messages) {
|
||||||
|
if(messages.isEmpty()){
|
||||||
|
callback.onFailure(new NotFoundException("Voter info not found in database."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BulletinBoardMessage latestMessage = getLatestMessage(messages);
|
||||||
|
|
||||||
|
try {
|
||||||
|
VoterRegistry.VoterInfo info = VoterRegistry.VoterInfo.newBuilder()
|
||||||
|
.mergeFrom(latestMessage.getMsg().getData()).build();
|
||||||
|
|
||||||
|
logger.debug("Wanted voter information: ", info.getId().getId(), info.getInfo(),
|
||||||
|
new java.util.Date().getTime());
|
||||||
|
|
||||||
|
callback.onSuccess(info);
|
||||||
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
logger.error("Error occurred while trying to get voter information: ",
|
||||||
|
new java.util.Date().getTime(),
|
||||||
|
e);
|
||||||
|
callback.onFailure(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
logger.error("Error occurred while trying to get voter information:",
|
||||||
|
new java.util.Date().getTime(),
|
||||||
|
t);
|
||||||
|
callback.onFailure(t);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package meerkat.registry;
|
||||||
|
|
||||||
|
import com.sun.deploy.util.StringUtils;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.FilterType;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.MessageFilter;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.MessageFilterList;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer Tokarev on 1/15/2016.
|
||||||
|
* adds extra functionality to Messages collections
|
||||||
|
*/
|
||||||
|
public abstract class MessageCollectionUtils {
|
||||||
|
/**
|
||||||
|
* Creates list of filters based on given list of strings (that are tags)
|
||||||
|
*
|
||||||
|
* @param logger logger object with debug method
|
||||||
|
* @param tags the tags based on which the messages will be filtered
|
||||||
|
* @return MessageFilterList.
|
||||||
|
*/
|
||||||
|
public static MessageFilterList generateFiltersFromTags(List<String> tags, Logger logger) {
|
||||||
|
if (tags == null){
|
||||||
|
return MessageFilterList.getDefaultInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFilterList.Builder filters = MessageFilterList.newBuilder();
|
||||||
|
|
||||||
|
for (String tag : tags) {
|
||||||
|
MessageFilter filter = MessageFilter.newBuilder().setTag(tag).setType(FilterType.TAG).build();
|
||||||
|
filters.addFilter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Converted next strings to filters", StringUtils.join(tags, " "));
|
||||||
|
|
||||||
|
return filters.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package meerkat.registry;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Vladimir Eliezer Tokarev on 1/9/2016.
|
||||||
|
* Have the tags for the registry messages
|
||||||
|
*/
|
||||||
|
public interface RegistryTags {
|
||||||
|
public static final String ID_TAG = "ID: ";
|
||||||
|
public static final String VOTER_ENTRY_TAG = "VoterEntry: ";
|
||||||
|
public static final String GROUP_ID_TAG = "GroupID: ";
|
||||||
|
public static final String ADD_TO_GROUP_TAG = "setVoterGroups: ";
|
||||||
|
public static final String VOTE_ACTION_TAG = "VoteAction: ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,508 @@
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import meerkat.AsyncRegistry;
|
||||||
|
import meerkat.bulletinboard.BulletinBoardServer;
|
||||||
|
import meerkat.bulletinboard.LocalBulletinBoardClient;
|
||||||
|
import meerkat.bulletinboard.sqlserver.BulletinBoardSQLServer;
|
||||||
|
import meerkat.bulletinboard.sqlserver.H2QueryProvider;
|
||||||
|
import meerkat.comm.CommunicationException;
|
||||||
|
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.registry.MessageCollectionUtils;
|
||||||
|
import meerkat.registry.RegistryTags;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
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.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
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.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 DigitalSignature signer;
|
||||||
|
private LocalBulletinBoardClient localBulletinBoardClient;
|
||||||
|
private SecureRandom random = new SecureRandom();
|
||||||
|
Semaphore jobSemaphore;
|
||||||
|
|
||||||
|
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";
|
||||||
|
private static final String DB_NAME = "TestDB";
|
||||||
|
private static final int SUBSCRIPTION_DELAY = 3000;
|
||||||
|
private static final int THREAD_NUM = 3;
|
||||||
|
final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
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.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates LocalBulletinBoardClient which connects to TestDB
|
||||||
|
* @return LocalBulletinBoardClient object
|
||||||
|
* @throws CommunicationException
|
||||||
|
*/
|
||||||
|
private LocalBulletinBoardClient CreateLocalBulletinBoardClient() throws CommunicationException, SQLException {
|
||||||
|
H2QueryProvider queryProvider = new H2QueryProvider(DB_NAME) ;
|
||||||
|
|
||||||
|
Connection conn = queryProvider.getDataSource().getConnection();
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
|
||||||
|
List<String> deletionQueries = queryProvider.getSchemaDeletionCommands();
|
||||||
|
|
||||||
|
for (String deletionQuery : deletionQueries) {
|
||||||
|
stmt.execute(deletionQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
BulletinBoardServer server = new BulletinBoardSQLServer(queryProvider);
|
||||||
|
server.init(DB_NAME);
|
||||||
|
|
||||||
|
logger.debug("Created new LocalBulletinBoardClient: {}", new Date());
|
||||||
|
|
||||||
|
return new LocalBulletinBoardClient(server, THREAD_NUM, SUBSCRIPTION_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize CachedBulletinBoardClient client that communicates with LocalBulletinBoardClient
|
||||||
|
* @throws InstantiationException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
* @throws CommunicationException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
private void CommunicatorSetup() throws InstantiationException, IllegalAccessException, CommunicationException, SQLException {
|
||||||
|
localBulletinBoardClient = CreateLocalBulletinBoardClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the signer to be instance of ECDSASignature
|
||||||
|
*/
|
||||||
|
private void SetSigner(){
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
this.signer = signer;
|
||||||
|
logger.info("Have set new signer: {}", new Date());
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
assert false : "The signers creation failed ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the needed params for all the tests
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws InstantiationException
|
||||||
|
* @throws CommunicationException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() throws SQLException, InstantiationException, CommunicationException, IllegalAccessException {
|
||||||
|
SetSigner();
|
||||||
|
CommunicatorSetup();
|
||||||
|
jobSemaphore = new Semaphore(0);
|
||||||
|
logger.info("Ended the setup preparations: {}", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AsyncRegistry GetRegistry()
|
||||||
|
{
|
||||||
|
AsyncRegistry registry = new AsyncRegistry();
|
||||||
|
registry.init(signer, localBulletinBoardClient);
|
||||||
|
logger.info("Created new AsyncRegistry: {}", new Date());
|
||||||
|
return registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates random string 32 chars length
|
||||||
|
* @return String object
|
||||||
|
*/
|
||||||
|
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 {
|
||||||
|
logger.info("Testing registry creation: {}", new Date());
|
||||||
|
GetRegistry();
|
||||||
|
logger.info("Registry creation succeed: {} \n\n", new Date());
|
||||||
|
} 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("Counted {} messages with all wanted tags from {} given messages: {}",
|
||||||
|
counter,
|
||||||
|
messages.size(),
|
||||||
|
new Date());
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads messages from localBulletinBoardClient 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, logger);
|
||||||
|
DummyBulletinBoardCallBackHandler bulletinHandler = new DummyBulletinBoardCallBackHandler();
|
||||||
|
localBulletinBoardClient.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 {
|
||||||
|
logger.info("Testing registry adding voter functionality: {}", new Date());
|
||||||
|
|
||||||
|
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);
|
||||||
|
logger.info("Tried to add next voter to registry: id: {} {}",
|
||||||
|
voterInfo.getId().getId(),
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
jobSemaphore.acquire();
|
||||||
|
assertEquals(1, handler.counter );
|
||||||
|
|
||||||
|
List<String> tags = new ArrayList<String>(){{ add(RegistryTags.VOTER_ENTRY_TAG);}};
|
||||||
|
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
|
||||||
|
|
||||||
|
|
||||||
|
jobSemaphore.acquire();
|
||||||
|
logger.info("Got add voter messages that have been added lately to the server: {} {}",
|
||||||
|
GetListOfTags(bulletinHandler.messages, RegistryTags.ID_TAG),
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
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.";
|
||||||
|
logger.info("The server had a message with voter data: id: {} data: {} {}", id, data, new Date());
|
||||||
|
logger.info("Ended testing registry adding voter functionality: {}\n\n", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
logger.info("Testing registry set voted functionality: {}", new Date());
|
||||||
|
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
|
||||||
|
|
||||||
|
String id = generateString();
|
||||||
|
VoterID voterInfo = VoterID.newBuilder().setId(id).build();
|
||||||
|
|
||||||
|
AsyncRegistry registry = GetRegistry();
|
||||||
|
registry.setVoted(voterInfo, handler);
|
||||||
|
logger.info("Tried to set that next voter voted : id: {} {}",
|
||||||
|
voterInfo.getId(),
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
jobSemaphore.acquire();
|
||||||
|
assertEquals(1, handler.counter );
|
||||||
|
|
||||||
|
List<String> tags = new ArrayList<String>(){{ add(RegistryTags.VOTE_ACTION_TAG);}};
|
||||||
|
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
|
||||||
|
|
||||||
|
jobSemaphore.acquire();
|
||||||
|
logger.info("Got set voted messages that have been added lately to the server: {} {} ",
|
||||||
|
GetListOfTags(bulletinHandler.messages, RegistryTags.ID_TAG),
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
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.";
|
||||||
|
logger.info("The server had a message with voter data: id: {} {}", id, new Date());
|
||||||
|
logger.info("Ended testing registry set voted functionality: {}\n\n", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that get groups retrieves the right groups the user are in
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSetVoterGroups() throws InterruptedException, SignatureException, IOException, ClassNotFoundException {
|
||||||
|
logger.info("Testing registry set voter groups functionality: {}", new Date());
|
||||||
|
|
||||||
|
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);
|
||||||
|
logger.info("Tried to set voter groups : id: {} groupId: {} {}",
|
||||||
|
voterId,
|
||||||
|
groupId1,
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
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();
|
||||||
|
logger.info("Got set voter groups messages that have been added lately to the server: {} {} ",
|
||||||
|
GetListOfTags(bulletinHandler.messages, RegistryTags.ID_TAG),
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
BulletinBoardMessage latestMessage = getLatestMessage(bulletinHandler.messages);
|
||||||
|
|
||||||
|
assert findTagWithPrefix(latestMessage, RegistryTags.ID_TAG).equals(voterId) :
|
||||||
|
"The latest message recieved is not of our voter";
|
||||||
|
|
||||||
|
logger.info("The server had a message of our voter, data: id: {} {}",
|
||||||
|
findTagWithPrefix(latestMessage, RegistryTags.ID_TAG), new Date());
|
||||||
|
|
||||||
|
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";
|
||||||
|
logger.info("The server had a message with voter data: groupId: {} {}",
|
||||||
|
groupsIds.get(0).getId(), new Date());
|
||||||
|
logger.info("Ended testing registry set voter groups functionality: {}\n\n", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
logger.info("Testing registry get voter groups functionality: {}", new Date());
|
||||||
|
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();
|
||||||
|
|
||||||
|
AsyncRegistry registry = GetRegistry();
|
||||||
|
registry.setVoterGroups(voterInfo, handler);
|
||||||
|
logger.info("Tried to set voter groups : id: {} groupId 1: {} groupId 2: {} {}",
|
||||||
|
voterId,
|
||||||
|
groupId1,
|
||||||
|
groupId2,
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
logger.info("Got get voter groups messages that have been added lately to the server: {}",
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
logger.info("The server had a message with wanted data: groupId 1: {} groupId 2: {} {}",
|
||||||
|
groupId1, groupId2, new Date());
|
||||||
|
logger.info("Ended testing registry get voter groups functionality: {}\n\n", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the personal data outputted about the user is right
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetVoter() throws InterruptedException, SignatureException {
|
||||||
|
logger.info("Testing registry get voter groups functionality: {}", new Date());
|
||||||
|
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);
|
||||||
|
|
||||||
|
logger.info("Tried to get voter with data: id: {} groupId 1: {} groupId 2: {} {}",
|
||||||
|
id, data, new Date());
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
logger.info("Got get voter messages that have been added lately to the server: {} {}",
|
||||||
|
personalHandler.data.getId(),
|
||||||
|
new Date());
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
logger.info("The server had a message with wanted data: if: {} personal data: {} {}",
|
||||||
|
personalHandler.data.getId().getId(), personalData, new Date());
|
||||||
|
logger.info("Ended testing registry get voter functionality: {}\n\n", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the hasVoted method of registry works
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testHasVoted () throws InterruptedException, SignatureException {
|
||||||
|
logger.info("Testing registry has voted functionality: {}", new Date());
|
||||||
|
|
||||||
|
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
|
||||||
|
String id = generateString();
|
||||||
|
VoterID voterInfo = VoterID.newBuilder().setId(id).build();
|
||||||
|
|
||||||
|
AsyncRegistry registry = GetRegistry();
|
||||||
|
registry.setVoted(voterInfo, handler);
|
||||||
|
|
||||||
|
logger.info("Tried to set voted with data: id: {} groupId 1: {} {}",
|
||||||
|
id, new Date());
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
logger.info("Got has voted messages that have been added lately to the server: {} {}",
|
||||||
|
personalHandler.data,
|
||||||
|
new Date());
|
||||||
|
assertTrue("The voter hasn't voted yet.", personalHandler.data);
|
||||||
|
|
||||||
|
logger.info("Ended testing registry has voted functionality: {}\n\n", new Date());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue