From 9ada38c4c355be119e021cf76a3d8f102583bf96 Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Wed, 21 Aug 2024 09:55:41 -0400 Subject: [PATCH 1/7] Test and Test-and-Set for HandlerFactory --- .../sdk/internal/HandlerFactory.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java b/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java index 0dcc6cf..a53ec1b 100644 --- a/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java +++ b/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java @@ -31,13 +31,20 @@ private static boolean didLoadCatalog() { return theClass != null; } - public static synchronized OutputHandler get() { + public static OutputHandler get() { if (HANDLER_INSTANCE == null) { - HANDLER_INSTANCE = - VoidstarHandler.get().orElseGet(() -> - LocalHandler.get().orElseGet(() -> - NoOpHandler.get().orElseThrow(RuntimeException::new)) - ); + HANDLER_INSTANCE = getInternal(); + } + return HANDLER_INSTANCE; + } + + private static synchronized OutputHandler getInternal() { + if (HANDLER_INSTANCE == null) { + HANDLER_INSTANCE = + VoidstarHandler.get().orElseGet(() -> + LocalHandler.get().orElseGet(() -> + NoOpHandler.get().orElseThrow(RuntimeException::new)) + ); } return HANDLER_INSTANCE; } From 8730fe30ccb1559b8f1ee87b99e30e8efb1bd06e Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Wed, 21 Aug 2024 10:10:05 -0400 Subject: [PATCH 2/7] Switch > If --- .../antithesis/sdk/assertions/Assertion.java | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/antithesis/sdk/assertions/Assertion.java b/src/main/java/com/antithesis/sdk/assertions/Assertion.java index 58bf77c..4322ff9 100644 --- a/src/main/java/com/antithesis/sdk/assertions/Assertion.java +++ b/src/main/java/com/antithesis/sdk/assertions/Assertion.java @@ -102,19 +102,24 @@ private enum AssertType { // LocationInfo is only available through previously seen rawAssert() // invocations which use the alternate Assertion instance constructor - // shown below. There is no attempt to derive LocationInfo programatically + // shown below. There is no attempt to derive LocationInfo programmatically // at runtime. AssertType userAssertType; - if (assertType.equals("always")) { - userAssertType = Assertion.AssertType.Always; - } else if (assertType.equals("sometimes")) { - userAssertType = Assertion.AssertType.Sometimes; - } else if (assertType.equals("reachability")) { - userAssertType = Assertion.AssertType.Reachability; - } else { - userAssertType = Assertion.AssertType.Unknown; + switch (assertType) { + case "always": + userAssertType = AssertType.Always; + break; + case "sometimes": + userAssertType = AssertType.Sometimes; + break; + case "reachability": + userAssertType = AssertType.Reachability; + break; + default: + userAssertType = AssertType.Unknown; + break; } this.assertType = userAssertType; @@ -150,14 +155,19 @@ private enum AssertType { ) { AssertType userAssertType; - if (assertType.equals("always")) { - userAssertType = Assertion.AssertType.Always; - } else if (assertType.equals("sometimes")) { - userAssertType = Assertion.AssertType.Sometimes; - } else if (assertType.equals("reachability")) { - userAssertType = Assertion.AssertType.Reachability; - } else { - userAssertType = Assertion.AssertType.Unknown; + switch (assertType) { + case "always": + userAssertType = AssertType.Always; + break; + case "sometimes": + userAssertType = AssertType.Sometimes; + break; + case "reachability": + userAssertType = AssertType.Reachability; + break; + default: + userAssertType = AssertType.Unknown; + break; } this.assertType = userAssertType; From 50279440df6ef1c5b654370603f49ac9b911322e Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Wed, 21 Aug 2024 10:23:09 -0400 Subject: [PATCH 3/7] Cleanup comments and dead imports --- .../java/com/antithesis/sdk/assertions/LocationInfo.java | 6 ------ .../com/antithesis/sdk/internal/INativeInstrumentation.java | 1 - .../sdk/internal/NativeInstrumentationFactory.java | 4 ---- 3 files changed, 11 deletions(-) diff --git a/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java b/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java index 469da3d..2a571ca 100644 --- a/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java +++ b/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java @@ -1,12 +1,6 @@ package com.antithesis.sdk.assertions; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.node.ObjectNode; class LocationInfo { @JsonProperty("class") diff --git a/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java b/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java index 9d841a2..afafa6d 100644 --- a/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java +++ b/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java @@ -1,5 +1,4 @@ package com.antithesis.sdk.internal; -// [WAS] package com.antithesis.instrumentation; /** * JNA will create bindings to libvoidstar.so based on diff --git a/src/main/java/com/antithesis/sdk/internal/NativeInstrumentationFactory.java b/src/main/java/com/antithesis/sdk/internal/NativeInstrumentationFactory.java index 2cf28a4..06dafd4 100644 --- a/src/main/java/com/antithesis/sdk/internal/NativeInstrumentationFactory.java +++ b/src/main/java/com/antithesis/sdk/internal/NativeInstrumentationFactory.java @@ -1,5 +1,4 @@ package com.antithesis.sdk.internal; -// [WAS] package com.antithesis.instrumentation; import com.sun.jna.Library; import com.sun.jna.Native; @@ -41,12 +40,9 @@ private interface AntithesisInstrumentationLibrary extends INativeInstrumentatio nativeInterface = Native.load(NATIVE_LIBRARY_NAME, AntithesisInstrumentationLibrary.class); } catch (UnsatisfiedLinkError error) { // load() throws an UnsatisfiedLinkError if it can't find the native library - // logger.log(Level.SEVERE, "Could not find " + NATIVE_LIBRARY_NAME, error); logger.log(Level.INFO, "Could not find " + NATIVE_LIBRARY_NAME); throw error; - // TODO (@shomik) Explicitly handle NoClassDefFoundError to facilitate using JNA as a compileOnly dep and providing a concrete implementation at jar runtime } catch (Throwable t) { - // logger.log(Level.SEVERE, "Could not find " + NATIVE_LIBRARY_NAME, t); logger.log(Level.INFO, "Could not find " + NATIVE_LIBRARY_NAME); throw new RuntimeException(t); } From 066f9a378634fa1ba9917fc373db0ccb4ecde241 Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Wed, 21 Aug 2024 16:40:39 -0400 Subject: [PATCH 4/7] Utilize lombok builder for assertion generation --- src/main/java/com/antithesis/sdk/assertions/lombok.config | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/com/antithesis/sdk/assertions/lombok.config diff --git a/src/main/java/com/antithesis/sdk/assertions/lombok.config b/src/main/java/com/antithesis/sdk/assertions/lombok.config new file mode 100644 index 0000000..7c3340f --- /dev/null +++ b/src/main/java/com/antithesis/sdk/assertions/lombok.config @@ -0,0 +1,6 @@ +a +sdgaehaewrhaerhahe + +lombok.addLombokGeneratedAnnotation = false +lombok.accessors.chain = true +lombok.accessors.fluent = true \ No newline at end of file From 3a5df80f4e3cff422459d0b8a7414a89657d5e4b Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Wed, 21 Aug 2024 16:48:28 -0400 Subject: [PATCH 5/7] Annotate assertion arguments with final to enable pooling --- .gitignore | 5 +- build.gradle | 8 +- .../antithesis/sdk/assertions/Assertion.java | 99 +-------- .../antithesis/sdk/assertions/Assertions.java | 193 ++++++++++++------ .../sdk/assertions/LocationInfo.java | 13 +- 5 files changed, 146 insertions(+), 172 deletions(-) diff --git a/.gitignore b/.gitignore index 16acba2..f655372 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Ignore Gradle project-specific cache directory .gradle -# Ignore Gradle build output directory +# Ignore Gradle build outputs build result* + +# Ignore IDE-specific directory +.idea \ No newline at end of file diff --git a/build.gradle b/build.gradle index e39f9fb..a9cd48b 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,12 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.2.3' testImplementation 'net.java.dev.jna:jna:5.13.0' + + compileOnly 'org.projectlombok:lombok:1.18.34' + annotationProcessor 'org.projectlombok:lombok:1.18.34' + + testCompileOnly 'org.projectlombok:lombok:1.18.34' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.34' } compileJava { @@ -51,7 +57,7 @@ task generateJavadoc(type: Javadoc) { // Hack to enable Javadoc to compile while exclude internal functions var sourceSetDirectories = sourceSets.main.java.srcDirs.join(":") - options.addStringOption("-source-path", sourceSetDirectories) + options.addStringOption("sourcepath", sourceSetDirectories) classpath = sourceSets.main.compileClasspath destinationDir = file("${buildDir}/docs/javadoc") diff --git a/src/main/java/com/antithesis/sdk/assertions/Assertion.java b/src/main/java/com/antithesis/sdk/assertions/Assertion.java index 4322ff9..b2e852a 100644 --- a/src/main/java/com/antithesis/sdk/assertions/Assertion.java +++ b/src/main/java/com/antithesis/sdk/assertions/Assertion.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +@lombok.Builder @lombok.AllArgsConstructor final class Assertion { private static final LocationInfo NoInfo = new LocationInfo( @@ -23,7 +24,7 @@ private static class TrackingInfo { int failCount = 0; LocationInfo locInfo; - public TrackingInfo(LocationInfo locInfo) { + public TrackingInfo(final LocationInfo locInfo) { this.locInfo = locInfo; } @@ -35,7 +36,7 @@ protected void trackFail() { this.failCount++; } - protected void setLocationInfo(LocationInfo locInfo) { + protected void setLocationInfo(final LocationInfo locInfo) { this.locInfo = locInfo; } @@ -64,7 +65,7 @@ public void serialize(AssertType value, JsonGenerator jsonGen, SerializerProvide MAPPER = mapper; } - private enum AssertType { + public enum AssertType { Always, Sometimes, Reachability, Unknown } @@ -95,95 +96,7 @@ private enum AssertType { @JsonProperty("details") final private ObjectNode details; - // ---------------------------------------------------------------------- - // Used for normal runtime calls - // ---------------------------------------------------------------------- - Assertion(final String assertType, String displayType, final boolean condition, final String message, final ObjectNode details, final boolean hit, boolean mustHit) { - - // LocationInfo is only available through previously seen rawAssert() - // invocations which use the alternate Assertion instance constructor - // shown below. There is no attempt to derive LocationInfo programmatically - // at runtime. - - AssertType userAssertType; - - switch (assertType) { - case "always": - userAssertType = AssertType.Always; - break; - case "sometimes": - userAssertType = AssertType.Sometimes; - break; - case "reachability": - userAssertType = AssertType.Reachability; - break; - default: - userAssertType = AssertType.Unknown; - break; - } - - this.assertType = userAssertType; - this.displayType = displayType; - this.location = getLocationInfo(message); - this.id = message; - this.condition = condition; - this.message = message; - this.details = details; - this.hit = hit; - this.mustHit = mustHit; - - this.trackEntry(); - } - - // ---------------------------------------------------------------------- - // Used for registration and DIY'ers - // ---------------------------------------------------------------------- - Assertion( - String assertType, - String displayType, - String className, - String functionName, - String fileName, - int begin_line, - int begin_column, - String id, - boolean condition, - String message, - ObjectNode details, // TODO: something in Java 8 that is better? - boolean hit, - boolean mustHit - ) { - AssertType userAssertType; - - switch (assertType) { - case "always": - userAssertType = AssertType.Always; - break; - case "sometimes": - userAssertType = AssertType.Sometimes; - break; - case "reachability": - userAssertType = AssertType.Reachability; - break; - default: - userAssertType = AssertType.Unknown; - break; - } - - this.assertType = userAssertType; - this.displayType = displayType; - this.location = new LocationInfo(className, functionName, fileName, begin_line, begin_column); - this.id = id; - this.message = message; - this.details = details; - this.condition = condition; - this.hit = hit; - this.mustHit = mustHit; - - this.trackEntry(); - } - - private LocationInfo getLocationInfo(String id) { + public static LocationInfo getLocationInfo(final String id) { TrackingInfo maybeTrackingInfo = TRACKER.get(id); if (maybeTrackingInfo == null) { return NoInfo; @@ -191,7 +104,7 @@ private LocationInfo getLocationInfo(String id) { return maybeTrackingInfo.getLocationInfo(); } - private void trackEntry() { + public void trackEntry() { // Requirement: Catalog entries must always will emit() if (!this.hit) { if (!TRACKER.containsKey(this.id)) { diff --git a/src/main/java/com/antithesis/sdk/assertions/Assertions.java b/src/main/java/com/antithesis/sdk/assertions/Assertions.java index b762325..961e61b 100644 --- a/src/main/java/com/antithesis/sdk/assertions/Assertions.java +++ b/src/main/java/com/antithesis/sdk/assertions/Assertions.java @@ -9,25 +9,47 @@ final public class Assertions { * called at least once. The corresponding test property will be viewable in the Antithesis SDK: Always group of your triage report. * * @param condition the result of evaluating the assertion at runtime - * @param message the unique text associated with the assertion - * @param details additional values describing the program state when the assertion was evaluated at runtime + * @param message the unique text associated with the assertion + * @param details additional values describing the program state when the assertion was evaluated at runtime */ - public static void always(boolean condition, String message, ObjectNode details) { - Assertion assertion = new Assertion("always", "Always", condition, message, details, true, true); + public static void always(final boolean condition, final String message, final ObjectNode details) { + Assertion.builder() + .assertType(Assertion.AssertType.Always) + .condition(condition) + .details(details) + .displayType("Always") + .hit(true) + .id(message) + .location(Assertion.getLocationInfo(message)) + .message(message) + .mustHit(true) + .build() + .trackEntry(); } /** - * Assert that condition is true every time this function is called. The corresponding + * Assert that condition is true every time this function is called. The corresponding * test property will pass even if the assertion is never encountered. - + *

* The corresponding test property will be viewable in the Antithesis SDK: Always group of your triage report. * * @param condition the result of evaluating the assertion at runtime - * @param message the unique text associated with the assertion - * @param details additional values describing the program state when the assertion was evaluated at runtime + * @param message the unique text associated with the assertion + * @param details additional values describing the program state when the assertion was evaluated at runtime */ - public static void alwaysOrUnreachable(boolean condition, String message, ObjectNode details) { - Assertion assertion = new Assertion("always", "AlwaysOrUnreachable", condition, message, details, true, true); + public static void alwaysOrUnreachable(final boolean condition, final String message, final ObjectNode details) { + Assertion.builder() + .assertType(Assertion.AssertType.Always) + .condition(condition) + .details(details) + .displayType("AlwaysOrUnreachable") + .hit(true) + .id(message) + .location(Assertion.getLocationInfo(message)) + .message(message) + .mustHit(false) + .build() + .trackEntry(); } /** @@ -36,11 +58,22 @@ public static void alwaysOrUnreachable(boolean condition, String message, Object * This test property will be viewable in the Antithesis SDK: Sometimes group. * * @param condition the result of evaluating the assertion at runtime - * @param message the unique text associated with the assertion - * @param details additional values describing the program state when the assertion was evaluated at runtime - */ - public static void sometimes(boolean condition, String message, ObjectNode details) { - Assertion assertion = new Assertion("sometimes", "Sometimes", condition, message, details, true, true); + * @param message the unique text associated with the assertion + * @param details additional values describing the program state when the assertion was evaluated at runtime + */ + public static void sometimes(final boolean condition, final String message, final ObjectNode details) { + Assertion.builder() + .assertType(Assertion.AssertType.Sometimes) + .condition(condition) + .details(details) + .displayType("Sometimes") + .hit(true) + .id(message) + .location(Assertion.getLocationInfo(message)) + .message(message) + .mustHit(true) + .build() + .trackEntry(); } /** @@ -51,9 +84,20 @@ public static void sometimes(boolean condition, String message, ObjectNode detai * * @param message the unique text associated with the assertion * @param details additional values describing the program state when the assertion was evaluated at runtime - */ - public static void unreachable(String message, ObjectNode details) { - Assertion assertion = new Assertion("reachability", "Unreachable", true, message, details, true, false); + */ + public static void unreachable(final String message, final ObjectNode details) { + Assertion.builder() + .assertType(Assertion.AssertType.Reachability) + .condition(false) + .details(details) + .displayType("Unreachable") + .hit(true) + .id(message) + .location(Assertion.getLocationInfo(message)) + .message(message) + .mustHit(false) + .build() + .trackEntry(); } /** @@ -64,72 +108,87 @@ public static void unreachable(String message, ObjectNode details) { * * @param message the unique text associated with the assertion * @param details additional values describing the program state when the assertion was evaluated at runtime - */ - public static void reachable(String message, ObjectNode details) { - Assertion assertion = new Assertion("reachability", "Reachable", true, message, details, true, true); - } + */ + public static void reachable(final String message, final ObjectNode details) { + Assertion.builder() + .assertType(Assertion.AssertType.Reachability) + .condition(true) + .details(details) + .displayType("Reachable") + .hit(true) + .id(message) + .location(Assertion.getLocationInfo(message)) + .message(message) + .mustHit(true) + .build() + .trackEntry(); + } /** * This is a low-level method designed to be used by third-party frameworks. * Regular users of the assertions package should not call it. - * + *

* This is primarily intended for use by adapters from other * diagnostic tools that intend to output Antithesis-style * assertions. - * + *

* Be certain to provide an assertion catalog entry * for each assertion issued with assert_raw(). Assertion catalog * entries are also created using assert_raw(), by setting the value * of the hit parameter to false. - * + *

* Please refer to the general Antithesis documentation regarding the * use of the Fallback SDK * for additional information. * - * @param assertType must be one of "always", "sometimes", "reachability" - * @param displayType one of "Always", "AlwaysOrUnreachable", "Sometimes", "Reachable", "Unreachable" - * @param className the name of the package and class containing this assertion + * @param assertType must be a valid Assertion.AssertType value + * @param displayType one of "Always", "AlwaysOrUnreachable", "Sometimes", "Reachable", "Unreachable" + * @param className the name of the package and class containing this assertion * @param functionName the name of the method containing this assertion - * @param fileName the name of the source file containing this assertion - * @param begin_line the source line number where the assertion is located - * @param begin_column the source column number where the assertion is located - * @param id the unique text associated with the assertion - * @param condition the result of evaluating the assertion at runtime - * @param hit true if the assertion has been evaluated, false if the assertion is being added to the assertion catalog - * @param message the unique text associated with the assertion - * @param details additional values describing the program state when the assertion was evaluated at runtime - * @param hit true if the assertion has been evaluated, false if the assertion is being added to the assertion catalog - * @param mustHit true if the assertion is expected to be evaluated at least once, otherwise false - */ + * @param fileName the name of the source file containing this assertion + * @param beginLine the source line number where the assertion is located + * @param beginColumn the source column number where the assertion is located + * @param id the unique text associated with the assertion + * @param condition the result of evaluating the assertion at runtime + * @param message the unique text associated with the assertion + * @param details additional values describing the program state when the assertion was evaluated at runtime + * @param hit true if the assertion has been evaluated, false if the assertion is being added to the assertion catalog + * @param mustHit true if the assertion is expected to be evaluated at least once, otherwise false + */ public static void rawAssert( - String assertType, - String displayType, - String className, - String functionName, - String fileName, - int begin_line, - int begin_column, - String id, - boolean condition, - String message, - ObjectNode details, - boolean hit, - boolean mustHit + final Assertion.AssertType assertType, + final String displayType, + final String className, + final String functionName, + final String fileName, + final int beginLine, + final int beginColumn, + final String id, + final boolean condition, + final String message, + final ObjectNode details, + final boolean hit, + final boolean mustHit ) { - Assertion assertion = new Assertion( - assertType, - displayType, - className, - functionName, - fileName, - begin_line, - begin_column, - id, - condition, - message, - details, - hit, - mustHit - ); + LocationInfo locationInfo = LocationInfo.builder() + .beginColumn(beginColumn) + .beginLine(beginLine) + .className(className) + .fileName(fileName) + .functionName(functionName) + .build(); + + Assertion.builder() + .assertType(assertType) + .condition(condition) + .details(details) + .displayType(displayType) + .hit(hit) + .id(id) + .location(locationInfo) + .message(message) + .mustHit(mustHit) + .build() + .trackEntry(); } } diff --git a/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java b/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java index 2a571ca..509956d 100644 --- a/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java +++ b/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; +@lombok.Builder @lombok.AllArgsConstructor class LocationInfo { @JsonProperty("class") private String className; @@ -13,16 +14,8 @@ class LocationInfo { private String fileName; @JsonProperty("begin_line") - private int begin_line; + private int beginLine; @JsonProperty("begin_column") - private int begin_column; - - LocationInfo(String className, String functionName, String fileName, int begin_line, int begin_column) { - this.className = className; - this.functionName = functionName; - this.fileName = fileName; - this.begin_line = begin_line; - this.begin_column = begin_column; - } + private int beginColumn; } From 0bf656a3f86fae6d8ba9d3d9a57cc602912fe11d Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Wed, 21 Aug 2024 16:57:59 -0400 Subject: [PATCH 6/7] Refactor visibility of assertion internals --- .../antithesis/sdk/assertions/Assertions.java | 34 +++++++++++++++---- .../{assertions => internal}/Assertion.java | 18 ++++------ .../LocationInfo.java | 4 +-- 3 files changed, 36 insertions(+), 20 deletions(-) rename src/main/java/com/antithesis/sdk/{assertions => internal}/Assertion.java (89%) rename src/main/java/com/antithesis/sdk/{assertions => internal}/LocationInfo.java (86%) diff --git a/src/main/java/com/antithesis/sdk/assertions/Assertions.java b/src/main/java/com/antithesis/sdk/assertions/Assertions.java index 961e61b..ae3fb47 100644 --- a/src/main/java/com/antithesis/sdk/assertions/Assertions.java +++ b/src/main/java/com/antithesis/sdk/assertions/Assertions.java @@ -1,9 +1,29 @@ package com.antithesis.sdk.assertions; +import com.antithesis.sdk.internal.Assertion; +import com.antithesis.sdk.internal.LocationInfo; import com.fasterxml.jackson.databind.node.ObjectNode; final public class Assertions { + /** + * Types of assertions available + */ + public enum AssertType { + /** + * Condition must always be true + */ + Always, + /** + * Condition must be true at least once + */ + Sometimes, + /** + * Indicates if an assertion should be encountered + */ + Reachability + } + /** * Assert that condition is true every time this function is called, and that it is * called at least once. The corresponding test property will be viewable in the Antithesis SDK: Always group of your triage report. @@ -14,7 +34,7 @@ final public class Assertions { */ public static void always(final boolean condition, final String message, final ObjectNode details) { Assertion.builder() - .assertType(Assertion.AssertType.Always) + .assertType(AssertType.Always) .condition(condition) .details(details) .displayType("Always") @@ -39,7 +59,7 @@ public static void always(final boolean condition, final String message, final O */ public static void alwaysOrUnreachable(final boolean condition, final String message, final ObjectNode details) { Assertion.builder() - .assertType(Assertion.AssertType.Always) + .assertType(AssertType.Always) .condition(condition) .details(details) .displayType("AlwaysOrUnreachable") @@ -63,7 +83,7 @@ public static void alwaysOrUnreachable(final boolean condition, final String mes */ public static void sometimes(final boolean condition, final String message, final ObjectNode details) { Assertion.builder() - .assertType(Assertion.AssertType.Sometimes) + .assertType(AssertType.Sometimes) .condition(condition) .details(details) .displayType("Sometimes") @@ -87,7 +107,7 @@ public static void sometimes(final boolean condition, final String message, fina */ public static void unreachable(final String message, final ObjectNode details) { Assertion.builder() - .assertType(Assertion.AssertType.Reachability) + .assertType(AssertType.Reachability) .condition(false) .details(details) .displayType("Unreachable") @@ -111,7 +131,7 @@ public static void unreachable(final String message, final ObjectNode details) { */ public static void reachable(final String message, final ObjectNode details) { Assertion.builder() - .assertType(Assertion.AssertType.Reachability) + .assertType(AssertType.Reachability) .condition(true) .details(details) .displayType("Reachable") @@ -156,7 +176,7 @@ public static void reachable(final String message, final ObjectNode details) { * @param mustHit true if the assertion is expected to be evaluated at least once, otherwise false */ public static void rawAssert( - final Assertion.AssertType assertType, + final AssertType assertType, final String displayType, final String className, final String functionName, @@ -190,5 +210,5 @@ public static void rawAssert( .mustHit(mustHit) .build() .trackEntry(); - } + } } diff --git a/src/main/java/com/antithesis/sdk/assertions/Assertion.java b/src/main/java/com/antithesis/sdk/internal/Assertion.java similarity index 89% rename from src/main/java/com/antithesis/sdk/assertions/Assertion.java rename to src/main/java/com/antithesis/sdk/internal/Assertion.java index b2e852a..f1f0171 100644 --- a/src/main/java/com/antithesis/sdk/assertions/Assertion.java +++ b/src/main/java/com/antithesis/sdk/internal/Assertion.java @@ -1,6 +1,6 @@ -package com.antithesis.sdk.assertions; +package com.antithesis.sdk.internal; -import com.antithesis.sdk.internal.Internal; +import com.antithesis.sdk.assertions.Assertions; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; @@ -14,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap; @lombok.Builder @lombok.AllArgsConstructor -final class Assertion { +public final class Assertion { private static final LocationInfo NoInfo = new LocationInfo( "class", "function", "file", 0, 0); @@ -49,9 +49,9 @@ protected LocationInfo getLocationInfo() { private static final ObjectMapper MAPPER; static { - class LowercaseEnumSerializer extends JsonSerializer { + class LowercaseEnumSerializer extends JsonSerializer { @Override - public void serialize(AssertType value, JsonGenerator jsonGen, SerializerProvider provider) throws IOException { + public void serialize(Assertions.AssertType value, JsonGenerator jsonGen, SerializerProvider provider) throws IOException { jsonGen.writeString(value.name().toLowerCase()); } } @@ -59,18 +59,14 @@ public void serialize(AssertType value, JsonGenerator jsonGen, SerializerProvide ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); - module.addSerializer(AssertType.class, new LowercaseEnumSerializer()); + module.addSerializer(Assertions.AssertType.class, new LowercaseEnumSerializer()); mapper.registerModule(module); MAPPER = mapper; } - public enum AssertType { - Always, Sometimes, Reachability, Unknown - } - @JsonProperty("assert_type") - final private AssertType assertType; + final private Assertions.AssertType assertType; @JsonProperty("display_type") final private String displayType; diff --git a/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java b/src/main/java/com/antithesis/sdk/internal/LocationInfo.java similarity index 86% rename from src/main/java/com/antithesis/sdk/assertions/LocationInfo.java rename to src/main/java/com/antithesis/sdk/internal/LocationInfo.java index 509956d..bb4131e 100644 --- a/src/main/java/com/antithesis/sdk/assertions/LocationInfo.java +++ b/src/main/java/com/antithesis/sdk/internal/LocationInfo.java @@ -1,9 +1,9 @@ -package com.antithesis.sdk.assertions; +package com.antithesis.sdk.internal; import com.fasterxml.jackson.annotation.JsonProperty; @lombok.Builder @lombok.AllArgsConstructor -class LocationInfo { +public class LocationInfo { @JsonProperty("class") private String className; From b45fe7627fc40ec039bf618789054943131353a0 Mon Sep 17 00:00:00 2001 From: Shomik Ghose Date: Thu, 22 Aug 2024 09:30:38 -0400 Subject: [PATCH 7/7] Format code --- build.gradle | 8 ++++---- settings.gradle | 7 ------- .../antithesis/sdk/assertions/Assertions.java | 6 +++--- .../com/antithesis/sdk/assertions/lombok.config | 3 --- .../antithesis/sdk/assertions/package-info.java | 4 ++-- .../com/antithesis/sdk/internal/Assertion.java | 7 ++++--- .../antithesis/sdk/internal/HandlerFactory.java | 2 +- .../sdk/internal/INativeInstrumentation.java | 6 +++++- .../antithesis/sdk/internal/LocationInfo.java | 5 +++-- .../antithesis/sdk/internal/OutputHandler.java | 3 +++ .../sdk/internal/VoidstarHandler.java | 1 + .../com/antithesis/sdk/lifecycle/Lifecycle.java | 14 +++++++------- .../java/com/antithesis/sdk/random/Random.java | 17 +++++++++-------- .../com/antithesis/sdk/random/package-info.java | 4 ++-- 14 files changed, 44 insertions(+), 43 deletions(-) diff --git a/build.gradle b/build.gradle index a9cd48b..e7994b0 100644 --- a/build.gradle +++ b/build.gradle @@ -20,11 +20,11 @@ dependencies { testImplementation 'net.java.dev.jna:jna:5.13.0' compileOnly 'org.projectlombok:lombok:1.18.34' - annotationProcessor 'org.projectlombok:lombok:1.18.34' + annotationProcessor 'org.projectlombok:lombok:1.18.34' - testCompileOnly 'org.projectlombok:lombok:1.18.34' - testAnnotationProcessor 'org.projectlombok:lombok:1.18.34' - } + testCompileOnly 'org.projectlombok:lombok:1.18.34' + testAnnotationProcessor 'org.projectlombok:lombok:1.18.34' +} compileJava { sourceCompatibility = 1.8 diff --git a/settings.gradle b/settings.gradle index 74dad8d..5618b80 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,8 +1 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.8/userguide/multi_project_builds.html in the Gradle documentation. - */ - rootProject.name = 'antithesis-sdk' diff --git a/src/main/java/com/antithesis/sdk/assertions/Assertions.java b/src/main/java/com/antithesis/sdk/assertions/Assertions.java index ae3fb47..c3cbc4f 100644 --- a/src/main/java/com/antithesis/sdk/assertions/Assertions.java +++ b/src/main/java/com/antithesis/sdk/assertions/Assertions.java @@ -142,7 +142,7 @@ public static void reachable(final String message, final ObjectNode details) { .mustHit(true) .build() .trackEntry(); - } + } /** * This is a low-level method designed to be used by third-party frameworks. @@ -166,8 +166,8 @@ public static void reachable(final String message, final ObjectNode details) { * @param className the name of the package and class containing this assertion * @param functionName the name of the method containing this assertion * @param fileName the name of the source file containing this assertion - * @param beginLine the source line number where the assertion is located - * @param beginColumn the source column number where the assertion is located + * @param beginLine the source line number where the assertion is located + * @param beginColumn the source column number where the assertion is located * @param id the unique text associated with the assertion * @param condition the result of evaluating the assertion at runtime * @param message the unique text associated with the assertion diff --git a/src/main/java/com/antithesis/sdk/assertions/lombok.config b/src/main/java/com/antithesis/sdk/assertions/lombok.config index 7c3340f..ac045f6 100644 --- a/src/main/java/com/antithesis/sdk/assertions/lombok.config +++ b/src/main/java/com/antithesis/sdk/assertions/lombok.config @@ -1,6 +1,3 @@ -a -sdgaehaewrhaerhahe - lombok.addLombokGeneratedAnnotation = false lombok.accessors.chain = true lombok.accessors.fluent = true \ No newline at end of file diff --git a/src/main/java/com/antithesis/sdk/assertions/package-info.java b/src/main/java/com/antithesis/sdk/assertions/package-info.java index b1a8456..c4fb051 100644 --- a/src/main/java/com/antithesis/sdk/assertions/package-info.java +++ b/src/main/java/com/antithesis/sdk/assertions/package-info.java @@ -1,11 +1,11 @@ /** * The assertions package enables defining test properties * about your program or workload. - * + *

* Each static method in this package takes a parameter called message, which is * a string literal identifier used to aggregate assertions. * Antithesis generates one test property per unique message This test property will be named message in the triage report. - * + *

* Each static method also takes a parameter called details, which is an ObjectNode reference of optional additional information provided by the user to add context for assertion failures. * The information that is logged will appear in the logs section of a triage report. * Normally the values in details are evaluated at runtime. diff --git a/src/main/java/com/antithesis/sdk/internal/Assertion.java b/src/main/java/com/antithesis/sdk/internal/Assertion.java index f1f0171..461edc4 100644 --- a/src/main/java/com/antithesis/sdk/internal/Assertion.java +++ b/src/main/java/com/antithesis/sdk/internal/Assertion.java @@ -13,11 +13,12 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -@lombok.Builder @lombok.AllArgsConstructor +@lombok.Builder +@lombok.AllArgsConstructor public final class Assertion { private static final LocationInfo NoInfo = new LocationInfo( - "class", "function", "file", 0, 0); + "class", "function", "file", 0, 0); private static class TrackingInfo { int passCount = 0; @@ -104,7 +105,7 @@ public void trackEntry() { // Requirement: Catalog entries must always will emit() if (!this.hit) { if (!TRACKER.containsKey(this.id)) { - TRACKER.put(this.id, new TrackingInfo(this.location)); + TRACKER.put(this.id, new TrackingInfo(this.location)); } this.emit(); return; diff --git a/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java b/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java index a53ec1b..b3e49fd 100644 --- a/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java +++ b/src/main/java/com/antithesis/sdk/internal/HandlerFactory.java @@ -9,7 +9,7 @@ public class HandlerFactory { // Will be initialized through the static 'HandlerFactory.get()' function - private static OutputHandler HANDLER_INSTANCE = null; + private static OutputHandler HANDLER_INSTANCE = null; private final static boolean CATALOG_SENT = didLoadCatalog(); diff --git a/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java b/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java index afafa6d..eb5217a 100644 --- a/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java +++ b/src/main/java/com/antithesis/sdk/internal/INativeInstrumentation.java @@ -6,8 +6,12 @@ */ public interface INativeInstrumentation { long fuzz_get_random(); - void fuzz_json_data( byte[] message, long length ); + + void fuzz_json_data(byte[] message, long length); + void fuzz_flush(); + long init_coverage_module(long edgeCount, byte[] symbolFilePath); + void notify_coverage(long edgePlusModule); } diff --git a/src/main/java/com/antithesis/sdk/internal/LocationInfo.java b/src/main/java/com/antithesis/sdk/internal/LocationInfo.java index bb4131e..6b47217 100644 --- a/src/main/java/com/antithesis/sdk/internal/LocationInfo.java +++ b/src/main/java/com/antithesis/sdk/internal/LocationInfo.java @@ -2,14 +2,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; -@lombok.Builder @lombok.AllArgsConstructor +@lombok.Builder +@lombok.AllArgsConstructor public class LocationInfo { @JsonProperty("class") private String className; @JsonProperty("function") private String functionName; - + @JsonProperty("file") private String fileName; diff --git a/src/main/java/com/antithesis/sdk/internal/OutputHandler.java b/src/main/java/com/antithesis/sdk/internal/OutputHandler.java index df91508..78a5195 100644 --- a/src/main/java/com/antithesis/sdk/internal/OutputHandler.java +++ b/src/main/java/com/antithesis/sdk/internal/OutputHandler.java @@ -2,7 +2,10 @@ public interface OutputHandler { void output(String value); + long random(); + long initializeModuleCoverage(long edgeCount, String symbolFilePath); + void notifyModuleEdge(long edgePlusModule); } diff --git a/src/main/java/com/antithesis/sdk/internal/VoidstarHandler.java b/src/main/java/com/antithesis/sdk/internal/VoidstarHandler.java index 5f071f6..a5ac1fa 100644 --- a/src/main/java/com/antithesis/sdk/internal/VoidstarHandler.java +++ b/src/main/java/com/antithesis/sdk/internal/VoidstarHandler.java @@ -17,6 +17,7 @@ public class VoidstarHandler implements OutputHandler { private VoidstarHandler(final INativeInstrumentation instrumentation) { NATIVE_VOIDSTAR = instrumentation; } + public static Optional get() { try { return Optional.of(new VoidstarHandler(NativeInstrumentationFactory.get())); diff --git a/src/main/java/com/antithesis/sdk/lifecycle/Lifecycle.java b/src/main/java/com/antithesis/sdk/lifecycle/Lifecycle.java index 830d2e2..a142f0e 100644 --- a/src/main/java/com/antithesis/sdk/lifecycle/Lifecycle.java +++ b/src/main/java/com/antithesis/sdk/lifecycle/Lifecycle.java @@ -11,13 +11,13 @@ final public class Lifecycle { * your system and workload are fully initialized. * After this function is called, Antithesis will take a snapshot of your system * and begin injecting faults. - * + *

* Calling this function multiple times or from multiple processes will have no effect. - * Antithesis will treat the first time any process called this function as + * Antithesis will treat the first time any process called this function as * the moment that the setup was completed. * - * @param details additional values describing the program state - * when the setupComplete was evaluated + * @param details additional values describing the program state + * when the setupComplete was evaluated */ public static void setupComplete(final ObjectNode details) { ObjectMapper mapper = new ObjectMapper(); @@ -33,10 +33,10 @@ public static void setupComplete(final ObjectNode details) { } /** - * Indicates to Antithesis that a certain event has been reached. It sends a + * Indicates to Antithesis that a certain event has been reached. It sends a * structured log message to Antithesis that you may later use to aid debugging. - * - * In addition to details, you also provide rawName, + *

+ * In addition to details, you also provide rawName, * which is the name of the event that you are logging. * * @param rawName the name of the event that is being logged diff --git a/src/main/java/com/antithesis/sdk/random/Random.java b/src/main/java/com/antithesis/sdk/random/Random.java index 7942b71..8225239 100644 --- a/src/main/java/com/antithesis/sdk/random/Random.java +++ b/src/main/java/com/antithesis/sdk/random/Random.java @@ -10,6 +10,7 @@ final public class Random { * Returns a long value chosen by Antithesis. You should not * store this value or use it to seed a PRNG, but should use it * immediately. + * * @return Random value */ public static long getRandom() { @@ -17,20 +18,20 @@ public static long getRandom() { } /** - * Returns a randomly chosen item from a list of options. You - * should not store this value, but should use it immediately. + * Returns a randomly chosen item from a list of options. You + * should not store this value, but should use it immediately. *

- * This function is not purely for convenience. Signaling to - * the Antithesis platform that you intend to use a random value - * in a structured way enables it to provide more interesting - * choices over time. + * This function is not purely for convenience. Signaling to + * the Antithesis platform that you intend to use a random value + * in a structured way enables it to provide more interesting + * choices over time. * * @param array An array of items to select from + * @param Type of the array member items * @return Selected item - * @param Type of the array member items */ public static Optional randomChoice(T[] array) { - if(array.length == 0) { + if (array.length == 0) { return Optional.empty(); } else if (array.length == 1) { return Optional.of(array[0]); diff --git a/src/main/java/com/antithesis/sdk/random/package-info.java b/src/main/java/com/antithesis/sdk/random/package-info.java index 722f08f..9023b55 100644 --- a/src/main/java/com/antithesis/sdk/random/package-info.java +++ b/src/main/java/com/antithesis/sdk/random/package-info.java @@ -1,10 +1,10 @@ /** * The random package provides methods that request both structured and unstructured randomness from the Antithesis environment. - * + *

* These methods should not be used to seed a conventional PRNG, and should not have their return values stored and used to make a decision at a later time. * Doing either of these things makes it much harder for the Antithesis platform to control the history of your program's execution, and also makes it harder for Antithesis to learn which inputs provided at which times are most fruitful. * Instead, you should call a method from the random package every time your program or workload needs to make a decision, at the moment that you need to make the decision. - * + *

* These methods are also safe to call outside the Antithesis environment, where * they will fall back on the Java standard class library implementation. */