* This method checks if we have enough resources to schedule the given amount of tasks and reserves the space if
- * the check is successful.
- *
+ * the check is successful.
+ *
+ *
* The reserved resources will be freed again once the tasks finish their execution or when they are cancelled
- * through their corresponding {@link Future}.
+ * through their corresponding {@link Future}.
+ *
*
* @param requestedJobCount the amount of tasks that shall be scheduled
* @return true if we could reserve the given space and false otherwise
@@ -908,11 +1003,14 @@ private boolean reserveCapacity(int requestedJobCount) {
}
/**
+ *
* This method is a utility method that simply checks the passed in object for being {@code null} and throws a
- * {@link RejectedExecutionException} if it is.
- *
+ * {@link RejectedExecutionException} if it is.
+ *
+ *
* It is used to turn the silent methods into non-silent ones and conform with the {@link ScheduledExecutorService}
- * interface.
+ * interface.
+ *
*
* @param result the object that shall be checked for being null (the result of a "silent" method call)
* @param the type of the result
diff --git a/src/main/java/com/iota/iri/utils/thread/DedicatedScheduledExecutorService.java b/src/main/java/com/iota/iri/utils/thread/DedicatedScheduledExecutorService.java
index d0dd4923ab..93ab1af3d4 100644
--- a/src/main/java/com/iota/iri/utils/thread/DedicatedScheduledExecutorService.java
+++ b/src/main/java/com/iota/iri/utils/thread/DedicatedScheduledExecutorService.java
@@ -6,49 +6,56 @@
import java.util.concurrent.*;
/**
+ *
* This class represents a {@link ScheduledExecutorService} that is associated with one specific task for which it
- * provides automatic logging capabilities
- *
+ * provides automatic logging capabilities.
+ *
+ *
* It informs the user about its lifecycle using the logback loggers used by IRI. In addition it offers "silent" methods
* of the {@link ScheduledExecutorService} that do not throw {@link Exception}s when we try to start the same task
* multiple times. This is handy for implementing the "start" and "shutdown" methods of the background workers of IRI
* that would otherwise have to take care of not starting the same task more than once (when trying to be robust against
- * coding errors or tests that start the same thread multiple times).
+ * coding errors or tests that start the same thread multiple times).
+ *
*/
public class DedicatedScheduledExecutorService extends BoundedScheduledExecutorService {
/**
- * Default logger for this class allowing us to dump debug and status messages.
- *
+ * Default logger for this class allowing us to dump debug and status messages.
+ *
* Note: The used logger can be overwritten by providing a different logger in the constructor (to have transparent
- * log messages that look like they are coming from a different source).
+ * log messages that look like they are coming from a different source).
+ *
*/
private static final Logger DEFAULT_LOGGER = LoggerFactory.getLogger(DedicatedScheduledExecutorService.class);
/**
- * Holds a reference to the logger that is used to emit messages.
+ * Holds a reference to the logger that is used to emit messages.
*/
private final Logger logger;
/**
- * Holds the name of the thread that gets started by this class and that gets printed in the log messages.
+ * Holds the name of the thread that gets started by this class and that gets printed in the log messages.
*/
private final String threadName;
/**
- * Flag indicating if we want to issue debug messages (for example whenever a task gets started and finished).
+ * Flag indicating if we want to issue debug messages (for example whenever a task gets started and finished).
*/
private final boolean debug;
/**
+ *
* Creates a {@link ScheduledExecutorService} that is associated with one specific task for which it provides
- * automatic logging capabilities (using the provided thread name).
- *
+ * automatic logging capabilities (using the provided thread name).
+ *
+ *
* It informs the user about its lifecycle using the logback loggers used by IRI. In addition it offers "silent"
* methods of the {@link ScheduledExecutorService} that do not throw {@link Exception}s when we try to start the
* same task multiple times. This is handy for implementing the "start" and "shutdown" methods of the background
* workers of IRI that would otherwise have to take care of not starting the same task more than once (when trying
- * to be robust against coding errors or tests that start the same thread multiple times).
- *
+ * to be robust against coding errors or tests that start the same thread multiple times).
+ *
+ *
*
* Example:
*
@@ -82,7 +89,8 @@ public class DedicatedScheduledExecutorService extends BoundedScheduledExecutorS
* [main] INFO MilestoneSolidifier - [Milestone Solidifier] Stopped (after #4 executions) ...
*
- *
+ *
+ *
* @param threadName name of the thread (or null if we want to disable the automatic logging - exceptions will
* always be logged)
* @param logger logback logger that shall be used for the origin of the log messages
@@ -98,7 +106,7 @@ public DedicatedScheduledExecutorService(String threadName, Logger logger, boole
/**
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to the
- * {@link #DEFAULT_LOGGER} for the log messages.
+ * {@link #DEFAULT_LOGGER} for the log messages.
*
* @param threadName name of the thread (or null if we want to disable the automatic logging - exceptions will
* always be logged)
@@ -110,7 +118,7 @@ public DedicatedScheduledExecutorService(String threadName, boolean debug) {
/**
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to false
- * for the debug flag.
+ * for the debug flag.
*
* @param threadName name of the thread (or null if we want to disable the automatic logging - exceptions will
* always be logged)
@@ -121,11 +129,14 @@ public DedicatedScheduledExecutorService(String threadName, Logger logger) {
}
/**
+ *
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to {@code null}
- * for the thread name (which causes only error messages to be printed - unless debug is true).
- *
+ * for the thread name (which causes only error messages to be printed - unless debug is true).
+ *
+ *
* Note: This is for example used by the {@link com.iota.iri.utils.log.interval.IntervalLogger} which does not want
- * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ *
*
* @param logger logback logger that shall be used for the origin of the log messages
* @param debug debug flag that indicates if every "run" should be accompanied with a log message
@@ -136,7 +147,7 @@ public DedicatedScheduledExecutorService(Logger logger, boolean debug) {
/**
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to the
- {@link #DEFAULT_LOGGER} for the log messages and false for the debug flag.
+ {@link #DEFAULT_LOGGER} for the log messages and false for the debug flag.
*
* @param threadName name of the thread (or null if we want to disable the automatic logging - exceptions will
* always be logged)
@@ -146,13 +157,16 @@ public DedicatedScheduledExecutorService(String threadName) {
}
/**
+ *
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to {@code null}
* for the thread name (which causes only error messages to be printed - unless debug is true) and and false for the
- * debug flag.
- *
+ * debug flag.
+ *
+ *
* Note: This is for example used by the {@link com.iota.iri.utils.log.interval.IntervalLogger} which does not want
- * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
- *
+ * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ *
+ *
* @param logger logback logger that shall be used for the origin of the log messages
*/
public DedicatedScheduledExecutorService(Logger logger) {
@@ -160,12 +174,15 @@ public DedicatedScheduledExecutorService(Logger logger) {
}
/**
+ *
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to {@code null}
* for the thread name (which causes only error messages to be printed - unless debug is true) and the
- * {@link #DEFAULT_LOGGER} for the log messages.
- *
+ * {@link #DEFAULT_LOGGER} for the log messages.
+ *
+ *
* Note: This is for example used by the {@link com.iota.iri.utils.log.interval.IntervalLogger} which does not want
- * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ *
*
* @param debug debug flag that indicates if every "run" should be accompanied with a log message
*/
@@ -174,19 +191,22 @@ public DedicatedScheduledExecutorService(boolean debug) {
}
/**
+ *
* Does the same as {@link #DedicatedScheduledExecutorService(String, Logger, boolean)} but defaults to {@code null}
* for the thread name (which causes only error messages to be printed), the {@link #DEFAULT_LOGGER} for the log
- * messages and {@code false} for the debug flag.
- *
+ * messages and {@code false} for the debug flag.
+ *
+ *
* Note: This is for example used by the {@link com.iota.iri.utils.log.interval.IntervalLogger} which does not want
- * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ * to inform the user when scheduling a log output, but which still needs the "only run one task" logic.
+ *
*/
public DedicatedScheduledExecutorService() {
this(null, DEFAULT_LOGGER, false);
}
/**
- * This method is the getter for the name of the thread that gets created by this service.
+ * This method is the getter for the name of the thread that gets created by this service.
*
* @return it simply returns the private property of {@link #threadName}.
*/
@@ -198,10 +218,14 @@ public String getThreadName() {
/**
* {@inheritDoc}
- * This method shows a message whenever a task gets successfully scheduled.
- *
+ *
+ *
+ * This method shows a message whenever a task gets successfully scheduled.
+ *
+ *
* We only show the scheduling message if debugging is enabled or a thread name was defined when creating this
- * {@link DedicatedScheduledExecutorService} (to not pollute the CLI with meaningless messages).
+ * {@link DedicatedScheduledExecutorService} (to not pollute the CLI with meaningless messages).
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -216,17 +240,23 @@ public void onScheduleTask(TaskDetails taskDetails) {
/**
* {@inheritDoc}
- * This method shows a message whenever a task starts to be processed.
- *
+ *
+ *
+ * This method shows a message whenever a task starts to be processed.
+ *
+ *
* We only show the starting message if debug is enabled or if it is the first start of the task in a named
* {@link DedicatedScheduledExecutorService} (display it like it would be a {@link Thread} with one start message
- * and one stop message - to not pollute the CLI with meaningless messages).
- *
+ * and one stop message - to not pollute the CLI with meaningless messages).
+ *
+ *
* To increase the information available for debugging, we change the thread name to the one that initiated the
- * start (rather than the randomly assigned one from the executor service) before printing the start message.
- *
+ * start (rather than the randomly assigned one from the executor service) before printing the start message.
+ *
+ *
* After the start message was printed, we set the name of the {@link Thread} that will consequently be used for log
- * messages from the task itself.
+ * messages from the task itself.
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -249,15 +279,20 @@ public void onStartTask(TaskDetails taskDetails) {
/**
* {@inheritDoc}
+ *
+ *
* This method shows a message when the task finishes its execution (can happen multiple times for recurring
- * tasks).
- *
+ * tasks).
+ *
+ *
* We only show the finishing message if debug is enabled and if no error occurred (otherwise the
- * {@link #onCompleteTask(TaskDetails, Throwable)} callback will give enough information about the crash).
- *
+ * {@link #onCompleteTask(TaskDetails, Throwable)} callback will give enough information about the crash).
+ *
+ *
* To be consistent with the start message, we change the thread name to the one that initiated the task (this also
* makes it easier to distinguish log messages that are emitted by the "real" logic of the task from the "automated"
- * messages about its lifecycle).
+ * messages about its lifecycle).
+ *
*
* @param taskDetails metadata holding the relevant information of the task
* @param error the exception that caused this task to terminate or {@code null} if it terminated normally
@@ -275,10 +310,14 @@ public void onFinishTask(TaskDetails taskDetails, Throwable error) {
/**
* {@inheritDoc}
- * This method shows an information about the intent to cancel the task.
- *
+ *
+ *
+ * This method shows an information about the intent to cancel the task.
+ *
+ *
* We only show the cancel message if debugging is enabled or a thread name was defined when creating this
- * {@link DedicatedScheduledExecutorService} (to not pollute the CLI with meaningless messages).
+ * {@link DedicatedScheduledExecutorService} (to not pollute the CLI with meaningless messages).
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -293,15 +332,21 @@ public void onCancelTask(TaskDetails taskDetails) {
/**
* {@inheritDoc}
+ *
+ *
* This method shows a stopped message whenever it finally terminates (and doesn't get launched again in case of
- * recurring tasks).
- *
+ * recurring tasks).
+ *
+ *
* We only show the stopped message if debug is enabled, an exception occurred (always show unexpected errors) or if
* we have a named {@link DedicatedScheduledExecutorService} (to not pollute the CLI with meaningless
- * messages).
+ * messages).
+ *
+ *
* If the completion of the task was not caused by an outside call to cancel it, we change the thread name to the
* one that initiated the task (this makes it easier to distinguish log messages that are emitted by the "real"
- * logic of the task from the "automated" messages about its lifecycle).
+ * logic of the task from the "automated" messages about its lifecycle).
+ *
*
* @param taskDetails metadata holding the relevant information of the task
* @param error the exception that caused this task to terminate or {@code null} if it terminated normally
@@ -329,10 +374,13 @@ public void onCompleteTask(TaskDetails taskDetails, Throwable error) {
//region PRIVATE UTILITY METHODS ///////////////////////////////////////////////////////////////////////////////////
/**
- * This method is a utility method that prints the schedule message of the task.
- *
+ *
+ * This method is a utility method that prints the schedule message of the task.
+ *
+ *
* It constructs the matching message by passing the task details into the
- * {@link #buildScheduledMessage(TaskDetails)} method.
+ * {@link #buildScheduledMessage(TaskDetails)} method.
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -341,10 +389,13 @@ private void printScheduledMessage(TaskDetails taskDetails) {
}
/**
- * This method is a utility method that prints the started message of the task.
- *
+ *
+ * This method is a utility method that prints the started message of the task.
+ *
+ *
* It constructs the message by passing the details into the {@link #buildStartedMessage(TaskDetails)} and printing
- * it through the logger.
+ * it through the logger.
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -353,10 +404,13 @@ private void printStartedMessage(TaskDetails taskDetails) {
}
/**
- * This method is a utility method that prints the finished message of the task.
- *
+ *
+ * This method is a utility method that prints the finished message of the task.
+ *
+ *
* It constructs the message by passing the details into the {@link #buildFinishedMessage(TaskDetails)} and printing
- * it through the logger.
+ * it through the logger.
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -365,10 +419,13 @@ private void printFinishedMessage(TaskDetails taskDetails) {
}
/**
- * This method is a utility method that prints the stop message of the task.
- *
+ *
+ * This method is a utility method that prints the stop message of the task.
+ *
+ *
* It constructs the message by passing the details into the {@link #buildStopMessage(TaskDetails)} and printing
- * it through the logger.
+ * it through the logger.
+ *
*
* @param taskDetails metadata holding the relevant information of the task
*/
@@ -377,12 +434,15 @@ private void printStopMessage(TaskDetails taskDetails) {
}
/**
- * This method is a utility method that prints the stopped message of the task.
- *
+ *
+ * This method is a utility method that prints the stopped message of the task.
+ *
+ *
* It constructs the message by passing the details into the {@link #buildStoppedMessage(TaskDetails, Throwable)}
* and printing it through the logger. If an error occurred we use the error channel and append the error to
- * get a stack trace of what happened.
- *
+ * get a stack trace of what happened.
+ *
+ *
* @param taskDetails metadata holding the relevant information of the task
* @param error the exception that caused the task to be stopped
*/
@@ -396,10 +456,13 @@ private void printStoppedMessage(TaskDetails taskDetails, Throwable error) {
}
/**
- * This method is a utility method that generates the thread name that is used in the log messages.
- *
+ *
+ * This method is a utility method that generates the thread name that is used in the log messages.
+ *
+ *
* It simply returns the thread name (if one is set) or generates a name if this
- * {@link DedicatedScheduledExecutorService} is "unnamed".
+ * {@link DedicatedScheduledExecutorService} is "unnamed".
+ *
*
* @return the thread name that is used in the log messages
*/
@@ -411,7 +474,7 @@ private String getPrintableThreadName(TaskDetails taskDetails) {
/**
* This method creates the schedule message of the task by first building the temporal parts of the message and
- * then appending them to the actual message.
+ * then appending them to the actual message.
*
* @param taskDetails metadata holding the relevant information of the task
* @return the schedule message that can be used with the logger
@@ -435,7 +498,7 @@ private String buildScheduledMessage(TaskDetails taskDetails) {
/**
* This method creates the started message of the task by simply extracting the relevant information from the
- * {@code taskDetails} and concatenating them to the actual message.
+ * {@code taskDetails} and concatenating them to the actual message.
*
* @param taskDetails metadata holding the relevant information of the task
* @return the started message that can be used with the logger
@@ -449,7 +512,7 @@ private String buildStartedMessage(TaskDetails taskDetails) {
/**
* This method creates the finished message of the task by simply extracting the relevant information from the
- * {@code taskDetails} and concatenating them to the actual message.
+ * {@code taskDetails} and concatenating them to the actual message.
*
* @param taskDetails metadata holding the relevant information of the task
* @return the finished message that can be used with the logger
@@ -463,7 +526,7 @@ private String buildFinishedMessage(TaskDetails taskDetails) {
/**
* This method creates the stop message of the task by simply extracting the relevant information from the
- * {@code taskDetails} and concatenating them to the actual message.
+ * {@code taskDetails} and concatenating them to the actual message.
*
* @param taskDetails metadata holding the relevant information of the task
* @return the stop message that can be used with the logger
@@ -475,12 +538,15 @@ private String buildStopMessage(TaskDetails taskDetails) {
: "Cancelling Start [" + printableThreadName + "] ...";
}
- /**
+ /**
+ *
* This method creates the stopped message of the task by simply extracting the relevant information from the
- * {@code taskDetails} and concatenating them to the actual message.
- *
- * We differentiate between different termination ways by giving different reasons in the message.
- *
+ * {@code taskDetails} and concatenating them to the actual message.
+ *
+ *
+ * We differentiate between different termination ways by giving different reasons in the message.
+ *
+ *
* @param taskDetails metadata holding the relevant information of the task
* @return the stop message that can be used with the logger
*/
@@ -500,7 +566,7 @@ private String buildStoppedMessage(TaskDetails taskDetails, Throwable error) {
/**
* This method is a utility method that builds the message fragment which expresses the delay of the scheduled
- * task.
+ * task.
*
* @param taskDetails metadata holding the relevant information of the task
* @return the message fragment which expresses the delay of the scheduled task
@@ -515,7 +581,7 @@ private String buildDelayMessageFragment(TaskDetails taskDetails) {
/**
* This method is a utility method that builds the message fragment which expresses the interval of the scheduled
- * task.
+ * task.
*
* @param taskDetails metadata holding the relevant information of the task
* @return the message fragment which expresses the interval of the scheduled task
@@ -530,7 +596,7 @@ private String buildIntervalMessageFragment(TaskDetails taskDetails) {
/**
* This method is a utility method that creates a human readable abbreviation of the provided
- * {@link TimeUnit}.
+ * {@link TimeUnit}.
*
* @param unit the time unit used for the values in the {@link TaskDetails}
* @return a human readable abbreviation of the provided {@link TimeUnit}
diff --git a/src/main/java/com/iota/iri/utils/thread/ReportingExecutorService.java b/src/main/java/com/iota/iri/utils/thread/ReportingExecutorService.java
index d10c3a71fc..96160efb78 100644
--- a/src/main/java/com/iota/iri/utils/thread/ReportingExecutorService.java
+++ b/src/main/java/com/iota/iri/utils/thread/ReportingExecutorService.java
@@ -1,36 +1,48 @@
package com.iota.iri.utils.thread;
/**
+ *
* This interface defines a contract for {@link java.util.concurrent.ExecutorService}s that makes them call a
- * "reporting" method whenever an important event occurs.
- *
+ * "reporting" method whenever an important event occurs.
+ *
+ *
* This way a child class extending these kind of {@link java.util.concurrent.ExecutorService}s can "hook" into these
- * events by overriding the specific method and add additional logic like logging or debugging capabilities.
+ * events by overriding the specific method and add additional logic like logging or debugging capabilities.
+ *
*/
public interface ReportingExecutorService {
/**
- * This method gets called whenever a new task is scheduled to run.
- *
+ *
+ * This method gets called whenever a new task is scheduled to run.
+ *
+ *
* In contrast to {@link #onStartTask(TaskDetails)} this method gets called only once for "recurring" tasks that are
- * scheduled to run in pre-defined intervals.
+ * scheduled to run in pre-defined intervals.
+ *
*
* @param taskDetails object containing details about this task
*/
void onScheduleTask(TaskDetails taskDetails);
/**
- * This method gets called whenever a task is started.
- *
- * For recurring tasks it is called multiple times.
+ *
+ * This method gets called whenever a task is started.
+ *
+ *
+ * For recurring tasks it is called multiple times.
+ *
*
* @param taskDetails object containing details about this task
*/
void onStartTask(TaskDetails taskDetails);
/**
- * This method gets called whenever a task is finished.
- *
- * For recurring tasks it is called multiple times.
+ *
+ * This method gets called whenever a task is finished.
+ *
+ *
+ * For recurring tasks it is called multiple times.
+ *
*
* @param taskDetails object containing details about this task
* @param error {@link Exception} that caused the task to complete
@@ -38,20 +50,26 @@ public interface ReportingExecutorService {
void onFinishTask(TaskDetails taskDetails, Throwable error);
/**
+ *
* This method gets called whenever a task is cancelled through its {@link java.util.concurrent.Future} or through
- * the shutdown methods of the {@link java.util.concurrent.ExecutorService}.
- *
- * It only gets called once for every task.
+ * the shutdown methods of the {@link java.util.concurrent.ExecutorService}.
+ *
+ *
+ * It only gets called once for every task.
+ *
*
* @param taskDetails object containing details about this task
*/
void onCancelTask(TaskDetails taskDetails);
/**
- * This method gets called whenever a task completes.
- *
+ *
+ * This method gets called whenever a task completes.
+ *
+ *
* This can be through either raising an exception, cancelling from the outside or by simply terminating in a normal
- * manner. For recurring tasks this only gets called once.
+ * manner. For recurring tasks this only gets called once.
+ *
*
* @param taskDetails object containing details about this task
* @param error {@link Exception} that caused the task to complete
diff --git a/src/main/java/com/iota/iri/utils/thread/SilentScheduledExecutorService.java b/src/main/java/com/iota/iri/utils/thread/SilentScheduledExecutorService.java
index 8d29e044f1..0ad4dc8308 100644
--- a/src/main/java/com/iota/iri/utils/thread/SilentScheduledExecutorService.java
+++ b/src/main/java/com/iota/iri/utils/thread/SilentScheduledExecutorService.java
@@ -5,17 +5,20 @@
import java.util.concurrent.*;
/**
+ *
* This interface extends the {@link ScheduledExecutorService} by providing additional methods to enqueue tasks without
- * throwing a {@link RejectedExecutionException} exception.
- *
+ * throwing a {@link RejectedExecutionException} exception.
+ *
+ *
* This can be useful when preventing additional tasks to run is no error but an intended design decision in the
* implementing class. In these cases raising an exception and catching it would cause too much unnecessary overhead
- * (using {@link Exception}s for control flow is an anti pattern).
+ * (using {@link Exception}s for control flow is an anti pattern).
+ *
*/
public interface SilentScheduledExecutorService extends ScheduledExecutorService {
/**
* Does the same as {@link ScheduledExecutorService#schedule(Runnable, long, TimeUnit)} but returns {@code null}
- * instead of throwing a {@link RejectedExecutionException} if the task cannot be scheduled for execution.
+ * instead of throwing a {@link RejectedExecutionException} if the task cannot be scheduled for execution.
*
* @param command the task to execute
* @param delay the time from now to delay execution
@@ -29,7 +32,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#schedule(Callable, long, TimeUnit)} but returns {@code null}
* instead of throwing a {@link java.util.concurrent.RejectedExecutionException} if the task cannot be scheduled for
- * execution.
+ * execution.
*
* @param callable the function to execute
* @param delay the time from now to delay execution
@@ -44,7 +47,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit)} but returns
* {@code null} instead of throwing a {@link RejectedExecutionException} if the task cannot be scheduled for
- * execution.
+ * execution.
*
* @param command the task to execute
* @param initialDelay the time to delay first execution
@@ -60,7 +63,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as
* {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)} but returns {@code null}
- * instead of throwing a {@link RejectedExecutionException} if the task cannot be scheduled for execution.
+ * instead of throwing a {@link RejectedExecutionException} if the task cannot be scheduled for execution.
*
* @param command the task to execute
* @param initialDelay the time to delay first execution
@@ -75,7 +78,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#submit(Callable)} but returns {@code null} instead of throwing a
- * {@link RejectedExecutionException} if the task cannot be scheduled for execution.
+ * {@link RejectedExecutionException} if the task cannot be scheduled for execution.
*
* @param task the task to submit
* @param the type of the task's result
@@ -86,7 +89,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#submit(Runnable)} but returns {@code null} instead of throwing a
- * {@link RejectedExecutionException} if the task cannot be scheduled for execution.
+ * {@link RejectedExecutionException} if the task cannot be scheduled for execution.
*
* @param task the task to submit
* @return a Future representing pending completion of the task / {@code null} if the task cannot be scheduled for
@@ -97,7 +100,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#submit(Runnable, Object)} but returns {@code null} instead of
- * throwing a {@link RejectedExecutionException} if the task cannot be scheduled for execution.
+ * throwing a {@link RejectedExecutionException} if the task cannot be scheduled for execution.
*
* @param task the task to submit
* @param result the result to return
@@ -110,7 +113,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#invokeAll(Collection)} but returns {@code null} instead of
- * throwing a {@link RejectedExecutionException} if any task cannot be scheduled for execution.
+ * throwing a {@link RejectedExecutionException} if any task cannot be scheduled for execution.
*
* @param tasks the collection of tasks
* @param the type of the values returned from the tasks
@@ -124,7 +127,7 @@ public interface SilentScheduledExecutorService extends ScheduledExecutorService
/**
* Does the same as {@link ScheduledExecutorService#invokeAll(Collection, long, TimeUnit)} but returns {@code null}
- * instead of throwing a {@link RejectedExecutionException} if any task cannot be scheduled for execution.
+ * instead of throwing a {@link RejectedExecutionException} if any task cannot be scheduled for execution.
*
* @param tasks the collection of tasks
* @param timeout the maximum time to wait
@@ -142,7 +145,7 @@ List> silentInvokeAll(Collection extends Callable> tasks, lon
/**
* Does the same as {@link ScheduledExecutorService#invokeAny(Collection)} but returns {@code null} instead of
- * throwing a {@link RejectedExecutionException} if tasks cannot be scheduled for execution.
+ * throwing a {@link RejectedExecutionException} if tasks cannot be scheduled for execution.
*
* @param tasks the collection of tasks
* @param the type of the values returned from the tasks
@@ -156,7 +159,7 @@ List> silentInvokeAll(Collection extends Callable> tasks, lon
/**
* Does the same as {@link ScheduledExecutorService#invokeAny(Collection, long, TimeUnit)} but returns {@code null}
- * instead of throwing a {@link RejectedExecutionException} if tasks cannot be scheduled for execution.
+ * instead of throwing a {@link RejectedExecutionException} if tasks cannot be scheduled for execution.
*
* @param tasks the collection of tasks
* @param timeout the maximum time to wait
@@ -172,7 +175,7 @@ List> silentInvokeAll(Collection extends Callable> tasks, lon
/**
* Does the same as {@link ScheduledExecutorService#execute(Runnable)} but doesn't throw a
- * {@link RejectedExecutionException} if this task cannot be accepted for execution.
+ * {@link RejectedExecutionException} if this task cannot be accepted for execution.
*
* @param command the runnable task
* @throws NullPointerException if command is null
diff --git a/src/main/java/com/iota/iri/utils/thread/TaskDetails.java b/src/main/java/com/iota/iri/utils/thread/TaskDetails.java
index 3fe30de012..e6c72f9ca7 100644
--- a/src/main/java/com/iota/iri/utils/thread/TaskDetails.java
+++ b/src/main/java/com/iota/iri/utils/thread/TaskDetails.java
@@ -5,58 +5,64 @@
import java.util.concurrent.atomic.AtomicInteger;
/**
+ *
* This class represents a container for the metadata of a task that was scheduled through an
- * {@link java.util.concurrent.ExecutorService} that implements the {@link ReportingExecutorService} interface.
- *
+ * {@link java.util.concurrent.ExecutorService} that implements the {@link ReportingExecutorService} interface.
+ *
+ *
* It can for example be used to show detailed log messages or even implement more sophisticated features like the
- * {@link BoundedScheduledExecutorService}.
+ * {@link BoundedScheduledExecutorService}.
+ *
*/
public class TaskDetails {
/**
- * Holds the name of the {@link Thread} that created the task.
+ * Holds the name of the {@link Thread} that created the task.
*/
private final String threadName;
/**
* Holds a thread-safe flag that indicates if the task is currently scheduled for execution (false if running or
- * done already).
+ * done already).
*/
private final AtomicBoolean scheduledForExecution;
/**
- * Holds a thread-safe counter for the amount of times this task was executed.
+ * Holds a thread-safe counter for the amount of times this task was executed.
*/
private final AtomicInteger executionCount;
/**
* Holds the initial delay that was provided when scheduling the task (or {@code null} if the task was set to run
- * immediately).
+ * immediately).
*/
private Long delay = null;
/**
- * Holds the interval in which the task is repeated (or {@code null} for non-recurring tasks).
+ * Holds the interval in which the task is repeated (or {@code null} for non-recurring tasks).
*/
private Long interval = null;
/**
* Holds the timeout that a task can take to terminate before it gets interrupted (or {@code null} if none was
- * provided).
+ * provided).
*/
private Long timeout = null;
/**
* Holds the time unit that the other values are denominated in (or {@code null} if no time based values are
- * provided).
+ * provided).
*/
private TimeUnit timeUnit = null;
/**
+ *
* Creates a container for the metadata of a task that was scheduled through an
- * {@link java.util.concurrent.ExecutorService}.
- *
+ * {@link java.util.concurrent.ExecutorService}.
+ *
+ *
* It is automatically initiated with the calling {@link Thread} name, the {@link #scheduledForExecution} flag being
- * set to {@code true} and the {@link #executionCount} being set to 0.
+ * set to {@code true} and the {@link #executionCount} being set to 0.
+ *
*/
public TaskDetails() {
this.threadName = Thread.currentThread().getName();
@@ -65,7 +71,7 @@ public TaskDetails() {
}
/**
- * Getter for the internal {@link #threadName} property.
+ * Getter for the internal {@link #threadName} property.
*
* @return name of the {@link Thread} that scheduled the task.
*/
@@ -74,10 +80,11 @@ public String getThreadName() {
}
/**
- * Getter for the internal {@link #scheduledForExecution} property.
- *
+ * Getter for the internal {@link #scheduledForExecution} property.
+ *
* Note: There is no setter for this property because it returns a mutable object that is not supposed be
- * overwritten.
+ * overwritten.
+ *
*
* @return a thread-safe flag that indicates if the task is currently scheduled for execution
*/
@@ -86,10 +93,11 @@ public AtomicBoolean getScheduledForExecution() {
}
/**
- * Getter for the internal {@link #executionCount} property.
- *
+ * Getter for the internal {@link #executionCount} property.
+ *
* Note: There is no setter for this property because it returns a mutable object that is not supposed be
- * overwritten.
+ * overwritten.
+ *
*
* @return a thread-safe counter for the amount of times this task was executed
*/
@@ -98,7 +106,7 @@ public AtomicInteger getExecutionCount() {
}
/**
- * Setter for the internal {@link #delay} property.
+ * Setter for the internal {@link #delay} property.
*
* @param delay the initial delay that was provided when scheduling the task
* @return the instance of TaskDetails itself to allow the chaining of calls
@@ -110,7 +118,7 @@ public TaskDetails setDelay(Long delay) {
}
/**
- * Getter for the internal {@link #delay} property.
+ * Getter for the internal {@link #delay} property.
*
* @return the initial delay that was provided when scheduling the task (or {@code null} if the task was set to run
* immediately)
@@ -120,7 +128,7 @@ public Long getDelay() {
}
/**
- * Setter for the internal {@link #interval} property.
+ * Setter for the internal {@link #interval} property.
*
* @param interval the interval in which the task is repeated (or {@code null} for non-recurring tasks)
* @return the instance of TaskDetails itself to allow the chaining of calls
@@ -132,7 +140,7 @@ public TaskDetails setInterval(Long interval) {
}
/**
- * Getter for the internal {@link #interval} property.
+ * Getter for the internal {@link #interval} property.
*
* @return the interval in which the task is repeated (or {@code null} for non-recurring tasks)
*/
@@ -141,7 +149,7 @@ public Long getInterval() {
}
/**
- * Setter for the internal {@link #timeout} property.
+ * Setter for the internal {@link #timeout} property.
*
* @param timeout the timeout that a task can take to terminate before it gets interrupted (or {@code null} if none
* was provided)
@@ -154,7 +162,7 @@ public TaskDetails setTimeout(Long timeout) {
}
/**
- * Getter for the internal {@link #timeout} property.
+ * Getter for the internal {@link #timeout} property.
*
* @return the timeout that a task can take to terminate before it gets interrupted (or {@code null} if none was
* provided)
@@ -164,7 +172,7 @@ public Long getTimeout() {
}
/**
- * Setter for the internal {@link #timeUnit} property.
+ * Setter for the internal {@link #timeUnit} property.
*
* @param timeUnit the time unit that the other values are denominated in (or {@code null} if no time based values
* are provided)
@@ -177,7 +185,7 @@ public TaskDetails setTimeUnit(TimeUnit timeUnit) {
}
/**
- * Getter for the internal {@link #timeUnit} property.
+ * Getter for the internal {@link #timeUnit} property.
*
* @return the time unit that the other values are denominated in (or {@code null} if no time based values are
* provided)
diff --git a/src/main/java/com/iota/iri/zmq/MessageQ.java b/src/main/java/com/iota/iri/zmq/MessageQ.java
index 7f5d4e35c9..eacbd391d0 100644
--- a/src/main/java/com/iota/iri/zmq/MessageQ.java
+++ b/src/main/java/com/iota/iri/zmq/MessageQ.java
@@ -31,39 +31,31 @@
* For a complete list and detailed topic specification please refer to the README.md.
*
*/
-public class MessageQ {
+class MessageQ {
private final static Logger LOG = LoggerFactory.getLogger(MessageQ.class);
private final ZMQ.Context context;
private final ZMQ.Socket publisher;
- private boolean enabled = false;
private final ExecutorService publisherService = Executors.newSingleThreadExecutor();
public static MessageQ createWith(ZMQConfig config) {
- return new MessageQ(config.getZmqPort(), config.getZmqIpc(), config.getZmqThreads(), config.isZmqEnabled());
+ return new MessageQ(config);
}
/**
* Creates and starts a ZMQ publisher.
*
- * @param port port the publisher will be bound to
- * @param ipc IPC socket the publisher will be bound to
- * @param nthreads number of threads used by the ZMQ publisher
- * @param enabled boolean enable flag; by default the publisher will not be started
+ * @param config {@link ZMQConfig} that should be used.
*/
- private MessageQ(int port, String ipc, int nthreads, boolean enabled) {
- if (enabled) {
- context = ZMQ.context(nthreads);
- publisher = context.socket(ZMQ.PUB);
- publisher.bind(String.format("tcp://*:%d", port));
- if (ipc != null) {
- publisher.bind(ipc);
- }
- this.enabled = true;
- } else {
- context = null;
- publisher = null;
+ private MessageQ(ZMQConfig config) {
+ context = ZMQ.context(config.getZmqThreads());
+ publisher = context.socket(ZMQ.PUB);
+ if (config.isZmqEnableTcp()) {
+ publisher.bind(String.format("tcp://*:%d", config.getZmqPort()));
+ }
+ if (config.isZmqEnableIpc()) {
+ publisher.bind(config.getZmqIpc());
}
}
@@ -74,10 +66,8 @@ private MessageQ(int port, String ipc, int nthreads, boolean enabled) {
* @param objects arguments referenced by the message body, similar to a format string
*/
public void publish(String message, Object... objects) {
- if (enabled) {
- String toSend = String.format(message, objects);
- publisherService.submit(() -> publisher.send(toSend));
- }
+ String toSend = String.format(message, objects);
+ publisherService.submit(() -> publisher.send(toSend));
}
/**
diff --git a/src/main/java/com/iota/iri/zmq/MessageQueueProvider.java b/src/main/java/com/iota/iri/zmq/MessageQueueProvider.java
new file mode 100644
index 0000000000..065b92a7c7
--- /dev/null
+++ b/src/main/java/com/iota/iri/zmq/MessageQueueProvider.java
@@ -0,0 +1,35 @@
+package com.iota.iri.zmq;
+
+import com.iota.iri.model.Hash;
+import com.iota.iri.model.persistables.Transaction;
+import com.iota.iri.storage.Indexable;
+import com.iota.iri.storage.Persistable;
+
+/**
+ * Publish messages to the MessageQueue.
+ */
+public interface MessageQueueProvider {
+ /**
+ * Publishes the message to the MessageQueue.
+ *
+ * @param message that can be formatted by {@link String#format(String, Object...)}
+ * @param objects that should replace the placeholder in message.
+ * @see String#format(String, Object...)
+ */
+ void publish(String message, Object... objects);
+
+ /**
+ * Publishes the transaction details to the MessageQueue.
+ *
+ * @param model with Transaction details send to the MessageQueue.
+ * @param index {@link Hash} identifier of the {@link Transaction} set
+ * @param item identifying the purpose of the update
+ * @return true when message was send to the MessageQueue
+ */
+ boolean publishTransaction(Persistable model, Indexable index, String item);
+
+ /**
+ * Shutdown the MessageQueue.
+ */
+ void shutdown();
+}
diff --git a/src/main/java/com/iota/iri/storage/ZmqPublishProvider.java b/src/main/java/com/iota/iri/zmq/ZmqMessageQueueProvider.java
similarity index 52%
rename from src/main/java/com/iota/iri/storage/ZmqPublishProvider.java
rename to src/main/java/com/iota/iri/zmq/ZmqMessageQueueProvider.java
index 9425805933..289bce9a6a 100644
--- a/src/main/java/com/iota/iri/storage/ZmqPublishProvider.java
+++ b/src/main/java/com/iota/iri/zmq/ZmqMessageQueueProvider.java
@@ -1,55 +1,34 @@
-package com.iota.iri.storage;
+package com.iota.iri.zmq;
+import com.iota.iri.conf.ZMQConfig;
import com.iota.iri.controllers.TransactionViewModel;
import com.iota.iri.model.Hash;
import com.iota.iri.model.persistables.Transaction;
+import com.iota.iri.storage.Indexable;
+import com.iota.iri.storage.Persistable;
import com.iota.iri.utils.Converter;
-import com.iota.iri.utils.Pair;
-import com.iota.iri.zmq.MessageQ;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ZmqPublishProvider implements PersistenceProvider {
+/**
+ * Use zeromq to create a MessageQueue that publishes messages.
+ */
+public class ZmqMessageQueueProvider implements MessageQueueProvider {
- private static final Logger log = LoggerFactory.getLogger(ZmqPublishProvider.class);
+ private static final Logger log = LoggerFactory.getLogger(ZmqMessageQueueProvider.class);
private final MessageQ messageQ;
- public ZmqPublishProvider( MessageQ messageQ ) {
- this.messageQ = messageQ;
- }
-
- @Override
- public void init() throws Exception {
-
- }
-
- @Override
- public boolean isAvailable() {
- return false;
- }
-
- @Override
- public void shutdown() {
-
- }
-
- @Override
- public boolean save(Persistable model, Indexable index) throws Exception {
- return false;
- }
-
- @Override
- public void delete(Class> model, Indexable index) throws Exception {
-
+ /**
+ * Factory method to create a new ZmqMessageQueue with the given configuration.
+ *
+ * @param configuration with the zmq properties used to create MessageQueue
+ */
+ public ZmqMessageQueueProvider(ZMQConfig configuration) {
+ this.messageQ = MessageQ.createWith(configuration);
}
@Override
- public boolean update(Persistable model, Indexable index, String item) throws Exception {
+ public boolean publishTransaction(Persistable model, Indexable index, String item) {
if(!(model instanceof Transaction)) {
return false;
}
@@ -74,7 +53,7 @@ private void publishTx(TransactionViewModel transactionViewModel) {
txStringBuilder.append(transactionViewModel.getHash()); txStringBuilder.append(" ");
txStringBuilder.append(transactionViewModel.getAddressHash()); txStringBuilder.append(" ");
txStringBuilder.append(String.valueOf(transactionViewModel.value())); txStringBuilder.append(" ");
- txStringBuilder.append(transactionViewModel.getObsoleteTagValue().toString().substring(0,27)); txStringBuilder.append(" ");
+ txStringBuilder.append(transactionViewModel.getObsoleteTagValue().toString(), 0, 27); txStringBuilder.append(" ");
txStringBuilder.append(String.valueOf(transactionViewModel.getTimestamp())); txStringBuilder.append(" ");
txStringBuilder.append(String.valueOf(transactionViewModel.getCurrentIndex())); txStringBuilder.append(" ");
txStringBuilder.append(String.valueOf(transactionViewModel.lastIndex())); txStringBuilder.append(" ");
@@ -82,7 +61,7 @@ private void publishTx(TransactionViewModel transactionViewModel) {
txStringBuilder.append(transactionViewModel.getTrunkTransactionHash()); txStringBuilder.append(" ");
txStringBuilder.append(transactionViewModel.getBranchTransactionHash()); txStringBuilder.append(" ");
txStringBuilder.append(String.valueOf(transactionViewModel.getArrivalTime())); txStringBuilder.append(" ");
- txStringBuilder.append(transactionViewModel.getTagValue().toString().substring(0,27));
+ txStringBuilder.append(transactionViewModel.getTagValue().toString(), 0, 27);
messageQ.publish(txStringBuilder.toString());
} catch (Exception e) {
@@ -106,83 +85,20 @@ private void publishTxTrytes(TransactionViewModel transactionViewModel) {
}
}
+ /**
+ * Publishes the message to the MessageQueue.
+ *
+ * @param message that can be formatted by {@link String#format(String, Object...)}
+ * @param objects that should replace the placeholder in message.
+ * @see String#format(String, Object...)
+ */
@Override
- public boolean exists(Class> model, Indexable key) throws Exception {
- return false;
+ public void publish(String message, Object... objects) {
+ this.messageQ.publish(message, objects);
}
@Override
- public Pair latest(Class> model, Class> indexModel) throws Exception {
- return null;
- }
-
- @Override
- public Set keysWithMissingReferences(Class> modelClass, Class> otherClass) throws Exception {
- return null;
- }
-
- @Override
- public Persistable get(Class> model, Indexable index) throws Exception {
- return null;
- }
-
- @Override
- public boolean mayExist(Class> model, Indexable index) throws Exception {
- return false;
- }
-
- @Override
- public long count(Class> model) throws Exception {
- return 0;
- }
-
- @Override
- public Set keysStartingWith(Class> modelClass, byte[] value) {
- return null;
- }
-
- @Override
- public Persistable seek(Class> model, byte[] key) throws Exception {
- return null;
- }
-
- @Override
- public Pair next(Class> model, Indexable index) throws Exception {
- return null;
- }
-
- @Override
- public Pair previous(Class> model, Indexable index) throws Exception {
- return null;
- }
-
- @Override
- public Pair first(Class> model, Class> indexModel) throws Exception {
- return null;
- }
-
- @Override
- public boolean saveBatch(List> models) throws Exception {
- return false;
- }
-
- @Override
- public void deleteBatch(Collection>> models) throws Exception {
-
- }
-
- @Override
- public void clear(Class> column) throws Exception {
-
- }
-
- @Override
- public void clearMetadata(Class> column) throws Exception {
-
- }
-
- @Override
- public List loadAllKeysFromTable(Class extends Persistable> model) {
- return null;
+ public void shutdown() {
+ this.messageQ.shutdown();
}
}
\ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index 0ce840ac49..85a08b9c40 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -24,7 +24,7 @@
DENY
- %d{MM/dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+ %d{MM/dd HH:mm:ss.SSS} [%thread] %-5level %logger{0}:%L - %msg%n
@@ -37,7 +37,7 @@
DENY
- %d{MM/dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+ %d{MM/dd HH:mm:ss.SSS} [%thread] %-5level %logger{0}:%L - %msg%n
@@ -46,4 +46,4 @@
-
\ No newline at end of file
+
diff --git a/src/test/java/com/iota/iri/IXITest.java b/src/test/java/com/iota/iri/IXITest.java
index 0efa3070a4..b8a4de59fc 100644
--- a/src/test/java/com/iota/iri/IXITest.java
+++ b/src/test/java/com/iota/iri/IXITest.java
@@ -1,5 +1,6 @@
package com.iota.iri;
+import com.iota.iri.service.CallableRequest;
import com.iota.iri.service.dto.AbstractResponse;
import com.iota.iri.service.dto.ErrorResponse;
import org.hamcrest.CoreMatchers;
@@ -8,6 +9,10 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -27,6 +32,12 @@ public static void setUp() throws Exception {
ixiDir.create();
ixi = new IXI();
ixi.init(ixiDir.getRoot().getAbsolutePath());
+
+ Field ixiApiField = ixi.getClass().getDeclaredField("ixiAPI");
+ ixiApiField.setAccessible(true);
+ Map>> ixiAPI =
+ (Map>>) ixiApiField.get(ixi);
+ ixiAPI.put("IXI", new HashMap<>());
}
/**
@@ -70,7 +81,7 @@ public void processCommandEmpty() {
}
/**
- * If an does not match the command pattern, expect an unknown command error message.
+ * If the given command does not exist, expect an unknown command error message.
*/
@Test
public void processCommandUnknown() {
@@ -79,4 +90,13 @@ public void processCommandUnknown() {
assertTrue("Wrong error message returned in response", response.toString().contains("Command [unknown] is unknown"));
}
-}
\ No newline at end of file
+ /**
+ * If an IXI module does not have the given command, expect an unknown command error message.
+ */
+ @Test
+ public void processIXICommandUnknown() {
+ AbstractResponse response = ixi.processCommand("IXI.unknown", null);
+ assertThat("Wrong type of response", response, CoreMatchers.instanceOf(ErrorResponse.class));
+ assertTrue("Wrong error message returned in response", response.toString().contains("Command [IXI.unknown] is unknown"));
+ }
+}
diff --git a/src/test/java/com/iota/iri/TangleMockUtils.java b/src/test/java/com/iota/iri/TangleMockUtils.java
index 1bee23d7fb..49637ab492 100644
--- a/src/test/java/com/iota/iri/TangleMockUtils.java
+++ b/src/test/java/com/iota/iri/TangleMockUtils.java
@@ -17,25 +17,31 @@
import java.util.*;
/**
- * Contains utilities that help to mock the retrieval of database entries from the tangle.
- *
+ * Contains utilities that help to mock the retrieval of database entries from the tangle.
+ *
+ *
* Mocking the tangle allows us to write unit tests that perform much faster than spinning up a new database for every
- * test.
+ * test.
+ *
*/
public class TangleMockUtils {
//region [mockMilestone] ///////////////////////////////////////////////////////////////////////////////////////////
/**
- * Registers a {@link Milestone} in the mocked tangle that can consequently be accessed by the tested classes.
- *
+ *
+ * Registers a {@link Milestone} in the mocked tangle that can consequently be accessed by the tested classes.
+ *
+ *
* It first creates the {@link Milestone} with the given details and then mocks the retrieval methods of the tangle
* to return this object. In addition to mocking the specific retrieval method for the given hash, we also mock the
* retrieval method for the "latest" entity so the mocked tangle returns the elements in the order that they were
- * mocked / created (which allows the mocked tangle to behave just like a normal one).
- *
+ * mocked / created (which allows the mocked tangle to behave just like a normal one).
+ *
+ *
* Note: We return the mocked object which allows us to set additional fields or modify it after "injecting" it into
- * the mocked tangle.
- *
+ * the mocked tangle.
+ *
+ *
* @param tangle mocked tangle object that shall retrieve a milestone object when being queried for it
* @param hash transaction hash of the milestone
* @param index milestone index of the milestone
@@ -72,7 +78,7 @@ public static List mockValidBundle(Tangle tangle,
address = TransactionTestUtils.nextWord(address);
Converter.trits(address, trits, TransactionViewModel.ADDRESS_TRINARY_OFFSET);
if (tx != null) {
- TransactionTestUtils.getTransactionTritsWithTrunkAndBranch(trits, tx.getHash(), Hash.NULL_HASH);
+ TransactionTestUtils.getTransactionTritsWithTrunkAndBranchTrits(trits, tx.getHash(), Hash.NULL_HASH);
}
TransactionTestUtils.setLastIndex(trits, lastIndex);
TransactionTestUtils.setCurrentIndex(trits, currentIndex--);
@@ -111,7 +117,7 @@ public static List mockValidBundle(Tangle tangle,
* This transaction is returned when the hash is asked to load in the tangle object
*
* @param tangle mocked tangle object that shall retrieve a milestone object when being queried for it
- * @param hash
+ * @param hash transaction hash
* @return The newly created (empty) transaction
*/
public static Transaction mockTransaction(Tangle tangle, Hash hash) {
diff --git a/src/test/java/com/iota/iri/TransactionTestUtils.java b/src/test/java/com/iota/iri/TransactionTestUtils.java
index c9200f4531..fc5b148f08 100644
--- a/src/test/java/com/iota/iri/TransactionTestUtils.java
+++ b/src/test/java/com/iota/iri/TransactionTestUtils.java
@@ -8,7 +8,6 @@
import com.iota.iri.model.persistables.Transaction;
import com.iota.iri.utils.Converter;
-import java.util.Arrays;
import java.util.Random;
import org.apache.commons.lang3.StringUtils;
@@ -26,7 +25,13 @@ public class TransactionTestUtils {
public static void setCurrentIndex(TransactionViewModel tx, long currentIndex) {
setCurrentIndex(tx.trits(), currentIndex);
}
-
+
+ /**
+ * Updates the transaction index trits.
+ *
+ * @param trits The trits to update
+ * @param currentIndex The new index to set the transaction to
+ */
public static void setCurrentIndex(byte[] trits, long currentIndex) {
Converter.copyTrits(currentIndex, trits, TransactionViewModel.CURRENT_INDEX_TRINARY_OFFSET,
TransactionViewModel.CURRENT_INDEX_TRINARY_SIZE);
@@ -42,21 +47,27 @@ public static void setLastIndex(TransactionViewModel tx, long lastIndex) {
setLastIndex(tx.trits(), lastIndex);
}
+ /**
+ * Updates the last transaction index trits.
+ *
+ * @param trits The trits to update
+ * @param currentIndex The new last index to set the transaction to
+ */
public static void setLastIndex(byte[] trits, long lastIndex) {
Converter.copyTrits(lastIndex, trits, TransactionViewModel.LAST_INDEX_TRINARY_OFFSET,
TransactionViewModel.LAST_INDEX_TRINARY_SIZE);
}
/**
- * Generates a random transaction with a random hash.
+ * Generates a transaction with a hash.
* Transaction last and current index are set to the index provided.
*
* @param index The index to set the transaction to
- * @return A random transaction which is located on the end of its (nonexistent) bundle
+ * @return A transaction which is located on the end of its (nonexistent) bundle
*/
public static TransactionViewModel createBundleHead(int index) {
- TransactionViewModel tx = new TransactionViewModel(getRandomTransactionTrits(), getRandomTransactionHash());
+ TransactionViewModel tx = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
setLastIndex(tx, index);
setCurrentIndex(tx, index);
return tx;
@@ -71,14 +82,14 @@ public static TransactionViewModel createBundleHead(int index) {
* @return A transaction in the same bundle as trunk, with its index 1 below trunk index
*/
public static TransactionViewModel createTransactionWithTrunkBundleHash(TransactionViewModel trunkTx, Hash branchHash) {
- byte[] txTrits = getTransactionWithTrunkAndBranch(trunkTx.getHash(), branchHash);
+ byte[] txTrits = getTransactionTritsWithTrunkAndBranch(trunkTx.getHash(), branchHash);
setCurrentIndex(txTrits, trunkTx.getCurrentIndex() - 1);
setLastIndex(txTrits, trunkTx.lastIndex());
System.arraycopy(trunkTx.trits(), TransactionViewModel.BUNDLE_TRINARY_OFFSET, txTrits,
TransactionViewModel.BUNDLE_TRINARY_OFFSET, TransactionViewModel.BUNDLE_TRINARY_SIZE);
TransactionViewModel tx = new TransactionViewModel(
txTrits,
- getRandomTransactionHash());
+ getTransactionHash());
return tx;
}
@@ -97,6 +108,13 @@ public static TransactionViewModel createTransactionWithTrytes(String trytes) {
return createTransactionFromTrits(trits);
}
+ /**
+ * Creates a {@link TransactionViewModel} from the supplied trits.
+ * Trits are not checked for size and content.
+ *
+ * @param trits The transaction trits
+ * @return The transaction
+ */
public static TransactionViewModel createTransactionFromTrits(byte[] trits) {
return new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
}
@@ -113,7 +131,7 @@ public static TransactionViewModel createTransactionFromTrits(byte[] trits) {
*/
public static TransactionViewModel createTransactionWithTrunkAndBranch(String trytes, Hash trunk, Hash branch) {
byte[] trits = createTransactionWithTrunkAndBranchTrits(trytes, trunk, branch);
- return new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
+ return createTransactionFromTrits(trits);
}
/**
@@ -128,19 +146,20 @@ public static TransactionViewModel createTransactionWithTrunkAndBranch(String tr
public static byte[] createTransactionWithTrunkAndBranchTrits(String trytes, Hash trunk, Hash branch) {
String expandedTrytes = expandTrytes(trytes);
byte[] trits = Converter.allocatingTritsFromTrytes(expandedTrytes);
- return getTransactionTritsWithTrunkAndBranch(trits, trunk, branch);
+ return getTransactionTritsWithTrunkAndBranchTrits(trits, trunk, branch);
}
/**
- * Generates random transaction trits with the provided trytes, trunk and hash.
+ * Generates transaction trits with the provided trytes, trunk and hash.
+ * No validation is done on the resulting trits, so fields are not valid except trunk and branch.
*
* @param trunk The trunk transaction hash
* @param branch The branch transaction hash
* @return The transaction trits
*/
- public static byte[] getTransactionWithTrunkAndBranch(Hash trunk, Hash branch) {
- byte[] trits = new byte[TransactionViewModel.TRINARY_SIZE];
- return getTransactionTritsWithTrunkAndBranch(trits, trunk, branch);
+ public static byte[] getTransactionTritsWithTrunkAndBranch(Hash trunk, Hash branch) {
+ byte[] trits = getTransactionTrits();
+ return getTransactionTritsWithTrunkAndBranchTrits(trits, trunk, branch);
}
/**
@@ -150,7 +169,7 @@ public static byte[] getTransactionWithTrunkAndBranch(Hash trunk, Hash branch) {
* @param branch The branch transaction hash
* @return trits The transaction trits
*/
- public static byte[] getTransactionTritsWithTrunkAndBranch(byte[] trits, Hash trunk, Hash branch) {
+ public static byte[] getTransactionTritsWithTrunkAndBranchTrits(byte[] trits, Hash trunk, Hash branch) {
System.arraycopy(trunk.trits(), 0, trits, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_OFFSET,
TransactionViewModel.TRUNK_TRANSACTION_TRINARY_SIZE);
System.arraycopy(branch.trits(), 0, trits, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_OFFSET,
@@ -184,22 +203,22 @@ else if (chars[i] != 'Z') {
}
/**
- * Generates a random transaction.
+ * Generates a transaction.
*
* @return The transaction
*/
- public static Transaction getRandomTransaction() {
- byte[] trits = getRandomTransactionTrits();
+ public static Transaction getTransaction() {
+ byte[] trits = getTransactionTrits();
return buildTransaction(trits);
}
/**
- * Generates random trits for a transaction.
+ * Generates trits for a transaction.
*
* @return The transaction trits
*/
- public static byte[] getRandomTransactionTrits() {
- return getRandomTrits(TransactionViewModel.TRINARY_SIZE);
+ public static byte[] getTransactionTrits() {
+ return getTrits(TransactionViewModel.TRINARY_SIZE);
}
/**
@@ -209,34 +228,58 @@ public static byte[] getRandomTransactionTrits() {
*/
public static Transaction get9Transaction() {
byte[] trits = new byte[TransactionViewModel.TRINARY_SIZE];
- Arrays.fill(trits, (byte) 0);
+ for (int i = 0; i < trits.length; i++) {
+ trits[i] = 0;
+ }
return buildTransaction(trits);
}
+
+
+ /**
+ * Generates a transaction with trunk and hash.
+ *
+ * @param trunk The trunk transaction hash
+ * @param branch The branch transaction hash
+ * @return The transaction
+ */
+ public static Transaction createTransactionWithTrunkAndBranch(Hash trunk, Hash branch) {
+ byte[] trits = getTrits(TransactionViewModel.TRINARY_SIZE);
+ getTransactionTritsWithTrunkAndBranchTrits(trits, trunk, branch);
+ return buildTransaction(trits);
+ }
/**
- * Generates random trits for a transaction.
+ * Generates trits for a hash.
*
* @return The transaction hash
*/
- public static Hash getRandomTransactionHash() {
- byte[] out = getRandomTrits(Hash.SIZE_IN_TRITS);
+ public static Hash getTransactionHash() {
+ byte[] out = getTrits(Hash.SIZE_IN_TRITS);
return HashFactory.TRANSACTION.create(out);
}
/**
* Builds a transaction by transforming trits to bytes.
+ * Make sure the trits are in the correct order (TVM.trits())
*
* @param trits The trits to build the transaction
* @return The created transaction
*/
- public static Transaction buildTransaction(byte[] trits) {
- Transaction transaction = new Transaction();
+ public static Transaction buildTransaction(byte[] trits) {
+ TransactionViewModel TVM = new TransactionViewModel(trits, Hash.NULL_HASH);
+
+ //Getters obtain and load values from TVM trits ("lazy loading")
+ TVM.getAddressHash();
+ TVM.getTrunkTransactionHash();
+ TVM.getBranchTransactionHash();
+ TVM.getBundleHash();
+ TVM.getTagValue();
+ TVM.getObsoleteTagValue();
+ TVM.setAttachmentData();
+ TVM.setMetadata();
- transaction.bytes = Converter.allocateBytesForTrits(trits.length);
- Converter.bytes(trits, 0, transaction.bytes, 0, trits.length);
- transaction.readMetadata( transaction.bytes);
- return transaction;
+ return TVM.getTransaction();
}
/**
@@ -250,12 +293,13 @@ private static String expandTrytes(String trytes) {
}
/**
- * Generates random trits of specified size.
+ * Generates 'random' trits of specified size.
+ * Not truly random as we always use the same seed.
*
* @param size the amount of trits to generate
* @return The trits
*/
- private static byte[] getRandomTrits(int size) {
+ private static byte[] getTrits(int size) {
byte[] out = new byte[size];
for(int i = 0; i < out.length; i++) {
diff --git a/src/test/java/com/iota/iri/TransactionValidatorTest.java b/src/test/java/com/iota/iri/TransactionValidatorTest.java
index f70c29d516..1ee6f751f6 100644
--- a/src/test/java/com/iota/iri/TransactionValidatorTest.java
+++ b/src/test/java/com/iota/iri/TransactionValidatorTest.java
@@ -11,12 +11,10 @@
import com.iota.iri.storage.Tangle;
import com.iota.iri.storage.rocksDB.RocksDBPersistenceProvider;
import com.iota.iri.utils.Converter;
-import com.iota.iri.zmq.MessageQ;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.mockito.Mockito;
import static com.iota.iri.TransactionTestUtils.*;
import static org.junit.Assert.assertFalse;
@@ -42,8 +40,7 @@ public static void setUp() throws Exception {
dbFolder.getRoot().getAbsolutePath(), logFolder.getRoot().getAbsolutePath(),1000, Tangle.COLUMN_FAMILIES, Tangle.METADATA_COLUMN_FAMILY));
tangle.init();
TipsViewModel tipsViewModel = new TipsViewModel();
- MessageQ messageQ = Mockito.mock(MessageQ.class);
- TransactionRequester txRequester = new TransactionRequester(tangle, snapshotProvider, messageQ);
+ TransactionRequester txRequester = new TransactionRequester(tangle, snapshotProvider);
txValidator = new TransactionValidator(tangle, snapshotProvider, tipsViewModel, txRequester);
txValidator.setMwm(false, MAINNET_MWM);
}
@@ -66,20 +63,20 @@ public void testMinMwm() throws InterruptedException {
@Test
public void validateTrits() {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Converter.copyTrits(0, trits, 0, trits.length);
txValidator.validateTrits(trits, MAINNET_MWM);
}
@Test(expected = RuntimeException.class)
public void validateTritsWithInvalidMetadata() {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
txValidator.validateTrits(trits, MAINNET_MWM);
}
@Test
public void validateBytesWithNewCurl() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Converter.copyTrits(0, trits, 0, trits.length);
byte[] bytes = Converter.allocateBytesForTrits(trits.length);
Converter.bytes(trits, 0, bytes, 0, trits.length);
@@ -102,7 +99,7 @@ public void verifyTxIsNotSolid() throws Exception {
@Test
public void addSolidTransactionWithoutErrors() {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Converter.copyTrits(0, trits, 0, trits.length);
txValidator.addSolidTransaction(TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
}
@@ -116,7 +113,7 @@ private TransactionViewModel getTxWithBranchAndTrunk() throws Exception {
trunkTx = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
branchTx = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
- byte[] childTx = getRandomTransactionTrits();
+ byte[] childTx = getTransactionTrits();
System.arraycopy(trunkTx.getHash().trits(), 0, childTx, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_OFFSET, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_SIZE);
System.arraycopy(branchTx.getHash().trits(), 0, childTx, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_OFFSET, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_SIZE);
tx = new TransactionViewModel(childTx, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, childTx));
@@ -165,25 +162,25 @@ public void testTransactionPropagation() throws Exception {
@Test
public void testTransactionPropagationFailure() throws Exception {
- TransactionViewModel leftChildLeaf = new TransactionViewModel(getRandomTransactionTrits(), getRandomTransactionHash());
+ TransactionViewModel leftChildLeaf = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
leftChildLeaf.updateSolid(true);
leftChildLeaf.store(tangle, snapshotProvider.getInitialSnapshot());
- TransactionViewModel rightChildLeaf = new TransactionViewModel(getRandomTransactionTrits(), getRandomTransactionHash());
+ TransactionViewModel rightChildLeaf = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
rightChildLeaf.updateSolid(true);
rightChildLeaf.store(tangle, snapshotProvider.getInitialSnapshot());
- TransactionViewModel parent = new TransactionViewModel(getTransactionWithTrunkAndBranch(leftChildLeaf.getHash(),
- rightChildLeaf.getHash()), getRandomTransactionHash());
+ TransactionViewModel parent = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(leftChildLeaf.getHash(),
+ rightChildLeaf.getHash()), getTransactionHash());
parent.updateSolid(false);
parent.store(tangle, snapshotProvider.getInitialSnapshot());
- TransactionViewModel parentSibling = new TransactionViewModel(getRandomTransactionTrits(), getRandomTransactionHash());
+ TransactionViewModel parentSibling = new TransactionViewModel(getTransactionTrits(), getTransactionHash());
parentSibling.updateSolid(false);
parentSibling.store(tangle, snapshotProvider.getInitialSnapshot());
- TransactionViewModel grandParent = new TransactionViewModel(getTransactionWithTrunkAndBranch(parent.getHash(),
- parentSibling.getHash()), getRandomTransactionHash());
+ TransactionViewModel grandParent = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(parent.getHash(),
+ parentSibling.getHash()), getTransactionHash());
grandParent.updateSolid(false);
grandParent.store(tangle, snapshotProvider.getInitialSnapshot());
@@ -199,7 +196,7 @@ public void testTransactionPropagationFailure() throws Exception {
}
private TransactionViewModel getTxWithoutBranchAndTrunk() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
TransactionViewModel tx = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
tx.store(tangle, snapshotProvider.getInitialSnapshot());
diff --git a/src/test/java/com/iota/iri/benchmarks/BenchmarkRunner.java b/src/test/java/com/iota/iri/benchmarks/BenchmarkRunner.java
index a5954a2ad6..ef4a22af9c 100644
--- a/src/test/java/com/iota/iri/benchmarks/BenchmarkRunner.java
+++ b/src/test/java/com/iota/iri/benchmarks/BenchmarkRunner.java
@@ -28,4 +28,19 @@ public void launchDbBenchmarks() throws RunnerException {
//possible to do assertions over run results
new Runner(opts).run();
}
+
+ @Test
+ public void launchCryptoBenchmark() throws RunnerException {
+ Options opts = new OptionsBuilder()
+ .include(this.getClass().getPackage().getName() + ".crypto")
+ .mode(Mode.Throughput)
+ .timeUnit(TimeUnit.SECONDS)
+ .warmupIterations(5)
+ .forks(1)
+ .measurementIterations(10)
+ .shouldFailOnError(true)
+ .shouldDoGC(false)
+ .build();
+ new Runner(opts).run();
+ }
}
diff --git a/src/test/java/com/iota/iri/benchmarks/crypto/CurlBenchmark.java b/src/test/java/com/iota/iri/benchmarks/crypto/CurlBenchmark.java
new file mode 100644
index 0000000000..341ab3d23a
--- /dev/null
+++ b/src/test/java/com/iota/iri/benchmarks/crypto/CurlBenchmark.java
@@ -0,0 +1,62 @@
+package com.iota.iri.benchmarks.crypto;
+
+import com.iota.iri.crypto.Curl;
+import com.iota.iri.crypto.SpongeFactory;
+import com.iota.iri.utils.Converter;
+import com.iota.iri.utils.Pair;
+import org.junit.Assert;
+import org.openjdk.jmh.annotations.Benchmark;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class CurlBenchmark {
+ private final static String TRYTES = "RSWWSFXPQJUBJROQBRQZWZXZJWMUBVIVMHPPTYSNW9YQIQQF9RCSJJCVZG9ZWITXNCSBBDHEEKDRBHVTWCZ9SZOOZHVBPCQNPKTWFNZAWGCZ9QDIMKRVINMIRZBPKRKQAIPGOHBTHTGYXTBJLSURDSPEOJ9UKJECUKCCPVIQQHDUYKVKISCEIEGVOQWRBAYXWGSJUTEVG9RPQLPTKYCRAJ9YNCUMDVDYDQCKRJOAPXCSUDAJGETALJINHEVNAARIPONBWXUOQUFGNOCUSSLYWKOZMZUKLNITZIFXFWQAYVJCVMDTRSHORGNSTKX9Z9DLWNHZSMNOYTU9AUCGYBVIITEPEKIXBCOFCMQPBGXYJKSHPXNUKFTXIJVYRFILAVXEWTUICZCYYPCEHNTK9SLGVL9RLAMYTAEPONCBHDXSEQZOXO9XCFUCPPMKEBR9IEJGQOPPILHFXHMIULJYXZJASQEGCQDVYFOM9ETXAGVMSCHHQLFPATWOSMZIDL9AHMSDCE9UENACG9OVFAEIPPQYBCLXDMXXA9UBJFQQBCYKETPNKHNOUKCSSYLWZDLKUARXNVKKKHNRBVSTVKQCZL9RY9BDTDTPUTFUBGRMSTOTXLWUHDMSGYRDSZLIPGQXIDMNCNBOAOI9WFUCXSRLJFIVTIPIAZUK9EDUJJ9B9YCJEZQQELLHVCWDNRH9FUXDGZRGOVXGOKORTCQQA9JXNROLETYCNLRMBGXBL9DQKMOAZCBJGWLNJLGRSTYBKLGFVRUF9QOPZVQFGMDJA9TBVGFJDBAHEVOLW9GNU9NICLCQJBOAJBAHHBZJGOFUCQMBGYQLCWNKSZPPBQMSJTJLM9GXOZHTNDLGIRCSIJAZTENQVQDHFSOQM9WVNWQQJNOPZMEISSCLOADMRNWALBBSLSWNCTOSNHNLWZBVCFIOGFPCPRKQSRGKFXGTWUSCPZSKQNLQJGKDLOXSBJMEHQPDZGSENUKWAHRNONDTBLHNAKGLOMCFYRCGMDOVANPFHMQRFCZIQHCGVORJJNYMTORDKPJPLA9LWAKAWXLIFEVLKHRKCDG9QPQCPGVKIVBENQJTJGZKFTNZHIMQISVBNLHAYSSVJKTIELGTETKPVRQXNAPWOBGQGFRMMK9UQDWJHSQMYQQTCBMVQKUVGJEAGTEQDN9TCRRAZHDPSPIYVNKPGJSJZASZQBM9WXEDWGAOQPPZFLAMZLEZGXPYSOJRWL9ZH9NOJTUKXNTCRRDO9GKULXBAVDRIZBOKJYVJUSHIX9F9O9ACYCAHUKBIEPVZWVJAJGSDQNZNWLIWVSKFJUMOYDMVUFLUXT9CEQEVRFBJVPCTJQCORM9JHLYFSMUVMFDXZFNCUFZZIKREIUIHUSHRPPOUKGFKWX9COXBAZMQBBFRFIBGEAVKBWKNTBMLPHLOUYOXPIQIZQWGOVUWQABTJT9ZZPNBABQFYRCQLXDHDEX9PULVTCQLWPTJLRSVZQEEYVBVY9KCNEZXQLEGADSTJBYOXEVGVTUFKNCNWMEDKDUMTKCMRPGKDCCBDHDVVSMPOPUBZOMZTXJSQNVVGXNPPBVSBL9WWXWQNMHRMQFEQYKWNCSW9URI9FYPT9UZMAFMMGUKFYTWPCQKVJ9DIHRJFMXRZUGI9TMTFUQHGXNBITDSORZORQIAMKY9VRYKLEHNRNFSEFBHF9KXIQAEZEJNQOENJVMWLMHI9GNZPXYUIFAJIVCLAGKUZIKTJKGNQVTXJORWIQDHUPBBPPYOUPFAABBVMMYATXERQHPECDVYGWDGXFJKOMOBXKRZD9MCQ9LGDGGGMYGUAFGMQTUHZOAPLKPNPCIKUNEMQIZOCM9COAOMZSJ9GVWZBZYXMCNALENZ9PRYMHENPWGKX9ULUIGJUJRKFJPBTTHCRZQKEAHT9DC9GSWQEGDTZFHACZMLFYDVOWZADBNMEM9XXEOMHCNJMDSUAJRQTBUWKJF9RZHK9ACGUNI9URFIHLXBXCEODONPXBSCWP9WNAEYNALKQHGULUQGAFL9LB9NBLLCACLQFGQMXRHGBTMI9YKAJKVELRWWKJAPKMSYMJTDYMZ9PJEEYIRXRMMFLRSFSHIXUL9NEJABLRUGHJFL9RASMSKOI9VCFRZ9GWTMODUUESIJBHWWHZYCLDENBFSJQPIOYC9MBGOOXSWEMLVU9L9WJXKZKVDBDMFSVHHISSSNILUMWULMVMESQUIHDGBDXROXGH9MTNFSLWJZRAPOKKRGXAAQBFPYPAAXLSTMNSNDTTJQSDQORNJS9BBGQ9KQJZYPAQ9JYQZJ9B9KQDAXUACZWRUNGMBOQLQZUHFNCKVQGORRZGAHES9PWJUKZWUJSBMNZFILBNBQQKLXITCTQDDBV9UDAOQOUPWMXTXWFWVMCXIXLRMRWMAYYQJPCEAAOFEOGZQMEDAGYGCTKUJBS9AGEXJAFHWWDZRYEN9DN9HVCMLFURISLYSWKXHJKXMHUWZXUQARMYPGKRKQMHVR9JEYXJRPNZINYNCGZHHUNHBAIJHLYZIZGGIDFWVNXZQADLEDJFTIUTQWCQSX9QNGUZXGXJYUUTFSZPQKXBA9DFRQRLTLUJENKESDGTZRGRSLTNYTITXRXRGVLWBTEWPJXZYLGHLQBAVYVOSABIVTQYQM9FIQKCBRRUEMVVTMERLWOK";
+ private final static String HASH = "TIXEPIEYMGURTQ9ABVYVQSWMNGCVQFASMFAEQWUZCLIWLCDIGYVXOEJBBEMZOIHAYSUQMEFOGZBXUMHQW";
+
+ /**
+ * Benchmark absorb and squeeze methods of Curl 81 hash function.
+ */
+ @Benchmark
+ public void curl() {
+ int size = 8019;
+ byte[] in_trits = new byte[size];
+ byte[] hash_trits = new byte[Curl.HASH_LENGTH];
+ Converter.trits(TRYTES, in_trits, 0);
+ Curl curl = (Curl) SpongeFactory.create(SpongeFactory.Mode.CURLP81);
+ curl.absorb(in_trits, 0, in_trits.length);
+ curl.squeeze(hash_trits, 0, Curl.HASH_LENGTH);
+ String out_trytes = Converter.trytes(hash_trits);
+ Assert.assertEquals(HASH, out_trytes);
+ }
+
+ /**
+ * Benchmark absorb and squeeze methods of pair Curl 81 hash function.
+ */
+ @Benchmark
+ public void pairCurl() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
+ int size = 8019;
+ byte[] in_trits = new byte[size];
+ Pair hashPair = new Pair<>(new long[Curl.HASH_LENGTH], new long[Curl.HASH_LENGTH]);
+ Converter.trits(TRYTES, in_trits, 0);
+ // Using reflection to benchmark private, non-production code.
+ // Reflection doesn't have impact on benchmark result (this has been tested)
+ // Please remove this code when method are public
+ Class curlClass = Curl.class;
+ Constructor curlConstructor = curlClass.getDeclaredConstructor(boolean.class, SpongeFactory.Mode.class);
+ curlConstructor.setAccessible(true);
+ Curl curl = curlConstructor.newInstance(true, SpongeFactory.Mode.CURLP81);
+ Method pairAbsorb = curlClass.getDeclaredMethod("absorb", Pair.class, int.class, int.class);
+ Method pairSqueeze = curlClass.getDeclaredMethod("squeeze", Pair.class, int.class, int.class);
+ pairAbsorb.setAccessible(true);
+ pairSqueeze.setAccessible(true);
+
+ pairAbsorb.invoke(curl, Converter.longPair(in_trits), 0, in_trits.length);
+ pairSqueeze.invoke(curl, hashPair, 0, Curl.HASH_LENGTH);
+ byte[] hash_trits = Converter.trits(hashPair.low, hashPair.hi);
+ String out_trytes = Converter.trytes(hash_trits);
+ Assert.assertEquals(HASH, out_trytes);
+ }
+
+}
diff --git a/src/test/java/com/iota/iri/benchmarks/crypto/PearlDiverBenchmark.java b/src/test/java/com/iota/iri/benchmarks/crypto/PearlDiverBenchmark.java
new file mode 100644
index 0000000000..9d36eb1ed3
--- /dev/null
+++ b/src/test/java/com/iota/iri/benchmarks/crypto/PearlDiverBenchmark.java
@@ -0,0 +1,23 @@
+package com.iota.iri.benchmarks.crypto;
+
+import com.iota.iri.crypto.PearlDiver;
+import com.iota.iri.utils.Converter;
+import org.openjdk.jmh.annotations.Benchmark;
+
+public class PearlDiverBenchmark {
+ private static final int MIN_WEIGHT_MAGNITUDE = 9;
+ private static final int NUM_CORES = -1; // use n-1 cores
+ private static final String TRYTES = "ZMGYJPAAYHGRDGKCUEAIZDERGWUJH9QIHEESTUAZIQDQGMREKOVZCQRKHUZPXQ9PPIBGARFTZBZCYGAWIEUGPMIEEMKVSLCCJPITK9A9VLHCWLRZTRYDPGPFGEEFMVMVQGGM9NFPEKLVQHMOPDTJHDIEHBFGBBFOHPLHX9RJVEIQC9WAOFPHP9GGFRYCJEX9UVUGVJLBCBNQCLKSLULGZUHCVUJZMILSROKHYAA9RLF9XQXKXCULHJIUGXDWBKJLGLHXXR9BNKDKG9JMJCTAGMKWGXPPKVBVNROUADXHUJWYDWZDSIUIVUTKKBTVJ9CMKWVFMCYMCVFMDPLQ9YFIHUMRTBZLIT9LIQRFXF9AKDMTXMHKCSFQDJIFQRFBHSIKVKQBUKFDPOLWQXBUZKNGGHJW9IVLG9GTIW9IRWGCM9A9YT99JUDKQQLWBFXGYVDYSRYSAWVRBFXIKMQRGCIHLWOUTKFWWDFRQZMCAUXSSK9LWQRCNNCXBJOIKVMLTMRENT9YLUOHACKHYYUERSBKWSCJTCJBCDCARABPVNNKIXXSVLELPILCTRQCEGYITPVODUMUEYFRJBOKAVVIFURHZO9SYVHZGZZIRYGYJDCOWIEEZNBDBHMVDFCGDCYSJFEGCYDIGTPTAZTM9MJXKCCRGJQTXTQYOGLGBAWAUAPVMJAAUB9QOOO9FPQVCQVZQLAICIWUXZAVVRZJFKMXSJEL9KGDSGPKEIZHDXQWZFYWPLVOSSOAETKPMSDDQEZDOCNCOJCEWLSA9SSQODHAEUEERDCOTSHNEOVGCFGXQRRIVYJQUUMRVCAEMMPFYZAEWRFVBNWSGTGEWZUCOWKMEIEAGXCHPVTABBXUEWCLHTEOJZ9JPRQP9CCJQMUNQYMMHCVPSABZ9XVRLWFOMYOGVVYSYMYWCXQFUBHUVPONPSZUCYAWHWOEGAFCUXUWBRTBTYWVXNSSIZ9LHLX9UNN9FUJDUVBNLJSD9OG9FACSRNELL9DMTYITWDZPOHZSUSNUWJ9CEKQOXOXVZJVZZPTWJIFXXXRAVTDLLETTKPGNLWQCWERXFRZOPBZTDWNURWXDFKKP9SIG9IPGUSEHAGPQTCRAMMMPUWPRQKJDAKFUTR9YVVCXJQC9ZWZBOEAQISNTDHUQRKCXASYNZLQIJMZMMO9TWTHPMJIJKPTU9DMMCPYXOSPNSDQPID9YSIOFDNIJBQUEB9JTSRTWLMXUP9WIQFSZNINQLNS9NJWTLDLZYABHFKCZOBHQQQVWWVTWCKMFSYVPZHRHNJZWWFUHMCHYKLMCBXGAVRJSYLXOSYUHHTB9VMQT9NYPRDVAWWYREFVGFEJZKGPVEOQXWZD9LQNUFTREMBT9NETURCGYBWLGNMUPDO9ZSSLZJR9AEUPYLGEEIKUTHTCIXHSBCEKATIEQYBTYACTFWUJQCCTYHNTMFXHZKEFIEOXFQTKYDY9BDSLS9HXC9ANNQONFKIBZHREPYLSZWCR99HBYTLLISHGDXNLSRKNBSFCPHAFEUYLQWISLWOZRKKP9GSYFMXUBXJLMARNGJHORAVNZVDBKAZESOBFVBFSOZQGZ9IOJGCDUPYRDGEJVOPNLEFXTNXUBDSEDIYLUQBTDJONKRMBUFWYIJINZGIZOVPRKCTYFILHJPGAUSS9QPANDZQFXWTSLLEMDXMKZYWTIRUZIXWMJRRIUINDORRFTNSHASDZRGADSIRZYQAGJUVDCCRWOCMKRL9IPEEUJKLZMGLBSLXFVEHT9LWIKZYMNZUIQMJBRJETVQVWIENTSF9HLAOMKRNHHTRTPFHGWYVODZMNFPJRHLJXTKXWSSWXSTILWWJHQFFZLIZZGVAMZ9AGTM9RXQRZENESFBYZDJAQQFEHIYWYNKNYIXIRFGMMMXUXQ9TMCHIMATYHNBAVGKOXLIIVPOEFLUJCYURXQLEXSBKCVGCPOZGTVFZVSMOE9DEHTYVT9BDXHEIZFAQFZGSEDQCJAMZTWTLACGTTQKFDWFH9DLTOSCPGFJVKEFOCDLNDOKJK9MNUEFXMOLXMXBMAYO9QZOJEYWPPBOFZMJQTLULEGEPECTHHCAOHSHLIIBNIELLLXIGMUPFLCEBHUSQ9ZEYGXVDOSZTECCJHATQODTZNLPGUVOXYZTHAQELTYYTTJTICZYRGLRROICEKMWXDEUCKFRKOQFCMPITOMWVPYGPMLVWNQAV99SYHJYZJTKXQICGYHKQJ9QAOFACDNHRYYHDMCSHPLMVLWEXUEZDDTQJUBMBVJCO9RNASPTYVHVLHAYYGYUCRBWZZESBHEUEZIHJDNOVOFCEAZTKDXACSUPBFYCIRDVPPJTSWHM9BAVSPPGMBVZKIJBAGWZEIIUNUYOHEVEO9FYMJZXJFLXXIYFBIZYKTHNQWBJYHJPTYJPPUWDBQWJAWEYSGSFVLQYIB9TNYUSNWVVJPFVDQUONBBPQJINWXAKXHFSUQKYJBFGXCQWT9TYHMAFIWQPQI9IBEMDCRIFOZN9KFGBGH99ZSKFTLOWMNYJDBREEYQBVSMZPDVGRYNDRPERXXISDEYTLJBNTJSVTSSTMHG9HCC9PIAHWZAMDGRMZFNQKEJCW9NBFRTNRRXTOTUAJS9DKRAUZWCIUYXTUHYT9SJDSFRWGCPFOBUHHNXMWNLJJRLGMVMBISRI";
+
+ /**
+ * Benchmark Pearl Diver search function.
+ */
+ @Benchmark
+ public void search() {
+ PearlDiver pearlDiver = new PearlDiver();
+ byte[] myTrits = Converter.allocateTritsForTrytes(TRYTES.length());
+ Converter.trits(TRYTES, myTrits, 0);
+ pearlDiver.search(myTrits, MIN_WEIGHT_MAGNITUDE, NUM_CORES);
+ }
+
+}
diff --git a/src/test/java/com/iota/iri/conf/ConfigTest.java b/src/test/java/com/iota/iri/conf/ConfigTest.java
index f865147f8e..c341615db0 100644
--- a/src/test/java/com/iota/iri/conf/ConfigTest.java
+++ b/src/test/java/com/iota/iri/conf/ConfigTest.java
@@ -19,8 +19,11 @@
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -51,7 +54,7 @@ public static void tearDownAfterClass() throws IOException {
Test that iterates over common configs. It also attempts to check different types of types (double, boolean, string)
*/
@Test
- public void testArgsParsingMainnet() {
+ public void testArgsParsingMainnet() throws UnknownHostException {
String[] args = {
"-p", "14000",
"-u", "13000",
@@ -59,6 +62,7 @@ public void testArgsParsingMainnet() {
"-n", "udp://neighbor1 neighbor, tcp://neighbor2",
"--api-host", "1.1.1.1",
"--remote-limit-api", "call1 call2, call3",
+ "--remote-trusted-api-hosts", "192.168.0.55, 10.0.0.10",
"--max-find-transactions", "500",
"--max-requests-list", "1000",
"--max-get-trytes", "4000",
@@ -72,11 +76,11 @@ public void testArgsParsingMainnet() {
"--ixi-dir", "/ixi",
"--db-path", "/db",
"--db-log-path", "/dblog",
- "--zmq-enabled",
+ "--zmq-enabled", "true",
//we ignore this on mainnet
"--mwm", "4",
"--testnet-coordinator", "TTTTTTTTT",
- "--test-no-coo-validation",
+ "--test-no-coo-validation", "true",
//this should be ignored everywhere
"--fake-config"
};
@@ -92,6 +96,13 @@ public void testArgsParsingMainnet() {
Assert.assertEquals("api host", "1.1.1.1", iotaConfig.getApiHost());
Assert.assertEquals("remote limit api", Arrays.asList("call1", "call2", "call3"),
iotaConfig.getRemoteLimitApi());
+
+ List expectedTrustedApiHosts = Arrays.asList(
+ InetAddress.getByName("192.168.0.55"),
+ InetAddress.getByName("10.0.0.10"),
+ InetAddress.getByName("127.0.0.1"));
+ Assert.assertEquals("remote trusted api hosts", expectedTrustedApiHosts, iotaConfig.getRemoteTrustedApiHosts());
+
Assert.assertEquals("max find transactions", 500, iotaConfig.getMaxFindTransactions());
Assert.assertEquals("max requests list", 1000, iotaConfig.getMaxRequestsList());
Assert.assertEquals("max get trytes", 4000, iotaConfig.getMaxGetTrytes());
@@ -102,7 +113,7 @@ public void testArgsParsingMainnet() {
Assert.assertEquals("max peers", 10, iotaConfig.getMaxPeers());
Assert.assertEquals("dns refresher", false, iotaConfig.isDnsRefresherEnabled());
Assert.assertEquals("dns resolution", false, iotaConfig.isDnsResolutionEnabled());
- Assert.assertEquals("tip solidification", true, iotaConfig.isTipSolidifierEnabled());
+ Assert.assertEquals("tip solidification", false, iotaConfig.isTipSolidifierEnabled());
Assert.assertEquals("ixi-dir", "/ixi", iotaConfig.getIxiDir());
Assert.assertEquals("db path", "/db", iotaConfig.getDbPath());
Assert.assertEquals("zmq enabled", true, iotaConfig.isZmqEnabled());
@@ -115,7 +126,7 @@ public void testArgsParsingMainnet() {
@Test
public void testRemoteFlag() {
- String[] args = {"--remote"};
+ String[] args = {"--remote", "true"};
IotaConfig iotaConfig = ConfigFactory.createIotaConfig(false);
iotaConfig.parseConfigFromArgs(args);
Assert.assertEquals("The api interface should be open to the public", "0.0.0.0", iotaConfig.getApiHost());
@@ -144,11 +155,11 @@ public void testArgsParsingTestnet() {
"--ixi-dir", "/ixi",
"--db-path", "/db",
"--db-log-path", "/dblog",
- "--zmq-enabled",
+ "--zmq-enabled", "true",
//we ignore this on mainnet
"--mwm", "4",
"--testnet-coordinator", "TTTTTTTTT",
- "--testnet-no-coo-validation",
+ "--testnet-no-coo-validation", "true",
//this should be ignored everywhere
"--fake-config"
};
@@ -190,6 +201,7 @@ public void testIniParsingMainnet() throws Exception {
.append("[IRI]").append(System.lineSeparator())
.append("PORT = 17000").append(System.lineSeparator())
.append("NEIGHBORS = udp://neighbor1 neighbor, tcp://neighbor2").append(System.lineSeparator())
+ .append("REMOTE_TRUSTED_API_HOSTS = 192.168.0.55, 10.0.0.10").append(System.lineSeparator())
.append("ZMQ_ENABLED = true").append(System.lineSeparator())
.append("P_REMOVE_REQUEST = 0.4").append(System.lineSeparator())
.append("MWM = 4").append(System.lineSeparator())
@@ -206,6 +218,13 @@ public void testIniParsingMainnet() throws Exception {
Assert.assertEquals("PORT", 17000, iotaConfig.getPort());
Assert.assertEquals("NEIGHBORS", Arrays.asList("udp://neighbor1", "neighbor", "tcp://neighbor2"),
iotaConfig.getNeighbors());
+
+ List expectedTrustedApiHosts = Arrays.asList(
+ InetAddress.getByName("192.168.0.55"),
+ InetAddress.getByName("10.0.0.10"),
+ BaseIotaConfig.Defaults.REMOTE_LIMIT_API_DEFAULT_HOST);
+ Assert.assertEquals("REMOTE_TRUSTED_API_HOSTS", expectedTrustedApiHosts, iotaConfig.getRemoteTrustedApiHosts());
+
Assert.assertEquals("ZMQ_ENABLED", true, iotaConfig.isZmqEnabled());
Assert.assertEquals("P_REMOVE_REQUEST", 0.4d, iotaConfig.getpRemoveRequest(), 0);
Assert.assertNotEquals("MWM", 4, iotaConfig.getMwm());
diff --git a/src/test/java/com/iota/iri/conf/ZMQConfigTest.java b/src/test/java/com/iota/iri/conf/ZMQConfigTest.java
new file mode 100644
index 0000000000..e2caee1feb
--- /dev/null
+++ b/src/test/java/com/iota/iri/conf/ZMQConfigTest.java
@@ -0,0 +1,88 @@
+package com.iota.iri.conf;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ZMQConfigTest {
+
+ @Test
+ public void isZmqEnabledLegacy() {
+ String[] args = {
+ "--zmq-enabled", "true",
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertTrue("ZMQ must be globally enabled", config.isZmqEnabled());
+ assertTrue("ZMQ TCP must be enabled", config.isZmqEnableTcp());
+ assertTrue("ZMQ IPC must be enabled", config.isZmqEnableIpc());
+ }
+
+ @Test
+ public void isZmqEnabled() {
+ String[] args = {
+ "--zmq-enable-tcp", "true",
+ "--zmq-enable-ipc", "true",
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertTrue("ZMQ must be globally enabled", config.isZmqEnabled());
+ assertTrue("ZMQ TCP must be enabled", config.isZmqEnableTcp());
+ assertTrue("ZMQ IPC must be enabled", config.isZmqEnableIpc());
+ }
+
+ @Test
+ public void isZmqEnableTcp() {
+ String[] args = {
+ "--zmq-enable-tcp", "true"
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertEquals("ZMQ port must be the default port", 5556, config.getZmqPort());
+ assertTrue("ZMQ TCP must be enabled", config.isZmqEnableTcp());
+ }
+
+ @Test
+ public void isZmqEnableIpc() {
+ String[] args = {
+ "--zmq-enable-ipc", "true"
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertEquals("ZMQ ipc must be the default ipc", "ipc://iri", config.getZmqIpc());
+ assertTrue("ZMQ IPC must be enabled", config.isZmqEnableIpc());
+ }
+
+ @Test
+ public void getZmqPort() {
+ String[] args = {
+ "--zmq-port", "8899"
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertTrue("ZMQ TCP must be enabled", config.isZmqEnableTcp());
+ assertEquals("ZMQ port must be overridden", 8899, config.getZmqPort());
+ }
+
+ @Test
+ public void getZmqThreads() {
+ String[] args = {
+ "--zmq-threads", "5"
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertEquals("ZMQ threads must be overridden", 5, config.getZmqThreads());
+ }
+
+ @Test
+ public void getZmqIpc() {
+ String[] args = {
+ "--zmq-ipc", "ipc://test"
+ };
+ IotaConfig config = ConfigFactory.createIotaConfig(false);
+ config.parseConfigFromArgs(args);
+ assertTrue("ZMQ IPC must be enabled", config.isZmqEnableIpc());
+ assertEquals("ZMQ ipc must be overridden", "ipc://test", config.getZmqIpc());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/iota/iri/controllers/BundleViewModelTest.java b/src/test/java/com/iota/iri/controllers/BundleViewModelTest.java
index f50f09583b..eeb99aa519 100644
--- a/src/test/java/com/iota/iri/controllers/BundleViewModelTest.java
+++ b/src/test/java/com/iota/iri/controllers/BundleViewModelTest.java
@@ -13,7 +13,7 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionTrits;
+import static com.iota.iri.TransactionTestUtils.getTransactionTrits;
public class BundleViewModelTest {
private static final TemporaryFolder dbFolder = new TemporaryFolder();
@@ -71,7 +71,7 @@ public void getTail() throws Exception {
@Test
public void firstShouldFindTx() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
TransactionViewModel transactionViewModel = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
diff --git a/src/test/java/com/iota/iri/controllers/TipsViewModelTest.java b/src/test/java/com/iota/iri/controllers/TipsViewModelTest.java
index 0be38f4b5d..b5420df844 100644
--- a/src/test/java/com/iota/iri/controllers/TipsViewModelTest.java
+++ b/src/test/java/com/iota/iri/controllers/TipsViewModelTest.java
@@ -8,7 +8,7 @@
import java.util.concurrent.ExecutionException;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionHash;
+import static com.iota.iri.TransactionTestUtils.getTransactionHash;
import static org.junit.Assert.*;
@@ -79,7 +79,7 @@ public void nonsolidCapacityLimited() throws ExecutionException, InterruptedExce
int capacity = TipsViewModel.MAX_TIPS;
//fill tips list
for (int i = 0; i < capacity * 2 ; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
tipsVM.addTipHash(hash);
}
//check that limit wasn't breached
@@ -92,7 +92,7 @@ public void solidCapacityLimited() throws ExecutionException, InterruptedExcepti
int capacity = TipsViewModel.MAX_TIPS;
//fill tips list
for (int i = 0; i < capacity * 2 ; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
tipsVM.addTipHash(hash);
tipsVM.setSolid(hash);
}
@@ -106,7 +106,7 @@ public void totalCapacityLimited() throws ExecutionException, InterruptedExcepti
int capacity = TipsViewModel.MAX_TIPS;
//fill tips list
for (int i = 0; i <= capacity * 4; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
tipsVM.addTipHash(hash);
if (i % 2 == 1) {
tipsVM.setSolid(hash);
diff --git a/src/test/java/com/iota/iri/controllers/TransactionViewModelTest.java b/src/test/java/com/iota/iri/controllers/TransactionViewModelTest.java
index 4d059f1201..720316e842 100644
--- a/src/test/java/com/iota/iri/controllers/TransactionViewModelTest.java
+++ b/src/test/java/com/iota/iri/controllers/TransactionViewModelTest.java
@@ -23,9 +23,9 @@
import java.util.Random;
import java.util.Set;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionTrits;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionHash;
-import static com.iota.iri.TransactionTestUtils.getTransactionWithTrunkAndBranch;
+import static com.iota.iri.TransactionTestUtils.getTransactionTrits;
+import static com.iota.iri.TransactionTestUtils.getTransactionHash;
+import static com.iota.iri.TransactionTestUtils.getTransactionTritsWithTrunkAndBranch;
import static org.junit.Assert.*;
@@ -77,17 +77,17 @@ public void getApprovers() throws Exception {
TransactionViewModel transactionViewModel, otherTxVM, trunkTx, branchTx;
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
trunkTx = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
branchTx = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
- byte[] childTx = getRandomTransactionTrits();
+ byte[] childTx = getTransactionTrits();
System.arraycopy(trunkTx.getHash().trits(), 0, childTx, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_OFFSET, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_SIZE);
System.arraycopy(branchTx.getHash().trits(), 0, childTx, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_OFFSET, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_SIZE);
transactionViewModel = new TransactionViewModel(childTx, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, childTx));
- childTx = getRandomTransactionTrits();
+ childTx = getTransactionTrits();
System.arraycopy(trunkTx.getHash().trits(), 0, childTx, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_OFFSET, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_SIZE);
System.arraycopy(branchTx.getHash().trits(), 0, childTx, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_OFFSET, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_SIZE);
otherTxVM = new TransactionViewModel(childTx, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, childTx));
@@ -120,13 +120,13 @@ public void update() throws Exception {
public void trits() throws Exception {
byte[] blanks = new byte[13];
for(int i=0; i++ < 1000;) {
- byte[] trits = getRandomTransactionTrits(), searchTrits;
+ byte[] trits = getTransactionTrits(), searchTrits;
System.arraycopy(new byte[TransactionViewModel.VALUE_TRINARY_SIZE], 0, trits, TransactionViewModel.VALUE_TRINARY_OFFSET, TransactionViewModel.VALUE_TRINARY_SIZE);
Converter.copyTrits(seed.nextLong(), trits, TransactionViewModel.VALUE_TRINARY_OFFSET, TransactionViewModel.VALUE_USABLE_TRINARY_SIZE);
System.arraycopy(blanks, 0, trits, TransactionViewModel.TRUNK_TRANSACTION_TRINARY_OFFSET-blanks.length, blanks.length);
System.arraycopy(blanks, 0, trits, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_OFFSET-blanks.length, blanks.length);
System.arraycopy(blanks, 0, trits, TransactionViewModel.BRANCH_TRANSACTION_TRINARY_OFFSET + TransactionViewModel.BRANCH_TRANSACTION_TRINARY_SIZE-blanks.length, blanks.length);
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
TransactionViewModel transactionViewModel = new TransactionViewModel(trits, hash);
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
assertArrayEquals(transactionViewModel.trits(), TransactionViewModel.fromHash(tangle, transactionViewModel.getHash()).trits());
@@ -136,10 +136,10 @@ public void trits() throws Exception {
@Test
public void getBytes() throws Exception {
for(int i=0; i++ < 1000;) {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
System.arraycopy(new byte[TransactionViewModel.VALUE_TRINARY_SIZE], 0, trits, TransactionViewModel.VALUE_TRINARY_OFFSET, TransactionViewModel.VALUE_TRINARY_SIZE);
Converter.copyTrits(seed.nextLong(), trits, TransactionViewModel.VALUE_TRINARY_OFFSET, TransactionViewModel.VALUE_USABLE_TRINARY_SIZE);
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
TransactionViewModel transactionViewModel = new TransactionViewModel(trits, hash);
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
assertArrayEquals(transactionViewModel.getBytes(), TransactionViewModel.fromHash(tangle, transactionViewModel.getHash()).getBytes());
@@ -295,13 +295,13 @@ public void getArrivalTime() throws Exception {
public void updateHeightShouldWork() throws Exception {
int count = 4;
TransactionViewModel[] transactionViewModels = new TransactionViewModel[count];
- Hash hash = getRandomTransactionHash();
- transactionViewModels[0] = new TransactionViewModel(getTransactionWithTrunkAndBranch(Hash.NULL_HASH,
+ Hash hash = getTransactionHash();
+ transactionViewModels[0] = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(Hash.NULL_HASH,
Hash.NULL_HASH), hash);
transactionViewModels[0].store(tangle, snapshotProvider.getInitialSnapshot());
for(int i = 0; ++i < count; ) {
- transactionViewModels[i] = new TransactionViewModel(getTransactionWithTrunkAndBranch(hash,
- Hash.NULL_HASH), hash = getRandomTransactionHash());
+ transactionViewModels[i] = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(hash,
+ Hash.NULL_HASH), hash = getTransactionHash());
transactionViewModels[i].store(tangle, snapshotProvider.getInitialSnapshot());
}
@@ -316,10 +316,10 @@ public void updateHeightShouldWork() throws Exception {
public void updateHeightPrefilledSlotShouldFail() throws Exception {
int count = 4;
TransactionViewModel[] transactionViewModels = new TransactionViewModel[count];
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
for(int i = 0; ++i < count; ) {
- transactionViewModels[i] = new TransactionViewModel(getTransactionWithTrunkAndBranch(hash,
- Hash.NULL_HASH), hash = getRandomTransactionHash());
+ transactionViewModels[i] = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(hash,
+ Hash.NULL_HASH), hash = getTransactionHash());
transactionViewModels[i].store(tangle, snapshotProvider.getInitialSnapshot());
}
@@ -332,7 +332,7 @@ public void updateHeightPrefilledSlotShouldFail() throws Exception {
@Test
public void findShouldBeSuccessful() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
TransactionViewModel transactionViewModel = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
Hash hash = transactionViewModel.getHash();
@@ -343,9 +343,9 @@ public void findShouldBeSuccessful() throws Exception {
@Test
public void findShouldReturnNull() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
TransactionViewModel transactionViewModel = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
- trits = getRandomTransactionTrits();
+ trits = getTransactionTrits();
TransactionViewModel transactionViewModelNoSave = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
Hash hash = transactionViewModelNoSave.getHash();
@@ -358,7 +358,7 @@ public void testManyTXInDB() throws Exception {
int i, j;
LinkedList hashes = new LinkedList<>();
Hash hash;
- hash = getRandomTransactionHash();
+ hash = getTransactionHash();
hashes.add(hash);
long start, diff, diffget;
long subSumDiff=0,maxdiff=0, sumdiff = 0;
@@ -366,13 +366,13 @@ public void testManyTXInDB() throws Exception {
int interval1 = 50;
int interval = interval1*10;
log.info("Starting Test. #TX: {}", TransactionViewModel.getNumberOfStoredTransactions(tangle));
- new TransactionViewModel(getTransactionWithTrunkAndBranch(Hash.NULL_HASH, Hash.NULL_HASH), hash).store(tangle, snapshotProvider.getInitialSnapshot());
+ new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(Hash.NULL_HASH, Hash.NULL_HASH), hash).store(tangle, snapshotProvider.getInitialSnapshot());
TransactionViewModel transactionViewModel;
boolean pop = false;
for (i = 0; i++ < max;) {
- hash = getRandomTransactionHash();
+ hash = getTransactionHash();
j = hashes.size();
- transactionViewModel = new TransactionViewModel(getTransactionWithTrunkAndBranch(hashes.get(seed.nextInt(j)), hashes.get(seed.nextInt(j))), hash);
+ transactionViewModel = new TransactionViewModel(getTransactionTritsWithTrunkAndBranch(hashes.get(seed.nextInt(j)), hashes.get(seed.nextInt(j))), hash);
start = System.nanoTime();
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
diff = System.nanoTime() - start;
@@ -408,7 +408,7 @@ public void testManyTXInDB() throws Exception {
@Test
public void firstShouldFindTx() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
TransactionViewModel transactionViewModel = new TransactionViewModel(trits, TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits));
transactionViewModel.store(tangle, snapshotProvider.getInitialSnapshot());
diff --git a/src/test/java/com/iota/iri/crypto/PearlDiverTest.java b/src/test/java/com/iota/iri/crypto/PearlDiverTest.java
index 68b2655b63..f68fabdfbb 100644
--- a/src/test/java/com/iota/iri/crypto/PearlDiverTest.java
+++ b/src/test/java/com/iota/iri/crypto/PearlDiverTest.java
@@ -55,7 +55,7 @@ public void testInvalidTritsLength() {
@Ignore("to test pearlDiver iteratively")
public void testNoRandomFail() {
for (int i = 0; i < 10000; i++) {
- byte[] trits = TransactionTestUtils.getRandomTransactionTrits();
+ byte[] trits = TransactionTestUtils.getTransactionTrits();
pearlDiver.search(trits, MIN_WEIGHT_MAGNITUDE, NUM_CORES);
Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
for (int j = Hash.SIZE_IN_TRITS - 1; j > Hash.SIZE_IN_TRITS - MIN_WEIGHT_MAGNITUDE; j--) {
diff --git a/src/test/java/com/iota/iri/model/HashTest.java b/src/test/java/com/iota/iri/model/HashTest.java
index bdbb561916..17e854d64c 100644
--- a/src/test/java/com/iota/iri/model/HashTest.java
+++ b/src/test/java/com/iota/iri/model/HashTest.java
@@ -4,7 +4,7 @@
import com.iota.iri.crypto.SpongeFactory;
import com.iota.iri.utils.Converter;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionTrits;
+import static com.iota.iri.TransactionTestUtils.getTransactionTrits;
import org.junit.Assert;
import org.junit.Test;
@@ -14,7 +14,7 @@
public class HashTest {
@Test
public void calculate() throws Exception {
- Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, getRandomTransactionTrits());
+ Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, getTransactionTrits());
Assert.assertNotEquals(0, hash.hashCode());
Assert.assertNotEquals(null, hash.bytes());
Assert.assertNotEquals(null, hash.trits());
@@ -22,7 +22,7 @@ public void calculate() throws Exception {
@Test
public void calculate1() throws Exception {
- Hash hash = TransactionHash.calculate(getRandomTransactionTrits(), 0, 729, SpongeFactory.create(SpongeFactory.Mode.CURLP81));
+ Hash hash = TransactionHash.calculate(getTransactionTrits(), 0, 729, SpongeFactory.create(SpongeFactory.Mode.CURLP81));
Assert.assertNotEquals(null, hash.bytes());
Assert.assertNotEquals(0, hash.hashCode());
Assert.assertNotEquals(null, hash.trits());
@@ -30,7 +30,7 @@ public void calculate1() throws Exception {
@Test
public void calculate2() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
byte[] bytes = Converter.allocateBytesForTrits(trits.length);
Converter.bytes(trits, bytes);
Hash hash = TransactionHash.calculate(bytes, TransactionViewModel.TRINARY_SIZE, SpongeFactory.create(SpongeFactory.Mode.CURLP81));
@@ -47,23 +47,23 @@ public void trailingZeros() throws Exception {
@Test
public void trits() throws Exception {
- Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, getRandomTransactionTrits());
+ Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, getTransactionTrits());
Assert.assertFalse(Arrays.equals(new byte[Hash.SIZE_IN_TRITS], hash.trits()));
}
@Test
public void equals() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
Hash hash1 = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
Assert.assertTrue(hash.equals(hash1));
Assert.assertFalse(hash.equals(Hash.NULL_HASH));
- Assert.assertFalse(hash.equals(TransactionHash.calculate(SpongeFactory.Mode.CURLP81, getRandomTransactionTrits())));
+ Assert.assertFalse(hash.equals(TransactionHash.calculate(SpongeFactory.Mode.CURLP81, getTransactionTrits())));
}
@Test
public void hashCodeTest() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
Assert.assertNotEquals(hash.hashCode(), 0);
Assert.assertEquals(Hash.NULL_HASH.hashCode(), -240540129);
@@ -71,7 +71,7 @@ public void hashCodeTest() throws Exception {
@Test
public void toStringTest() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
Assert.assertEquals(Hash.NULL_HASH.toString(), "999999999999999999999999999999999999999999999999999999999999999999999999999999999");
Assert.assertNotEquals(hash.toString(), "999999999999999999999999999999999999999999999999999999999999999999999999999999999");
@@ -81,7 +81,7 @@ public void toStringTest() throws Exception {
@Test
public void bytes() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
Assert.assertTrue(Arrays.equals(new byte[Hash.SIZE_IN_BYTES], Hash.NULL_HASH.bytes()));
Assert.assertFalse(Arrays.equals(new byte[Hash.SIZE_IN_BYTES], hash.bytes()));
@@ -90,7 +90,7 @@ public void bytes() throws Exception {
@Test
public void compareTo() throws Exception {
- byte[] trits = getRandomTransactionTrits();
+ byte[] trits = getTransactionTrits();
Hash hash = TransactionHash.calculate(SpongeFactory.Mode.CURLP81, trits);
Assert.assertEquals(hash.compareTo(Hash.NULL_HASH), -Hash.NULL_HASH.compareTo(hash));
}
diff --git a/src/test/java/com/iota/iri/network/TransactionRequesterTest.java b/src/test/java/com/iota/iri/network/TransactionRequesterTest.java
index b4f02e88d3..72b909a9e6 100644
--- a/src/test/java/com/iota/iri/network/TransactionRequesterTest.java
+++ b/src/test/java/com/iota/iri/network/TransactionRequesterTest.java
@@ -5,12 +5,11 @@
import com.iota.iri.service.snapshot.SnapshotProvider;
import com.iota.iri.service.snapshot.impl.SnapshotProviderImpl;
import com.iota.iri.storage.Tangle;
-import com.iota.iri.zmq.MessageQ;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionHash;
+import static com.iota.iri.TransactionTestUtils.getTransactionHash;
import java.util.ArrayList;
import java.util.Arrays;
@@ -22,7 +21,6 @@
public class TransactionRequesterTest {
private static Tangle tangle = new Tangle();
private static SnapshotProvider snapshotProvider;
- private MessageQ mq;
@Before
public void setUp() throws Exception {
@@ -81,13 +79,13 @@ public void instance() throws Exception {
@Test
public void popEldestTransactionToRequest() throws Exception {
- TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider, mq);
+ TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider);
// Add some Txs to the pool and see if the method pops the eldest one
- Hash eldest = getRandomTransactionHash();
+ Hash eldest = getTransactionHash();
txReq.requestTransaction(eldest, false);
- txReq.requestTransaction(getRandomTransactionHash(), false);
- txReq.requestTransaction(getRandomTransactionHash(), false);
- txReq.requestTransaction(getRandomTransactionHash(), false);
+ txReq.requestTransaction(getTransactionHash(), false);
+ txReq.requestTransaction(getTransactionHash(), false);
+ txReq.requestTransaction(getTransactionHash(), false);
txReq.popEldestTransactionToRequest();
// Check that the transaction is there no more
@@ -98,18 +96,18 @@ public void popEldestTransactionToRequest() throws Exception {
public void transactionRequestedFreshness() throws Exception {
// Add some Txs to the pool and see if the method pops the eldest one
List eldest = new ArrayList(Arrays.asList(
- getRandomTransactionHash(),
- getRandomTransactionHash(),
- getRandomTransactionHash()
+ getTransactionHash(),
+ getTransactionHash(),
+ getTransactionHash()
));
- TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider, mq);
+ TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider);
int capacity = TransactionRequester.MAX_TX_REQ_QUEUE_SIZE;
//fill tips list
for (int i = 0; i < 3; i++) {
txReq.requestTransaction(eldest.get(i), false);
}
for (int i = 0; i < capacity; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
txReq.requestTransaction(hash,false);
}
@@ -123,11 +121,11 @@ public void transactionRequestedFreshness() throws Exception {
@Test
public void nonMilestoneCapacityLimited() throws Exception {
- TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider, mq);
+ TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider);
int capacity = TransactionRequester.MAX_TX_REQ_QUEUE_SIZE;
//fill tips list
for (int i = 0; i < capacity * 2 ; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
txReq.requestTransaction(hash,false);
}
//check that limit wasn't breached
@@ -136,11 +134,11 @@ public void nonMilestoneCapacityLimited() throws Exception {
@Test
public void milestoneCapacityNotLimited() throws Exception {
- TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider, mq);
+ TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider);
int capacity = TransactionRequester.MAX_TX_REQ_QUEUE_SIZE;
//fill tips list
for (int i = 0; i < capacity * 2 ; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
txReq.requestTransaction(hash,true);
}
//check that limit was surpassed
@@ -149,11 +147,11 @@ public void milestoneCapacityNotLimited() throws Exception {
@Test
public void mixedCapacityLimited() throws Exception {
- TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider, mq);
+ TransactionRequester txReq = new TransactionRequester(tangle, snapshotProvider);
int capacity = TransactionRequester.MAX_TX_REQ_QUEUE_SIZE;
//fill tips list
for (int i = 0; i < capacity * 4 ; i++) {
- Hash hash = getRandomTransactionHash();
+ Hash hash = getTransactionHash();
txReq.requestTransaction(hash, (i % 2 == 1));
}
diff --git a/src/test/java/com/iota/iri/network/impl/TransactionRequesterWorkerImplTest.java b/src/test/java/com/iota/iri/network/impl/TransactionRequesterWorkerImplTest.java
index 91060e854b..5bde327817 100644
--- a/src/test/java/com/iota/iri/network/impl/TransactionRequesterWorkerImplTest.java
+++ b/src/test/java/com/iota/iri/network/impl/TransactionRequesterWorkerImplTest.java
@@ -20,15 +20,13 @@
import com.iota.iri.model.persistables.Transaction;
import com.iota.iri.network.Node;
import com.iota.iri.network.TransactionRequester;
-import com.iota.iri.network.impl.TransactionRequesterWorkerImpl;
import com.iota.iri.service.snapshot.SnapshotProvider;
import com.iota.iri.storage.Tangle;
-import com.iota.iri.zmq.MessageQ;
-import static com.iota.iri.TransactionTestUtils.getRandomTransaction;
+import static com.iota.iri.TransactionTestUtils.getTransaction;
import static com.iota.iri.TransactionTestUtils.get9Transaction;
import static com.iota.iri.TransactionTestUtils.buildTransaction;
-import static com.iota.iri.TransactionTestUtils.getRandomTransactionHash;
+import static com.iota.iri.TransactionTestUtils.getTransactionHash;
import static org.mockito.Mockito.when;
@@ -36,13 +34,13 @@ public class TransactionRequesterWorkerImplTest {
//Good
private static final TransactionViewModel TVMRandomNull = new TransactionViewModel(
- getRandomTransaction(), Hash.NULL_HASH);
+ getTransaction(), Hash.NULL_HASH);
private static final TransactionViewModel TVMRandomNotNull = new TransactionViewModel(
- getRandomTransaction(), getRandomTransactionHash());
+ getTransaction(), getTransactionHash());
private static final TransactionViewModel TVMAll9Null = new TransactionViewModel(
get9Transaction(), Hash.NULL_HASH);
private static final TransactionViewModel TVMAll9NotNull = new TransactionViewModel(
- get9Transaction(), getRandomTransactionHash());
+ get9Transaction(), getTransactionHash());
//Bad
private static final TransactionViewModel TVMNullNull = new TransactionViewModel((Transaction)null, Hash.NULL_HASH);
@@ -53,9 +51,6 @@ public class TransactionRequesterWorkerImplTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private static SnapshotProvider snapshotProvider;
- @Mock
- private static MessageQ messageQ;
-
private static TransactionRequester requester;
private static TransactionRequesterWorkerImpl worker;
@@ -70,7 +65,7 @@ public class TransactionRequesterWorkerImplTest {
@Before
public void before() {
- requester = new TransactionRequester(tangle, snapshotProvider, messageQ);
+ requester = new TransactionRequester(tangle, snapshotProvider);
worker = new TransactionRequesterWorkerImpl();
worker.init(tangle, requester, tipsVM, node);
@@ -146,7 +141,7 @@ private void fillRequester() throws Exception {
}
private void addRequest() throws Exception {
- Hash randomHash = getRandomTransactionHash();
+ Hash randomHash = getTransactionHash();
TangleMockUtils.mockTransaction(tangle, randomHash);
requester.requestTransaction(randomHash, false);
}
diff --git a/src/test/java/com/iota/iri/service/APIIntegrationTests.java b/src/test/java/com/iota/iri/service/APIIntegrationTests.java
index 73152876a8..a3b90e061b 100644
--- a/src/test/java/com/iota/iri/service/APIIntegrationTests.java
+++ b/src/test/java/com/iota/iri/service/APIIntegrationTests.java
@@ -10,6 +10,7 @@
import com.iota.iri.controllers.TransactionViewModel;
import com.iota.iri.crypto.SpongeFactory;
import com.iota.iri.model.TransactionHash;
+import com.iota.iri.service.restserver.resteasy.RestEasy;
import com.iota.iri.utils.Converter;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.builder.ResponseSpecBuilder;
@@ -83,20 +84,24 @@ public static void setUp() throws Exception {
logFolder.create();
configuration = ConfigFactory.createIotaConfig(true);
- String[] args = {"-p", portStr, "--testnet", "--db-path", dbFolder.getRoot().getAbsolutePath(), "--db-log-path",
+ String[] args = {"-p", portStr, "--testnet", "true", "--db-path", dbFolder.getRoot().getAbsolutePath(), "--db-log-path",
logFolder.getRoot().getAbsolutePath(), "--mwm", "1"};
configuration.parseConfigFromArgs(args);
//create node
iota = new Iota(configuration);
ixi = new IXI(iota);
- api = new API(iota, ixi);
+ api = new API(iota.configuration, ixi, iota.transactionRequester,
+ iota.spentAddressesService, iota.tangle, iota.bundleValidator,
+ iota.snapshotProvider, iota.ledgerService, iota.node, iota.tipsSelector,
+ iota.tipsViewModel, iota.transactionValidator,
+ iota.latestMilestoneTracker);
//init
try {
iota.init();
iota.snapshotProvider.getInitialSnapshot().setTimestamp(0);
- api.init();
+ api.init(new RestEasy(configuration));
ixi.init(IXIConfig.IXI_DIR);
} catch (final Exception e) {
log.error("Exception during IOTA node initialisation: ", e);
diff --git a/src/test/java/com/iota/iri/service/ApiCallTest.java b/src/test/java/com/iota/iri/service/ApiCallTest.java
new file mode 100644
index 0000000000..3d00328542
--- /dev/null
+++ b/src/test/java/com/iota/iri/service/ApiCallTest.java
@@ -0,0 +1,28 @@
+package com.iota.iri.service;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.iota.iri.conf.IotaConfig;
+
+public class ApiCallTest {
+
+ private API api;
+
+ @Before
+ public void setUp() {
+ IotaConfig configuration = Mockito.mock(IotaConfig.class);
+ api = new API(configuration, null, null, null, null, null, null, null, null, null, null, null, null);
+ }
+
+ @Test
+ public void apiHasAllEnums() {
+ for (ApiCommand c : ApiCommand.values()) {
+ if (!api.commandRoute.containsKey(c)) {
+ Assert.fail("Api should contain all enum values");
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/iota/iri/service/NodeIntegrationTests.java b/src/test/java/com/iota/iri/service/NodeIntegrationTests.java
index 47c93ad2c2..04b0d48051 100644
--- a/src/test/java/com/iota/iri/service/NodeIntegrationTests.java
+++ b/src/test/java/com/iota/iri/service/NodeIntegrationTests.java
@@ -12,6 +12,7 @@
import com.iota.iri.model.Hash;
import com.iota.iri.model.HashFactory;
import com.iota.iri.network.Node;
+import com.iota.iri.service.restserver.resteasy.RestEasy;
import com.iota.iri.utils.Converter;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.After;
@@ -52,8 +53,14 @@ public void testGetsSolid() throws Exception {
iotaNodes[i] = newNode(i, folders[i*2], folders[i*2+1]);
ixi[i] = new IXI(iotaNodes[i]);
ixi[i].init(IXIConfig.IXI_DIR);
- api[i] = new API(iotaNodes[i], ixi[i]);
- api[i].init();
+
+ api[i] = new API(iotaNodes[i].configuration, ixi[i], iotaNodes[i].transactionRequester,
+ iotaNodes[i].spentAddressesService, iotaNodes[i].tangle, iotaNodes[i].bundleValidator,
+ iotaNodes[i].snapshotProvider, iotaNodes[i].ledgerService, iotaNodes[i].node,
+ iotaNodes[i].tipsSelector, iotaNodes[i].tipsViewModel, iotaNodes[i].transactionValidator,
+ iotaNodes[i].latestMilestoneTracker);
+
+ api[i].init(new RestEasy(iotaNodes[i].configuration));
}
Node.uri("udp://localhost:14701").ifPresent(uri -> iotaNodes[0].node.addNeighbor(iotaNodes[0].node.newNeighbor(uri, true)));
//Node.uri("udp://localhost:14700").ifPresent(uri -> iotaNodes[1].node.addNeighbor(iotaNodes[1].node.newNeighbor(uri, true)));
diff --git a/src/test/java/com/iota/iri/service/restserver/RestEasyTest.java b/src/test/java/com/iota/iri/service/restserver/RestEasyTest.java
new file mode 100644
index 0000000000..f62f9f05d7
--- /dev/null
+++ b/src/test/java/com/iota/iri/service/restserver/RestEasyTest.java
@@ -0,0 +1,135 @@
+package com.iota.iri.service.restserver;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.InetAddress;
+import java.util.Base64;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.test.TestPortProvider;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import com.iota.iri.conf.APIConfig;
+import com.iota.iri.service.dto.ErrorResponse;
+import com.iota.iri.service.dto.GetNodeInfoResponse;
+import com.iota.iri.service.restserver.resteasy.RestEasy;
+
+public class RestEasyTest {
+
+ private static final String USER_PASS = "user:pass";
+
+ @Rule
+ public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+ @Mock
+ private APIConfig apiconfig;
+
+
+ private RestEasy server;
+
+ @Before
+ public void setUp() {
+ Mockito.when(apiconfig.getPort()).thenReturn(TestPortProvider.getPort());
+ Mockito.when(apiconfig.getApiHost()).thenReturn(TestPortProvider.getHost());
+ Mockito.when(apiconfig.getMaxBodyLength()).thenReturn(Integer.MAX_VALUE);
+ }
+
+ @After
+ public void tearDown() {
+ this.server.stop();
+ }
+
+ @Test
+ public void nodeInfoMissingApiVersion() {
+ this.server = new RestEasy(apiconfig);
+ this.server.init((String param, InetAddress address) -> {
+ return GetNodeInfoResponse.createEmptyResponse();
+ });
+ this.server.start();
+
+ Client client = ClientBuilder.newClient();
+ String jsonString = "{\"command\": \"getNodeInfo\"}";
+ Response val = client.target(TestPortProvider.generateURL("/"))
+ .request()
+ .post(Entity.entity(jsonString, MediaType.APPLICATION_JSON));
+ ErrorResponse response = val.readEntity(ErrorResponse.class);
+ assertEquals("API version should be required in the header", "Invalid API Version", response.getError());
+ }
+
+ @Test
+ public void nodeInfoValid() {
+ this.server = new RestEasy(apiconfig);
+ this.server.init((String param, InetAddress address) -> {
+ return GetNodeInfoResponse.createEmptyResponse();
+ });
+ this.server.start();
+
+ Client client = ClientBuilder.newClient();
+ String jsonString = "{\"command\": \"getNodeInfo\"}";
+ Response val = client.target(TestPortProvider.generateURL("/"))
+ .request()
+ .header("X-IOTA-API-Version", "1")
+ .post(Entity.entity(jsonString, MediaType.APPLICATION_JSON));
+
+ GetNodeInfoResponse response = val.readEntity(GetNodeInfoResponse.class);
+ assertNotNull("Response should not be parseable as a GetNodeInfoResponse", response);
+ }
+
+ @Test
+ public void notAllowed() {
+ Mockito.when(apiconfig.getRemoteAuth()).thenReturn(USER_PASS);
+
+ this.server = new RestEasy(apiconfig);
+ this.server.init((String param, InetAddress address) -> {
+ return GetNodeInfoResponse.createEmptyResponse();
+ });
+ this.server.start();
+
+ Client client = ClientBuilder.newClient();
+ String jsonString = "{\"command\": \"getNodeInfo\"}";
+ Response val = client.target(TestPortProvider.generateURL("/"))
+ .request()
+ .header("X-IOTA-API-Version", "1")
+ .post(Entity.entity(jsonString, MediaType.APPLICATION_JSON));
+
+ assertEquals("Request should be denied due to lack of authentication",
+ Response.Status.UNAUTHORIZED, val.getStatusInfo());
+ }
+
+ @Test
+ public void allowed() {
+ Mockito.when(apiconfig.getRemoteAuth()).thenReturn(USER_PASS);
+
+ this.server = new RestEasy(apiconfig);
+ this.server.init((String param, InetAddress address) -> {
+ return GetNodeInfoResponse.createEmptyResponse();
+ });
+ this.server.start();
+
+ Client client = ClientBuilder.newClient();
+ String jsonString = "{\"command\": \"getNodeInfo\"}";
+
+ String encoded = Base64.getEncoder().encodeToString(USER_PASS.getBytes());
+
+ Response val = client.target(TestPortProvider.generateURL("/"))
+ .request()
+ .header("X-IOTA-API-Version", "1")
+ .header("Authorization", "Basic " + encoded)
+ .post(Entity.entity(jsonString, MediaType.APPLICATION_JSON));
+
+ assertEquals("Request should be accepted as we authenticated", Response.Status.OK, val.getStatusInfo());
+ }
+}
diff --git a/src/test/java/com/iota/iri/service/snapshot/impl/LocalSnapshotManagerImplTest.java b/src/test/java/com/iota/iri/service/snapshot/impl/LocalSnapshotManagerImplTest.java
new file mode 100644
index 0000000000..b1dd52bbb5
--- /dev/null
+++ b/src/test/java/com/iota/iri/service/snapshot/impl/LocalSnapshotManagerImplTest.java
@@ -0,0 +1,149 @@
+package com.iota.iri.service.snapshot.impl;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.any;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import com.iota.iri.conf.SnapshotConfig;
+import com.iota.iri.service.milestone.LatestMilestoneTracker;
+import com.iota.iri.service.snapshot.SnapshotException;
+import com.iota.iri.service.snapshot.SnapshotProvider;
+import com.iota.iri.service.snapshot.SnapshotService;
+import com.iota.iri.service.transactionpruning.TransactionPruner;
+import com.iota.iri.utils.thread.ThreadUtils;
+
+public class LocalSnapshotManagerImplTest {
+
+ private static final int BUFFER = LocalSnapshotManagerImpl.LOCAL_SNAPSHOT_SYNC_BUFFER;
+
+ private static final int DELAY_SYNC = 5;
+ private static final int DELAY_UNSYNC = 1;
+ private static final int SNAPSHOT_DEPTH = 5;
+
+ @Rule
+ public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+ @Mock
+ private static SnapshotConfig config;
+
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ SnapshotProvider snapshotProvider;
+
+ @Mock
+ SnapshotService snapshotService;
+
+ @Mock
+ TransactionPruner transactionPruner;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ LatestMilestoneTracker milestoneTracker;
+
+ private LocalSnapshotManagerImpl lsManager;
+
+ @Before
+ public void setUp() throws Exception {
+ this.lsManager = new LocalSnapshotManagerImpl();
+
+ lsManager.init(snapshotProvider, snapshotService, transactionPruner, config);
+ when(snapshotProvider.getLatestSnapshot().getIndex()).thenReturn(-5, -1, 10, 998, 999, 1999, 2000);
+
+ when(config.getLocalSnapshotsIntervalSynced()).thenReturn(DELAY_SYNC);
+ when(config.getLocalSnapshotsIntervalUnsynced()).thenReturn(DELAY_UNSYNC);
+ when(config.getLocalSnapshotsDepth()).thenReturn(SNAPSHOT_DEPTH);
+ }
+
+ @After
+ public void tearDown() {
+ lsManager.shutdown();
+ }
+
+ @Test
+ public synchronized void takeLocalSnapshot() throws SnapshotException {
+ // Always return true
+ when(milestoneTracker.isInitialScanComplete()).thenReturn(true);
+
+ // When we call it, we are in sync
+ when(milestoneTracker.getLatestMilestoneIndex()).thenReturn(-5);
+
+ // We are more then the depth ahead
+ when(snapshotProvider.getLatestSnapshot().getIndex()).thenReturn(100);
+ when(snapshotProvider.getInitialSnapshot().getIndex()).thenReturn(100 - SNAPSHOT_DEPTH - DELAY_SYNC - 1);
+
+ // Run in separate thread to allow us to time-out
+ Thread t = new Thread(() -> lsManager.monitorThread(milestoneTracker));
+
+ t.start();
+ // We should finish directly, margin for slower computers
+ ThreadUtils.sleep(100);
+
+ // Cancel the thread
+ t.interrupt();
+
+ // Verify we took a snapshot
+ try {
+ verify(snapshotService, times(1)).takeLocalSnapshot(any(), any());
+ } catch (MockitoAssertionError e) {
+ throw new MockitoAssertionError("A snapshot should have been taken when we are below SNAPSHOT_DEPTH");
+ }
+ }
+
+ @Test
+ public void isInSyncTestScanIncomplete() {
+ when(milestoneTracker.isInitialScanComplete()).thenReturn(false);
+
+ assertFalse("We should be out of sync when he havent finished initial scans", lsManager.isInSync(milestoneTracker));
+ }
+
+ @Test
+ public void isInSyncTestScanComplete() {
+ // Always return true
+ when(milestoneTracker.isInitialScanComplete()).thenReturn(true);
+
+ // We don't really support -1 indexes, but if this breaks, it is a good indication to be careful going further
+ when(milestoneTracker.getLatestMilestoneIndex()).thenReturn(-1, 5, 10, 998 + BUFFER - 1, 2000);
+
+ // snapshotProvider & milestoneTracker
+ // -5 & -1 -> not in sync
+ assertFalse("Previous out of sync and not equal index should not be in sync", lsManager.isInSync(milestoneTracker));
+
+ // -1 and 5 -> not in sync
+ assertFalse("Previous out of sync and not equal index should not be in sync", lsManager.isInSync(milestoneTracker));
+
+ // 10 and 10 -> in sync
+ assertTrue("Equal index should be in sync", lsManager.isInSync(milestoneTracker));
+
+ // 998 and 1002 -> in sync since sync gap = 5
+ assertTrue("Index difference less than the buffer still should be in sync", lsManager.isInSync(milestoneTracker));
+
+ // 999 and 2000 -> out of sync again, bigger gap than 5
+ assertFalse("Index difference more than the buffer should be out of sync again ", lsManager.isInSync(milestoneTracker));
+
+ // 1999 and 2000 -> out of sync still
+ assertFalse("Previous out of sync and not equal index should not be in sync", lsManager.isInSync(milestoneTracker));
+
+ // 2000 and 2000 -> in sync again
+ assertTrue("Equal index should be in sync", lsManager.isInSync(milestoneTracker));
+ }
+
+ @Test
+ public void getDelayTest() {
+ assertEquals("Out of sync should return the config value at getLocalSnapshotsIntervalUnsynced",
+ DELAY_UNSYNC, lsManager.getSnapshotInterval(false));
+
+ assertEquals("In sync should return the config value at getLocalSnapshotsIntervalSynced",
+ DELAY_SYNC, lsManager.getSnapshotInterval(true));
+ }
+}
diff --git a/src/test/java/com/iota/iri/service/snapshot/impl/SnapshotImplTest.java b/src/test/java/com/iota/iri/service/snapshot/impl/SnapshotImplTest.java
new file mode 100644
index 0000000000..2ac294fa06
--- /dev/null
+++ b/src/test/java/com/iota/iri/service/snapshot/impl/SnapshotImplTest.java
@@ -0,0 +1,68 @@
+package com.iota.iri.service.snapshot.impl;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.iota.iri.TransactionTestUtils;
+import com.iota.iri.model.Hash;
+import com.iota.iri.service.snapshot.Snapshot;
+import com.iota.iri.service.snapshot.SnapshotMetaData;
+import com.iota.iri.service.snapshot.SnapshotState;
+
+public class SnapshotImplTest {
+
+ private static SnapshotState state;
+
+ private static SnapshotMetaData metaData;
+
+ @Before
+ public void setUp() throws Exception {
+ state = new SnapshotStateImpl(new HashMap<>());
+ metaData = new SnapshotMetaDataImpl(Hash.NULL_HASH, 1, 1l, new HashMap<>(), new HashMap<>());
+ }
+
+ @Test
+ public void skippedMilestoneTest() {
+ Snapshot snapshot = new SnapshotImpl(state, metaData);
+ assertTrue("Not previously seen milestone should be accepted", snapshot.addSkippedMilestone(1));
+
+ assertFalse("Previously seen milestone should not be accepted", snapshot.addSkippedMilestone(1));
+ assertTrue("Skipped milestone should be removed correctly", snapshot.removeSkippedMilestone(1));
+ assertFalse("Not skipped milestone should fail to get removed", snapshot.removeSkippedMilestone(1));
+ }
+
+ @Test
+ public void updateTest() {
+ Snapshot snapshot = new SnapshotImpl(state, metaData);
+ snapshot.setIndex(0);
+ snapshot.setHash(Hash.NULL_HASH);
+ snapshot.setInitialTimestamp(1l);
+
+ Snapshot newSnapshot = snapshot.clone();
+ newSnapshot.setIndex(1);
+ snapshot.setHash(TransactionTestUtils.getTransactionHash());
+ snapshot.setInitialTimestamp(5l);
+
+ assertNotEquals("Modified snapshot clone should not be equal to its original", snapshot, newSnapshot);
+ snapshot.update(newSnapshot);
+ assertEquals("Updating a snapshot with another snapshot should make them equal", snapshot, newSnapshot);
+ }
+
+ @Test
+ public void cloneTest() {
+ Snapshot oldSnapshot = new SnapshotImpl(state, metaData);
+ Snapshot newSnapshot = oldSnapshot.clone();
+
+ assertEquals("A clone of a snapshot is equal to its original", oldSnapshot, newSnapshot);
+
+ oldSnapshot.addSkippedMilestone(1);
+
+ // Clone shouldnt have the skipped milestone
+ assertFalse("Adding a value to a clone should be reflected on the original", newSnapshot.removeSkippedMilestone(1));
+ assertNotEquals("A clone should not be equal to its original after modification", oldSnapshot, newSnapshot);
+ }
+}
diff --git a/src/test/java/com/iota/iri/service/snapshot/impl/SnapshotMetaDataImplTest.java b/src/test/java/com/iota/iri/service/snapshot/impl/SnapshotMetaDataImplTest.java
new file mode 100644
index 0000000000..7e41c4696b
--- /dev/null
+++ b/src/test/java/com/iota/iri/service/snapshot/impl/SnapshotMetaDataImplTest.java
@@ -0,0 +1,124 @@
+package com.iota.iri.service.snapshot.impl;
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.iota.iri.TransactionTestUtils;
+import com.iota.iri.conf.BaseIotaConfig;
+import com.iota.iri.model.Hash;
+import com.iota.iri.service.snapshot.SnapshotMetaData;
+
+public class SnapshotMetaDataImplTest {
+
+ private static final Hash A = TransactionTestUtils.getTransactionHash();
+ private static final Hash B = TransactionTestUtils.getTransactionHash();
+ private static final Hash C = TransactionTestUtils.getTransactionHash();
+ private static final Hash D = TransactionTestUtils.getTransactionHash();
+
+ private static Map solidEntryPoints = new HashMap(){{
+ put(A, 1);
+ put(B, 2);
+ put(C, -1);
+ }};
+
+ private static Map