diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkComparisonResult.java b/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkComparisonResult.java index 5b002712..9438ef42 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkComparisonResult.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkComparisonResult.java @@ -128,6 +128,7 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(currentResult, baselineResult, percentChange, isRegression, isImprovement, isFirstRun); } + /** {@return the builder} */ public static Builder builder() { return new Builder(); @@ -141,41 +142,84 @@ public static class Builder { private boolean isImprovement; private boolean isFirstRun; private double thresholdPercent; + /** + * Current result. + * + * @param currentResult the current result + * @return the current result + */ public Builder currentResult(BenchmarkResult currentResult) { this.currentResult = currentResult; return this; } + /** + * Baseline result. + * + * @param baselineResult the baseline result + * @return the baseline result + */ public Builder baselineResult(BenchmarkResult baselineResult) { this.baselineResult = baselineResult; return this; } + /** + * Percent change. + * + * @param percentChange the percent change + * @return the percent change + */ public Builder percentChange(double percentChange) { this.percentChange = percentChange; return this; } + /** + * Is regression. + * + * @param isRegression the is regression + * @return the is regression + */ public Builder isRegression(boolean isRegression) { this.isRegression = isRegression; return this; } + /** + * Is improvement. + * + * @param isImprovement the is improvement + * @return the is improvement + */ public Builder isImprovement(boolean isImprovement) { this.isImprovement = isImprovement; return this; } + /** + * Is first run. + * + * @param isFirstRun the is first run + * @return the is first run + */ public Builder isFirstRun(boolean isFirstRun) { this.isFirstRun = isFirstRun; return this; } + /** + * Threshold percent. + * + * @param thresholdPercent the threshold percent + * @return the threshold percent + */ public Builder thresholdPercent(double thresholdPercent) { this.thresholdPercent = thresholdPercent; return this; } + /** {@return the build} */ public BenchmarkComparisonResult build() { return new BenchmarkComparisonResult(this); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkResult.java b/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkResult.java index 2f86c11b..6bc49a13 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkResult.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/benchmark/BenchmarkResult.java @@ -160,6 +160,7 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(testClass, testMethod, timestamp); } + /** {@return the builder} */ public static Builder builder() { return new Builder(); @@ -176,56 +177,117 @@ public static class Builder { private long minTimePerInvocationNanos; private long maxTimePerInvocationNanos; private List invocationTimesNanos = new ArrayList<>(); + /** + * Test class. + * + * @param testClass the test class + * @return the test class + */ public Builder testClass(String testClass) { this.testClass = testClass; return this; } + /** + * Test method. + * + * @param testMethod the test method + * @return the test method + */ public Builder testMethod(String testMethod) { this.testMethod = testMethod; return this; } + /** + * Timestamp. + * + * @param timestamp the timestamp + * @return the timestamp + */ public Builder timestamp(LocalDateTime timestamp) { this.timestamp = timestamp; return this; } + /** + * Threads. + * + * @param threads the threads + * @return the threads + */ public Builder threads(int threads) { this.threads = threads; return this; } + /** + * Invocations. + * + * @param invocations the invocations + * @return the invocations + */ public Builder invocations(int invocations) { this.invocations = invocations; return this; } + /** + * Total execution time in nanoseconds. + * + * @param totalExecutionTimeNanos the total execution time in nanoseconds + * @return the total execution time in nanoseconds + */ public Builder totalExecutionTimeNanos(long totalExecutionTimeNanos) { this.totalExecutionTimeNanos = totalExecutionTimeNanos; return this; } + /** + * Avg time per invocation in nanoseconds. + * + * @param avgTimePerInvocationNanos the avg time per invocation in nanoseconds + * @return the avg time per invocation in nanoseconds + */ public Builder avgTimePerInvocationNanos(long avgTimePerInvocationNanos) { this.avgTimePerInvocationNanos = avgTimePerInvocationNanos; return this; } + /** + * Min time per invocation in nanoseconds. + * + * @param minTimePerInvocationNanos the min time per invocation in nanoseconds + * @return the min time per invocation in nanoseconds + */ public Builder minTimePerInvocationNanos(long minTimePerInvocationNanos) { this.minTimePerInvocationNanos = minTimePerInvocationNanos; return this; } + /** + * Max time per invocation in nanoseconds. + * + * @param maxTimePerInvocationNanos the max time per invocation in nanoseconds + * @return the max time per invocation in nanoseconds + */ public Builder maxTimePerInvocationNanos(long maxTimePerInvocationNanos) { this.maxTimePerInvocationNanos = maxTimePerInvocationNanos; return this; } + /** + * Invocation times in nanoseconds. + * + * @param invocationTimesNanos the invocation times in nanoseconds + * @return the invocation times in nanoseconds + */ public Builder invocationTimesNanos(List invocationTimesNanos) { this.invocationTimesNanos = new ArrayList<>(invocationTimesNanos); return this; } + /** {@return the build} */ public BenchmarkResult build() { return new BenchmarkResult(this); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ABAProblemDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ABAProblemDetector.java index 848b9394..feb731de 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ABAProblemDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ABAProblemDetector.java @@ -213,20 +213,30 @@ public ABAReport analyzeABA() { public ABAReport analyze() { return analyzeABA(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { trackedVariables.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; } public static class ABAReport { + /** The variables with cycles. */ public final Map variablesWithCycles = new HashMap<>(); /** The successful ABA cases. */ public final Set successfulABACases = new HashSet<>(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AtomicityValidator.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AtomicityValidator.java index 160e8591..cab7d11a 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AtomicityValidator.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AtomicityValidator.java @@ -47,6 +47,11 @@ private static class FieldAccessRecord { */ private final Queue atomicityViolations = new ConcurrentLinkedQueue<>(); private volatile boolean enabled = true; + /** + * Records compound operation start so it can be analysed at the end of the run. + * + * @param operationName the operation name + */ public void recordCompoundOperationStart(String operationName) { if (!enabled || operationName == null || operationName.isBlank()) { @@ -56,6 +61,11 @@ public void recordCompoundOperationStart(String operationName) { activeOperations.put(operationKey(operationName), new CompoundOperation(operationName, Thread.currentThread().threadId())); } + /** + * Records compound operation end so it can be analysed at the end of the run. + * + * @param operationName the operation name + */ public void recordCompoundOperationEnd(String operationName) { if (!enabled || operationName == null || operationName.isBlank()) { @@ -64,6 +74,13 @@ public void recordCompoundOperationEnd(String operationName) { activeOperations.remove(operationKey(operationName)); } + /** + * Records field access so it can be analysed at the end of the run. + * + * @param fieldName the field name + * @param value the value + * @param isWrite the is write + */ public void recordFieldAccess(String fieldName, @Nullable Object value, boolean isWrite) { recordFieldAccess(fieldName, value, isWrite, Thread.currentThread().threadId()); @@ -122,6 +139,15 @@ public void recordFieldAccess(String fieldName, @Nullable Object value, boolean } } } + /** + * Detect check then act violation. + * + * @param fieldName the field name + * @param checkValue the check value + * @param expectedValue the expected value + * @param wouldAct the would act + * @return the detect check then act violation + */ public boolean detectCheckThenActViolation(String fieldName, Object checkValue, Object expectedValue, boolean wouldAct) { @@ -138,6 +164,11 @@ public boolean detectCheckThenActViolation(String fieldName, Object checkValue, } return violation; } + /** + * Analyses what has been recorded about atomicity and builds the report for it. + * + * @return the analyze atomicity + */ public AtomicityReport analyzeAtomicity() { AtomicityReport report = new AtomicityReport(); @@ -185,16 +216,25 @@ public AtomicityReport analyze() { private String operationKey(String operationName) { return Thread.currentThread().threadId() + ":" + operationName; } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { activeOperations.clear(); fieldHistory.clear(); atomicityViolations.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AutoFix.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AutoFix.java index 6a65ba05..9c655bf8 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AutoFix.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/AutoFix.java @@ -88,10 +88,20 @@ public static String getRaceConditionFix() { Option 3: Use synchronized methods ───────────────────────────────────────────────────────── + /** + * Deposit. + * + * @param amount the amount + */ // Before: public void deposit(long amount) { balance += amount; } + /** + * Deposit. + * + * @param amount the amount + */ // After: public synchronized void deposit(long amount) { @@ -103,6 +113,11 @@ public synchronized void deposit(long amount) { ───────────────────────────────────────────────────────── private final ReentrantLock lock = new ReentrantLock(); private long balance; + /** + * Deposit. + * + * @param amount the amount + */ public void deposit(long amount) { lock.lock(); @@ -147,10 +162,14 @@ public static String getVisibilityFix() { Option 3: Use synchronized ───────────────────────────────────────────────────────── private boolean ready = false; + /** + * Set ready. + */ public synchronized void setReady() { ready = true; } + /** {@return the is ready} */ public synchronized boolean isReady() { return ready; @@ -422,6 +441,9 @@ public static String getAtomicityViolationFix() { Option 3: Use synchronized ───────────────────────────────────────────────────────── private long counter; + /** + * Increment. + */ public synchronized void increment() { counter++; // Now atomic @@ -458,6 +480,9 @@ public static String getLockLeakFix() { class LockedResource implements AutoCloseable { private final Lock lock; LockedResource(Lock lock) { this.lock = lock; lock.lock(); } + /** + * Close. + */ public void close() { lock.unlock(); } } diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/BusyWaitDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/BusyWaitDetector.java index e9891397..6fe8fedc 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/BusyWaitDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/BusyWaitDetector.java @@ -39,6 +39,9 @@ private static class SpinEvent { private final Map threadActivities = new ConcurrentHashMap<>(); private volatile boolean enabled = true; + /** + * Records loop iteration so it can be analysed at the end of the run. + */ public void recordLoopIteration() { if (!enabled) { @@ -58,6 +61,9 @@ public void recordLoopIteration() { } } } + /** + * Records yield so it can be analysed at the end of the run. + */ public void recordYield() { if (!enabled) { @@ -83,6 +89,12 @@ public void recordYield() { activity.spinStartTime = 0; } } + /** + * Report spin loop. + * + * @param description the description + * @param iterations the iterations + */ public void reportSpinLoop(String description, long iterations) { if (!enabled) { @@ -103,6 +115,11 @@ private String inferCallSite() { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); return trace.length > 3 ? trace[3].toString() : "unknown"; } + /** + * Analyses what has been recorded about busy waiting and builds the report for it. + * + * @return the analyze busy waiting + */ public BusyWaitReport analyzeBusyWaiting() { BusyWaitReport report = new BusyWaitReport(); @@ -160,14 +177,23 @@ private static void addToReport(BusyWaitReport report, long threadId, SpinEvent public BusyWaitReport analyze() { return analyzeBusyWaiting(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { threadActivities.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; @@ -178,6 +204,7 @@ public static class BusyWaitReport { public final Set busyWaitLoops = new HashSet<>(); /** The tight loops. */ public final Set tightLoops = new HashSet<>(); + /** The cpu wasted. */ public long cpuWasted; /** {@return whether there are issues} */ diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureBlockingCallbackDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureBlockingCallbackDetector.java index f47bc961..e1e7c82e 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureBlockingCallbackDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureBlockingCallbackDetector.java @@ -62,6 +62,11 @@ public void recordBlockingCall(Thread thread, String blockingApiName) { s.blockingCalls.add(blockingApiName + " by thread " + thread.getName()); } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureObtrudeDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureObtrudeDetector.java index 2fc90218..29e59bce 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureObtrudeDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/CompletableFutureObtrudeDetector.java @@ -48,6 +48,11 @@ public void recordObtrude(CompletableFuture future, String label, Thread thre new State(name, old.obtrudeCount + 1, val.lastObtrudedByThread) ); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ConstructorSafetyValidator.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ConstructorSafetyValidator.java index 3ec9c7cd..307a2034 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ConstructorSafetyValidator.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ConstructorSafetyValidator.java @@ -154,14 +154,23 @@ public ConstructorSafetyReport validateConstructorSafety() { return report; } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { objects.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/DeadlockDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/DeadlockDetector.java index 1261fc6c..e376626d 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/DeadlockDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/DeadlockDetector.java @@ -40,6 +40,9 @@ public DeadlockDetector() { preexistingDeadlockedThreads = Set.copyOf(ids); } } + /** + * Prints thread dump to the report output. + */ public static void printThreadDump() { ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ExecutorDeadlockDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ExecutorDeadlockDetector.java index e3cdf8c8..4e2dc2a1 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ExecutorDeadlockDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ExecutorDeadlockDetector.java @@ -30,6 +30,13 @@ private static class ExecutorState { } private final Map executors = new ConcurrentHashMap<>(); + /** + * Registers executor for tracking. + * + * @param executor the executor + * @param name the name + * @param maxThreads the max threads + */ public void registerExecutor(Object executor, String name, int maxThreads) { if (executor == null) { @@ -38,6 +45,11 @@ public void registerExecutor(Object executor, String name, int maxThreads) { executors.putIfAbsent(System.identityHashCode(executor), new ExecutorState(name == null || name.isBlank() ? "Executor" : name, maxThreads)); } + /** + * Records task submitted so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordTaskSubmitted(Object executor) { ExecutorState state = stateFor(executor); @@ -45,6 +57,11 @@ public void recordTaskSubmitted(Object executor) { state.submitted.incrementAndGet(); } } + /** + * Records task started so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordTaskStarted(Object executor) { ExecutorState state = stateFor(executor); @@ -52,6 +69,11 @@ public void recordTaskStarted(Object executor) { state.running.incrementAndGet(); } } + /** + * Records waiting on sibling so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordWaitingOnSibling(Object executor) { ExecutorState state = stateFor(executor); @@ -59,6 +81,11 @@ public void recordWaitingOnSibling(Object executor) { state.waitingOnSibling.incrementAndGet(); } } + /** + * Records task completed so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordTaskCompleted(Object executor) { ExecutorState state = stateFor(executor); @@ -70,6 +97,11 @@ public void recordTaskCompleted(Object executor) { private @Nullable ExecutorState stateFor(Object executor) { return executor == null ? null : executors.get(System.identityHashCode(executor)); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public ExecutorDeadlockReport analyze() { ExecutorDeadlockReport report = new ExecutorDeadlockReport(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FalseSharingDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FalseSharingDetector.java index d5751390..2520372c 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FalseSharingDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FalseSharingDetector.java @@ -165,15 +165,24 @@ private long getFieldSize(Class type) { if (type == byte.class || type == boolean.class) return 1; return 8; // References } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { fieldAccess.clear(); accessHistory.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FileChannelPositionRaceDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FileChannelPositionRaceDetector.java index dbb84e1b..60804088 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FileChannelPositionRaceDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FileChannelPositionRaceDetector.java @@ -116,6 +116,11 @@ private State stateFor(Object channel) { } return s; } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FutureBlockingDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FutureBlockingDetector.java index bc176b0a..6b042d7c 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FutureBlockingDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/FutureBlockingDetector.java @@ -31,9 +31,22 @@ private static class ExecutorState { private final Map executors = new ConcurrentHashMap<>(); private volatile boolean enabled = true; + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; } + /** + * Registers executor for tracking. + * + * @param executor the executor + * @param name the name + * @param maxThreads the max threads + */ public void registerExecutor(Object executor, String name, int maxThreads) { if (!enabled || executor == null) { @@ -42,6 +55,11 @@ public void registerExecutor(Object executor, String name, int maxThreads) { executors.putIfAbsent(System.identityHashCode(executor), new ExecutorState(name == null || name.isBlank() ? "Executor" : name, maxThreads)); } + /** + * Records task submitted so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordTaskSubmitted(Object executor) { ExecutorState state = stateFor(executor); @@ -49,6 +67,11 @@ public void recordTaskSubmitted(Object executor) { state.submittedTasks.incrementAndGet(); } } + /** + * Records task started so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordTaskStarted(Object executor) { ExecutorState state = stateFor(executor); @@ -56,6 +79,11 @@ public void recordTaskStarted(Object executor) { state.runningTasks.incrementAndGet(); } } + /** + * Records blocking wait so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordBlockingWait(Object executor) { ExecutorState state = stateFor(executor); @@ -63,6 +91,11 @@ public void recordBlockingWait(Object executor) { state.blockingTasks.incrementAndGet(); } } + /** + * Records task completed so it can be analysed at the end of the run. + * + * @param executor the executor + */ public void recordTaskCompleted(Object executor) { ExecutorState state = stateFor(executor); @@ -77,6 +110,11 @@ public void recordTaskCompleted(Object executor) { } return executors.get(System.identityHashCode(executor)); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public FutureBlockingReport analyze() { FutureBlockingReport report = new FutureBlockingReport(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/InterruptMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/InterruptMonitor.java index d0d2bb89..667e333a 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/InterruptMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/InterruptMonitor.java @@ -31,6 +31,11 @@ private static class InterruptEvent { private final Set ignoredDescriptions = ConcurrentHashMap.newKeySet(); private final Set blockingWithoutHandling = ConcurrentHashMap.newKeySet(); private volatile boolean enabled = true; + /** + * Records interrupt exception so it can be analysed at the end of the run. + * + * @param ex the ex + */ public void recordInterruptException(InterruptedException ex) { if (!enabled) { @@ -49,6 +54,9 @@ public void recordInterruptException(InterruptedException ex) { interruptEvents.add(event); } } + /** + * Records interrupt restored so it can be analysed at the end of the run. + */ public void recordInterruptRestored() { if (!enabled) { @@ -66,6 +74,11 @@ public void recordInterruptRestored() { } } } + /** + * Records ignored exception so it can be analysed at the end of the run. + * + * @param description the description + */ public void recordIgnoredException(String description) { if (!enabled) { @@ -79,6 +92,11 @@ public void recordIgnoredException(String description) { description )); } + /** + * Records blocking operation without interrupt handling so it can be analysed at the end of the run. + * + * @param operationName the operation name + */ public void recordBlockingOperationWithoutInterruptHandling(String operationName) { if (!enabled) { @@ -97,6 +115,11 @@ private String inferCallSite() { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); return trace.length > 3 ? trace[3].toString() : "unknown"; } + /** + * Analyses what has been recorded about interrupt handling and builds the report for it. + * + * @return the analyze interrupt handling + */ public InterruptReport analyzeInterruptHandling() { InterruptReport report = new InterruptReport(); @@ -146,6 +169,9 @@ public InterruptReport analyzeInterruptHandling() { public InterruptReport analyze() { return analyzeInterruptHandling(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { synchronized (interruptEvents) { @@ -154,10 +180,16 @@ public void reset() { ignoredDescriptions.clear(); blockingWithoutHandling.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/JdbcConnectionSharedDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/JdbcConnectionSharedDetector.java index f24be98b..81ada98f 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/JdbcConnectionSharedDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/JdbcConnectionSharedDetector.java @@ -103,6 +103,11 @@ public void recordAccess(Object resource, String name, Thread thread) { s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LatchMisuseDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LatchMisuseDetector.java index 8011d588..2cec6412 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LatchMisuseDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LatchMisuseDetector.java @@ -29,6 +29,13 @@ private static class LatchState { } private final Map latches = new ConcurrentHashMap<>(); + /** + * Registers latch for tracking. + * + * @param latch the latch + * @param name the name + * @param initialCount the initial count + */ public void registerLatch(Object latch, String name, int initialCount) { if (latch == null) { @@ -37,6 +44,11 @@ public void registerLatch(Object latch, String name, int initialCount) { latches.putIfAbsent(System.identityHashCode(latch), new LatchState(name == null || name.isBlank() ? "CountDownLatch" : name, initialCount)); } + /** + * Records await so it can be analysed at the end of the run. + * + * @param latch the latch + */ public void recordAwait(Object latch) { LatchState state = stateFor(latch); @@ -44,6 +56,11 @@ public void recordAwait(Object latch) { state.awaitCalls.incrementAndGet(); } } + /** + * Records count down so it can be analysed at the end of the run. + * + * @param latch the latch + */ public void recordCountDown(Object latch) { LatchState state = stateFor(latch); @@ -55,6 +72,11 @@ public void recordCountDown(Object latch) { private @Nullable LatchState stateFor(Object latch) { return latch == null ? null : latches.get(System.identityHashCode(latch)); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public LatchMisuseReport analyze() { LatchMisuseReport report = new LatchMisuseReport(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LazyInitValidator.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LazyInitValidator.java index bb0f8f2f..12e45653 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LazyInitValidator.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LazyInitValidator.java @@ -27,6 +27,15 @@ private static class LazyFieldState { private final Map fields = new ConcurrentHashMap<>(); private volatile boolean enabled = true; + /** + * Records access so it can be analysed at the end of the run. + * + * @param fieldName the field name + * @param observedNull the observed null + * @param initializedValue the initialized value + * @param synchronizedAccess the synchronized access + * @param volatileField the volatile field + */ public void recordAccess(String fieldName, boolean observedNull, boolean initializedValue, boolean synchronizedAccess, boolean volatileField) { @@ -56,6 +65,11 @@ public void recordAccess(String fieldName, boolean observedNull, boolean initial state.initializationAttempts.incrementAndGet(); } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public LazyInitReport analyze() { LazyInitReport report = new LazyInitReport(); @@ -82,6 +96,9 @@ public LazyInitReport analyze() { return report; } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { fields.clear(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LivelockDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LivelockDetector.java index bece49df..4cfcfd24 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LivelockDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LivelockDetector.java @@ -171,15 +171,24 @@ private boolean madeProgress(List snapshots) { // Otherwise: progress means CPU time advanced, or the thread moved between states. return last.cpuTime > first.cpuTime || first.state != last.state; } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { threadHistory.clear(); observedThreads.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockOrderValidator.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockOrderValidator.java index 913a308a..decf2813 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockOrderValidator.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockOrderValidator.java @@ -162,14 +162,23 @@ private boolean hasCycle(String node, Map> graph, recursionStack.remove(node); return false; } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { threadLockOrders.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockUpgradeDeadlockDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockUpgradeDeadlockDetector.java index 375fb0e2..c95444b1 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockUpgradeDeadlockDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/LockUpgradeDeadlockDetector.java @@ -71,6 +71,11 @@ public void recordWriteLockAcquisitionAttempt(ReentrantReadWriteLock lock, Strin s.deadlockedThreads.add(thread.getName()); } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryModelValidator.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryModelValidator.java index b52bff61..f377c4a2 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryModelValidator.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryModelValidator.java @@ -167,7 +167,9 @@ private void testAtomicVisibility(ValidationResult result) { } public static class ValidationResult { + /** The tests run. */ public int testsRun = 0; + /** The tests passed. */ public int testsPassed = 0; /** The observations. */ public final List observations = Collections.synchronizedList(new ArrayList<>()); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryOrderingMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryOrderingMonitor.java index db356d8e..20f9848d 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryOrderingMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/MemoryOrderingMonitor.java @@ -105,14 +105,23 @@ public MemoryOrderingReport analyzeOrdering() { public MemoryOrderingReport analyze() { return analyzeOrdering(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { accessLog.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NonAtomicConcurrentMapUpdateDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NonAtomicConcurrentMapUpdateDetector.java index 2934ddb0..ea19a1e5 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NonAtomicConcurrentMapUpdateDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NonAtomicConcurrentMapUpdateDetector.java @@ -102,6 +102,11 @@ public void recordCheckThenAct(ConcurrentMap map, Object key, String opera s.threadIds.add(thread.threadId()); s.threadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NotifyAllValidator.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NotifyAllValidator.java index 868c4d13..1fef0bd4 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NotifyAllValidator.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/NotifyAllValidator.java @@ -32,6 +32,12 @@ private static class MonitorState { private final Map monitors = new ConcurrentHashMap<>(); private volatile boolean enabled = true; + /** + * Records waiter added so it can be analysed at the end of the run. + * + * @param monitor the monitor + * @param monitorName the monitor name + */ public void recordWaiterAdded(Object monitor, String monitorName) { if (!enabled || monitor == null) { @@ -47,6 +53,11 @@ public void recordWaiterAdded(Object monitor, String monitorName) { int parked = state.waitingThreads.incrementAndGet(); state.peakWaitingThreads.updateAndGet(peak -> Math.max(peak, parked)); } + /** + * Records waiter released so it can be analysed at the end of the run. + * + * @param monitor the monitor + */ public void recordWaiterReleased(Object monitor) { if (!enabled || monitor == null) { @@ -58,6 +69,12 @@ public void recordWaiterReleased(Object monitor) { state.waitingThreads.updateAndGet(current -> Math.max(0, current - 1)); } } + /** + * Records notify so it can be analysed at the end of the run. + * + * @param monitor the monitor + * @param notifyAll the notify all + */ public void recordNotify(Object monitor, boolean notifyAll) { if (!enabled || monitor == null) { @@ -81,6 +98,11 @@ public void recordNotify(Object monitor, boolean notifyAll) { } } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public NotifyAllReport analyze() { NotifyAllReport report = new NotifyAllReport(); @@ -107,14 +129,23 @@ public NotifyAllReport analyze() { return report; } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { monitors.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/PipelineMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/PipelineMonitor.java index 2dc75c15..a6ed9f28 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/PipelineMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/PipelineMonitor.java @@ -121,15 +121,24 @@ public PipelineReport analyzePipeline() { public PipelineReport analyze() { return analyzePipeline(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { stages.clear(); eventLog.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; @@ -138,6 +147,7 @@ public void enable() { public static class PipelineReport { /** The missing events. */ public final Set missingEvents = new HashSet<>(); + /** The failed events. */ public final Map> failedEvents = new HashMap<>(); /** The low processing rate. */ public final Set lowProcessingRate = new HashSet<>(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/RaceConditionDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/RaceConditionDetector.java index 551b2f08..b1c7a600 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/RaceConditionDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/RaceConditionDetector.java @@ -40,6 +40,12 @@ private static class ObjectFieldState { private final Map objects = new ConcurrentHashMap<>(); private final IssueDeduplicator deduplicator = new IssueDeduplicator<>(); private volatile boolean enabled = true; + /** + * Records field read so it can be analysed at the end of the run. + * + * @param object the object + * @param fieldName the field name + */ public void recordFieldRead(Object object, String fieldName) { if (!enabled || object == null || fieldName == null || fieldName.isBlank()) { @@ -47,6 +53,12 @@ public void recordFieldRead(Object object, String fieldName) { } recordAccess(object, fieldName, false); } + /** + * Records field write so it can be analysed at the end of the run. + * + * @param object the object + * @param fieldName the field name + */ public void recordFieldWrite(Object object, String fieldName) { if (!enabled || object == null || fieldName == null || fieldName.isBlank()) { @@ -65,6 +77,11 @@ private void recordAccess(Object object, String fieldName, boolean write) { state.fieldAccesses.computeIfAbsent(fieldName, ignored -> Collections.synchronizedList(new ArrayList<>())) .add(new FieldAccess(Thread.currentThread().threadId(), write)); } + /** + * Analyses what has been recorded about race conditions and builds the report for it. + * + * @return the analyze race conditions + */ public RaceConditionReport analyzeRaceConditions() { RaceConditionReport report = new RaceConditionReport(); @@ -148,15 +165,24 @@ public RaceConditionReport analyzeRaceConditions() { public RaceConditionReport analyze() { return analyzeRaceConditions(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { objects.clear(); deduplicator.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ReadWriteLockMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ReadWriteLockMonitor.java index ac83d209..cc66d4c7 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ReadWriteLockMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ReadWriteLockMonitor.java @@ -164,14 +164,23 @@ public ReadWriteLockReport analyzeFairness() { public ReadWriteLockReport analyze() { return analyzeFairness(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { locks.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedByteBufferDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedByteBufferDetector.java index f758eaca..ecc962e7 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedByteBufferDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedByteBufferDetector.java @@ -121,6 +121,11 @@ private State resolve(Object buffer) { } return s; } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedCharsetCoderDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedCharsetCoderDetector.java index 3e50f079..dfbe3abd 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedCharsetCoderDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedCharsetCoderDetector.java @@ -104,6 +104,11 @@ private void record(int id, String operation, String kind, Thread thread) { s.operations.add(operation); } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedChecksumDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedChecksumDetector.java index a39f4c45..999a12f0 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedChecksumDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedChecksumDetector.java @@ -81,6 +81,11 @@ public void recordAccess(Checksum checksum, String operation, Thread thread) { s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedDeflaterDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedDeflaterDetector.java index 952abdc9..121de0b4 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedDeflaterDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedDeflaterDetector.java @@ -98,6 +98,11 @@ private void record(int id, String name, String kind, Thread thread) { s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedIteratorDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedIteratorDetector.java index 4af806bb..292e0c56 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedIteratorDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedIteratorDetector.java @@ -112,6 +112,11 @@ private static String kindOf(Object iterator) { if (iterator instanceof Iterator) return "Iterator"; return iterator.getClass().getSimpleName(); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedJsonMapperReconfigDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedJsonMapperReconfigDetector.java index 9c4960e2..d5b58a65 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedJsonMapperReconfigDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedJsonMapperReconfigDetector.java @@ -134,6 +134,11 @@ private State stateFor(Object mapper) { } return s; } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedKdfDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedKdfDetector.java index b1fce9c2..efbd389c 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedKdfDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedKdfDetector.java @@ -88,6 +88,11 @@ public void recordAccess(Object kdf, String algorithm, String operation, Thread s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedSecureRandomDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedSecureRandomDetector.java index 78aace78..9324e4ce 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedSecureRandomDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedSecureRandomDetector.java @@ -98,6 +98,11 @@ public void recordAccess(SecureRandom random, String name, Thread thread) { s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedStatefulCryptoDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedStatefulCryptoDetector.java index f8b383f4..69ce477c 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedStatefulCryptoDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SharedStatefulCryptoDetector.java @@ -126,6 +126,11 @@ private void record(int id, String name, String kind, Class type, String algo s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SleepInLockDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SleepInLockDetector.java index a6652a7a..26dc02c4 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SleepInLockDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SleepInLockDetector.java @@ -188,6 +188,9 @@ public void clear() { } eventCount.set(0); } + /** + * Disable. + */ public void disable() { this.enabled = false; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SpuriousWakeupDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SpuriousWakeupDetector.java index 626d9de6..3f813e3c 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SpuriousWakeupDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SpuriousWakeupDetector.java @@ -47,6 +47,11 @@ public void recordWait(Object monitor, String monitorName, boolean insideLoop, T )); s.threadsOutsideLoop.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SynchronizerMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SynchronizerMonitor.java index 45fb4696..1e423a30 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SynchronizerMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/SynchronizerMonitor.java @@ -130,14 +130,23 @@ public SynchronizerReport analyzeSynchronizers() { public SynchronizerReport analyze() { return analyzeSynchronizers(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { synchronizers.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThisEscapeDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThisEscapeDetector.java index b1514420..7a9f7698 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThisEscapeDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThisEscapeDetector.java @@ -122,6 +122,11 @@ public void recordConstructionComplete(Object instance) { State s = instances.get(System.identityHashCode(instance)); if (s != null) s.completed = true; } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLeakDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLeakDetector.java index 03c1344e..78449a03 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLeakDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLeakDetector.java @@ -192,6 +192,9 @@ public void clear() { trackedThreads.clear(); maxThreadCount = 0; } + /** + * Disable. + */ public void disable() { this.enabled = false; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalMonitor.java index 67092097..88b1f0c0 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalMonitor.java @@ -26,6 +26,12 @@ private static class ThreadLocalState { private final Map threadLocals = new ConcurrentHashMap<>(); private final Map> threadLocalsByThread = new ConcurrentHashMap<>(); private volatile boolean enabled = true; + /** + * Records thread local init so it can be analysed at the end of the run. + * + * @param threadLocal the thread local + * @param name the name + */ public void recordThreadLocalInit(ThreadLocal threadLocal, String name) { if (!enabled || threadLocal == null) { @@ -38,6 +44,11 @@ public void recordThreadLocalInit(ThreadLocal threadLocal, String name) { state.initialized = true; recordThreadUsage(state, Thread.currentThread().threadId()); } + /** + * Records thread local access so it can be analysed at the end of the run. + * + * @param threadLocal the thread local + */ public void recordThreadLocalAccess(ThreadLocal threadLocal) { if (!enabled || threadLocal == null) { @@ -48,6 +59,11 @@ public void recordThreadLocalAccess(ThreadLocal threadLocal) { ThreadLocalState state = threadLocals.computeIfAbsent(id, ignored -> new ThreadLocalState("ThreadLocal-" + id, id)); recordThreadUsage(state, Thread.currentThread().threadId()); } + /** + * Records thread local cleanup so it can be analysed at the end of the run. + * + * @param threadLocal the thread local + */ public void recordThreadLocalCleanup(ThreadLocal threadLocal) { if (!enabled || threadLocal == null) { @@ -65,6 +81,11 @@ private void recordThreadUsage(ThreadLocalState state, long threadId) { state.threadsThatUsed.add(threadId); threadLocalsByThread.computeIfAbsent(threadId, ignored -> ConcurrentHashMap.newKeySet()).add(state.threadLocalId); } + /** + * Analyses what has been recorded about thread local leaks and builds the report for it. + * + * @return the analyze thread local leaks + */ public ThreadLocalReport analyzeThreadLocalLeaks() { ThreadLocalReport report = new ThreadLocalReport(); @@ -105,15 +126,24 @@ public ThreadLocalReport analyzeThreadLocalLeaks() { public ThreadLocalReport analyze() { return analyzeThreadLocalLeaks(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { threadLocals.clear(); threadLocalsByThread.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalRandomMisuseDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalRandomMisuseDetector.java index f28f9a14..7b9c17a8 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalRandomMisuseDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadLocalRandomMisuseDetector.java @@ -102,6 +102,11 @@ public void recordUse(ThreadLocalRandom rng, Thread thread) { s.misusingThreads.add(thread.getName()); } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadPoolMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadPoolMonitor.java index bd620449..530e9ec1 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadPoolMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadPoolMonitor.java @@ -156,14 +156,23 @@ public ThreadPoolReport analyzePoolHealth() { public ThreadPoolReport analyze() { return analyzePoolHealth(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { pools.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadStarvationDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadStarvationDetector.java index 7c1d7cb8..b7750c3e 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadStarvationDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/ThreadStarvationDetector.java @@ -224,6 +224,9 @@ public void clear() { starvationEvents.clear(); } } + /** + * Disable. + */ public void disable() { this.enabled = false; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/TryLockMisuseDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/TryLockMisuseDetector.java index c1cd438b..7df20e41 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/TryLockMisuseDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/TryLockMisuseDetector.java @@ -62,6 +62,11 @@ public void recordUnlock(Object lock, String lockName, Thread thread) { threadResults.remove(thread.threadId()); } } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/UnboundedQueueDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/UnboundedQueueDetector.java index 779700f2..9d8cd2d6 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/UnboundedQueueDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/UnboundedQueueDetector.java @@ -195,6 +195,9 @@ public void clear() { events.clear(); } } + /** + * Disable. + */ public void disable() { this.enabled = false; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VirtualThreadStressConfig.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VirtualThreadStressConfig.java index 6a3b2729..58867028 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VirtualThreadStressConfig.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VirtualThreadStressConfig.java @@ -47,6 +47,7 @@ public VirtualThreadStressConfig(StressLevel stressLevel, this.enableVirtualThreadEvents = enableVirtualThreadEvents; this.timeoutMs = timeoutMs; } + /** {@return the builder} */ public static Builder builder() { return new Builder(); @@ -82,26 +83,51 @@ public static class Builder { private boolean detectThreadPinning = true; private boolean enableVirtualThreadEvents = false; private long timeoutMs = 30000; // 30 seconds for extreme stress tests + /** + * Stress level. + * + * @param level the level + * @return the stress level + */ public Builder stressLevel(StressLevel level) { this.stressLevel = level; return this; } + /** + * Detect thread pinning. + * + * @param detect the detect + * @return the detect thread pinning + */ public Builder detectThreadPinning(boolean detect) { this.detectThreadPinning = detect; return this; } + /** + * Enable virtual thread events. + * + * @param enable the enable + * @return the enable virtual thread events + */ public Builder enableVirtualThreadEvents(boolean enable) { this.enableVirtualThreadEvents = enable; return this; } + /** + * Timeout in milliseconds. + * + * @param timeout the timeout + * @return the timeout in milliseconds + */ public Builder timeoutMs(long timeout) { this.timeoutMs = timeout; return this; } + /** {@return the build} */ public VirtualThreadStressConfig build() { return new VirtualThreadStressConfig(stressLevel, detectThreadPinning, diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VisibilityMonitor.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VisibilityMonitor.java index 03717b9a..390f02ce 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VisibilityMonitor.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/VisibilityMonitor.java @@ -99,16 +99,25 @@ public VisibilityReport analyzeVisibility() { public VisibilityReport analyze() { return analyzeVisibility(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { fieldSnapshots.clear(); seenValues.clear(); invocationCounter.set(0); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; @@ -117,6 +126,7 @@ public void enable() { public static class VisibilityReport { /** The suspected fields. */ public final Set suspectedFields = new HashSet<>(); + /** The field value variations. */ public final Map>> fieldValueVariations = new HashMap<>(); /** {@return whether there are issues} */ diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WakeupDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WakeupDetector.java index f480e95e..3171b354 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WakeupDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WakeupDetector.java @@ -143,14 +143,23 @@ public WakeupReport analyzeWakeups() { public WakeupReport analyze() { return analyzeWakeups(); } + /** + * Clears recorded the observation so this instance can be reused for the next run. + */ public void reset() { monitors.clear(); } + /** + * Disable. + */ public void disable() { enabled = false; } + /** + * Enable. + */ public void enable() { enabled = true; diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WeakHashMapSharedDetector.java b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WeakHashMapSharedDetector.java index d6c9aa7b..fd7f78f5 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WeakHashMapSharedDetector.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/diagnostics/WeakHashMapSharedDetector.java @@ -88,6 +88,11 @@ public void recordAccess(Map map, String name, Thread thread) { s.accessingThreadIds.add(thread.threadId()); s.accessingThreadNames.add(thread.getName()); } + /** + * Analyses what has been recorded about the observation and builds the report for it. + * + * @return the analyze + */ public Report analyze() { Report r = new Report(); diff --git a/async-test-lib/src/main/java/se/deversity/asynctest/spi/DetectorRegistry.java b/async-test-lib/src/main/java/se/deversity/asynctest/spi/DetectorRegistry.java index 04e858b2..5c1c96a7 100644 --- a/async-test-lib/src/main/java/se/deversity/asynctest/spi/DetectorRegistry.java +++ b/async-test-lib/src/main/java/se/deversity/asynctest/spi/DetectorRegistry.java @@ -224,10 +224,16 @@ public List analyzeAll() { } return out; } + /** + * Fire on test start. + */ public void fireOnTestStart() { for (Detector d : byType.values()) d.onTestStart(); } + /** + * Fire on test end. + */ public void fireOnTestEnd() { for (Detector d : byType.values()) d.onTestEnd();