diff --git a/README.md b/README.md index 841ad51..7637f49 100644 --- a/README.md +++ b/README.md @@ -43,11 +43,11 @@ Annotations placed on packages affect tests for all classes and methods under te Annotations placed on classes affect tests for that class and all it's methods under test, overriding package level annotations. Annotations placed on methods affect just that method under test, overriding package and class level annotations. -| Annotation | Equivalent `dcover create` option | -|:----------------------------|:--------------------------------------------------| -| `@InTestsMock` | `--mock`, `--disable-mock-inputs` | -| `@InTestsMockConstruction` | `--mock-construction` | -| `@InTestsMockStatic` | `--mock-static` | +| Annotation | Equivalent `dcover create` option | +|:---------------------------|:----------------------------------| +| `@InTestsMock` | `--mock`, `--disable-mock-inputs` | +| `@InTestsMockConstruction` | `--mock-construction` | +| `@InTestsMockStatic` | `--mock-static` | The annotations will be respected by Diffblue Cover via both command line and IntelliJ Plugin. When used from the command line in conjunction with equivalent options then the command line options take priority over the annotations found. @@ -104,3 +104,157 @@ public class ClassUnderTest { } } ``` + +### Using `@InTestsUseClasses` + +The `@InTestsUseClasses` annotation allows the user to recommend specific `Class` literal values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated with an example class literal to achieve a positive test: + +```java +public static boolean isAnnotation(@InTestsUseClasses(Nullable.class) Class theClass) { + return theClass.isAnnotation(); +} +``` + +### Using `@InTestsUseStrings` + +The `@InTestsUseStrings` annotation allows the user to recommend specific `String` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated with some genuine examples of song titles that can be used to achieve coverage: + +```java +public static boolean isDayRelatedSongTitle(@InTestsUseStrings({"I Don't Like Mondays", "Here Comes The Weekend"}) String title) { + return Stream.of(DayOfWeek.values()) + .map(DayOfWeek::name) + .map(String::toLowerCase) + .anyMatch(title.toLowerCase()::contains); +} +``` + +### Using `@InTestsUseCharacters` + +The `@InTestsUseCharacters` annotation allows the user to recommend specific `char` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated with a genuine examples characters that make up a Unicode surrogate pair that can be used to achieve a positive test: + +```java +@Nullable +public static Integer toNullableCodePoint( + @InTestsUseCharacters('\uD801') char high, + @InTestsUseCharacters('\uDC37') char low) { + if (Character.isSurrogatePair(high, low)) { + return Character.toCodePoint(high, low); + } + return null; +} +``` + +### Using `@InTestsUseBytes` + +The `@InTestsUseBytes` annotation allows the user to recommend specific `byte` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated to use a specific preferred value: + +```java +public static String toUpperHexString(@InTestsUseBytes((byte)0xD1) byte input) { + return Long.toHexString(input).toUpperCase(); +} +``` + +### Using `@InTestsUseShorts` + +The `@InTestsUseShorts` annotation allows the user to recommend specific `short` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated to use a specific preferred value: + +```java +public static String toUpperHexString(@InTestsUseShorts((short)0xD1FF) short input) { + return Long.toHexString(input).toUpperCase(); +} +``` + +### Using `@InTestsUseIntegers` + +The `@InTestsUseIntegers` annotation allows the user to recommend specific `int` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated to use a specific preferred value: + +```java +public static String toUpperHexString(@InTestsUseIntegers(0xD1FFB) int input) { + return Long.toHexString(input).toUpperCase(); +} +``` + +### Using `@InTestsUseLongs` + +The `@InTestsUseLongs` annotation allows the user to recommend specific `long` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated to use a specific preferred value: + +```java +public static String toUpperHexString(@InTestsUseLongs(0xD1FFBL) long input) { + return Long.toHexString(input).toUpperCase(); +} +``` + +### Using `@InTestsUseFloats` + +The `@InTestsUseFloats` annotation allows the user to recommend specific `float` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated to use a specific preferred value: + +```java +public static boolean isNearPi(@InTestsUseFloats(3.14159f) float input) { + return Float.toString(input).startsWith("3.14"); +} +``` + +### Using `@InTestsUseDoubles` + +The `@InTestsUseDoubles` annotation allows the user to recommend specific `double` values to use in tests. +Sometimes this can be useful to control the values used for cosmetic reasons, but it can also be useful when Cover is unable to identify values to cover all cases. +For example the following method is annotated to use a specific preferred value: + +```java +public static boolean isNearPi(@InTestsUseDoubles(Math.PI) float input) { + return Double.toString(input).startsWith("3.14"); +} +``` + +### Using `@InterestingTestFactory` + +Indicates the annotated method as a useful factory method for use in tests. +Cover will automatically recognise factory methods that simply return a newly created instance, but may not identify more complicated factories. +This annotation allows such factory methods to be manually annotated so that Cover considers them for producing inputs. +For example the following method under test takes a `User` as input, but the `User` constructor is private and Cover doesn't naturally consider `ofStaff(String)` to be a safe factory method to call. +By annotating the `ofStaff(String)` with `@InterstingTestFactory` we can tell Cover that this should be considered a good factory method to use in tests. + +```java +public String getUserDisplayString(User user) { + if (user.manager) { + return user.username + " (manager)"; + } + else { + return user.username; + } +} + +class User { + private static Map staff = new HashMap(); + + @InterestingTestFactory + public static User ofStaff(String name) { + return staff.computeIfAbsent(name, ignored -> new User(name, false)); + } + + public final String username; + public final boolean manager; + + private User(String username, boolean manager) { + this.username = username; + this.manager = manager; + } +} +``` + diff --git a/pom.xml b/pom.xml index 360768c..48a68f7 100644 --- a/pom.xml +++ b/pom.xml @@ -12,9 +12,7 @@ ~ express or implied. See the License for the specific language governing ~ permissions and limitations under the License. --> - + 4.0.0 com.diffblue.cover cover-annotations @@ -22,9 +20,7 @@ jar Cover Annotations - - Annotations for end users to enable fine-grained control of Diffblue Cover. - + Annotations for end users to enable fine-grained control of Diffblue Cover. https://www.diffblue.com/ @@ -45,103 +41,166 @@ - https://github.com/diffblue/cover-annotations scm:git:git://github.com/diffblue/cover-annotations.git + https://github.com/diffblue/cover-annotations + + + ossrh + + https://oss.sonatype.org/content/repositories/snapshots + + + UTF-8 UTF-8 3.13.0 3.6.3 3.3.0 + 2.43.0 + 1.17.0 3.2.1 - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - - - stdbuild - - true - - + + stdbuild + + true + + + - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.plugin.version} + + 1.8 + 1.8 + 8 + + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven.compiler.plugin.version} - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-source-plugin - ${maven.source.plugin.version} - - - attach-sources - - jar - - - - + + + org.apache.maven.plugins + maven-source-plugin + ${maven.source.plugin.version} + + + attach-sources + + jar + + + + - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven.javadoc.plugin.version} - - - attach-javadocs - - jar - - - - - - - - - sign - - false - - - - - - org.apache.maven.plugins - maven-gpg-plugin - ${gpg.plugin.version} - - - sign-artifacts - verify - - sign - - - - + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.javadoc.plugin.version} + + + attach-javadocs + + jar + + + 8 + + + + + + + com.diffplug.spotless + spotless-maven-plugin + ${maven.spotless.plugin.version} + + origin/main + + + **/pom.xml + + + + + + **/*.java + + + /* + * Copyright $YEAR Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + package + + + ${google.java.format.version} + + + + + + **/*.md + + + + + + + default-cli + + apply + + generate-sources + + + - - - + + + + + sign + + false + + + + + + org.apache.maven.plugins + maven-gpg-plugin + ${gpg.plugin.version} + + + sign-artifacts + + sign + + verify + + + + + + diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsMock.java b/src/main/java/com/diffblue/cover/annotations/InTestsMock.java index 8f76e3f..882fdd9 100644 --- a/src/main/java/com/diffblue/cover/annotations/InTestsMock.java +++ b/src/main/java/com/diffblue/cover/annotations/InTestsMock.java @@ -12,7 +12,6 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ - package com.diffblue.cover.annotations; import static com.diffblue.cover.annotations.MockDecision.RECOMMENDED; @@ -40,6 +39,10 @@ @Retention(CLASS) @Target({PACKAGE, TYPE, METHOD}) @interface Repeatable { + + /** + * @return the repeated {@link InTestsMock} annotations. + */ InTestsMock[] value(); } diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsMockConstruction.java b/src/main/java/com/diffblue/cover/annotations/InTestsMockConstruction.java index 633e8a3..0f0470e 100644 --- a/src/main/java/com/diffblue/cover/annotations/InTestsMockConstruction.java +++ b/src/main/java/com/diffblue/cover/annotations/InTestsMockConstruction.java @@ -12,7 +12,6 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ - package com.diffblue.cover.annotations; import static com.diffblue.cover.annotations.MockDecision.RECOMMENDED; @@ -40,6 +39,10 @@ @Retention(CLASS) @Target({PACKAGE, TYPE, METHOD}) @interface Repeatable { + + /** + * @return the repeated {@link InTestsMockConstruction} annotations. + */ InTestsMockConstruction[] value(); } diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsMockStatic.java b/src/main/java/com/diffblue/cover/annotations/InTestsMockStatic.java index 535c184..c100db6 100644 --- a/src/main/java/com/diffblue/cover/annotations/InTestsMockStatic.java +++ b/src/main/java/com/diffblue/cover/annotations/InTestsMockStatic.java @@ -12,7 +12,6 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ - package com.diffblue.cover.annotations; import static com.diffblue.cover.annotations.MockDecision.RECOMMENDED; @@ -40,6 +39,10 @@ @Retention(CLASS) @Target({PACKAGE, TYPE, METHOD}) @interface Repeatable { + + /** + * @return the repeated {@link InTestsMockStatic} annotations. + */ InTestsMockStatic[] value(); } diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseBytes.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseBytes.java new file mode 100644 index 0000000..40a4c0c --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseBytes.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * byte} or {@link Byte}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseBytes.Repeatable.class) +public @interface InTestsUseBytes { + + /** Collects multiple {@link InTestsUseBytes} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseBytes} annotations. + */ + InTestsUseBytes[] value(); + } + + /** + * @return {@code byte} values that should be tried. + */ + byte[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseCharacters.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseCharacters.java new file mode 100644 index 0000000..c394df0 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseCharacters.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * char} or {@link Character}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseCharacters.Repeatable.class) +public @interface InTestsUseCharacters { + + /** Collects multiple {@link InTestsUseCharacters} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseCharacters} annotations. + */ + InTestsUseCharacters[] value(); + } + + /** + * @return {@link Character} values that should be tried. + */ + char[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseClasses.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseClasses.java new file mode 100644 index 0000000..8cdb654 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseClasses.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@link + * Class}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseClasses.Repeatable.class) +public @interface InTestsUseClasses { + + /** Collects multiple {@link InTestsUseClasses} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseClasses} annotations. + */ + InTestsUseClasses[] value(); + } + + /** + * @return {@link Class} values that should be tried. + */ + Class[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseDoubles.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseDoubles.java new file mode 100644 index 0000000..4311c76 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseDoubles.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * double} or {@link Double}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseDoubles.Repeatable.class) +public @interface InTestsUseDoubles { + + /** Collects multiple {@link InTestsUseDoubles} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseDoubles} annotations. + */ + InTestsUseDoubles[] value(); + } + + /** + * @return {@code double} values that should be tried. + */ + double[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseFloats.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseFloats.java new file mode 100644 index 0000000..6829fe9 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseFloats.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * float} or {@link Float}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseFloats.Repeatable.class) +public @interface InTestsUseFloats { + + /** Collects multiple {@link InTestsUseFloats} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseFloats} annotations. + */ + InTestsUseFloats[] value(); + } + + /** + * @return {@code float} values that should be tried. + */ + float[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseIntegers.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseIntegers.java new file mode 100644 index 0000000..4950bef --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseIntegers.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * int} or {@link Integer}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseIntegers.Repeatable.class) +public @interface InTestsUseIntegers { + + /** Collects multiple {@link InTestsUseIntegers} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseIntegers} annotations. + */ + InTestsUseIntegers[] value(); + } + + /** + * @return {@code int} values that should be tried. + */ + int[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseLongs.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseLongs.java new file mode 100644 index 0000000..b01a86d --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseLongs.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * long} or {@link Long}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseLongs.Repeatable.class) +public @interface InTestsUseLongs { + + /** Collects multiple {@link InTestsUseLongs} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseLongs} annotations. + */ + InTestsUseLongs[] value(); + } + + /** + * @return {@code long} values that should be tried. + */ + long[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseShorts.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseShorts.java new file mode 100644 index 0000000..8c25eb3 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseShorts.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@code + * short} or {@link Short}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseShorts.Repeatable.class) +public @interface InTestsUseShorts { + + /** Collects multiple {@link InTestsUseShorts} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseShorts} annotations. + */ + InTestsUseShorts[] value(); + } + + /** + * @return {@code short} values that should be tried. + */ + short[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InTestsUseStrings.java b/src/main/java/com/diffblue/cover/annotations/InTestsUseStrings.java new file mode 100644 index 0000000..e29b286 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InTestsUseStrings.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Identifies values that should be considered when writing tests that require inputs of type {@link + * String}. + */ +@Retention(RUNTIME) +@Repeatable(InTestsUseStrings.Repeatable.class) +public @interface InTestsUseStrings { + + /** Collects multiple {@link InTestsUseStrings} annotations. */ + @Retention(RUNTIME) + @Target({PACKAGE, TYPE, METHOD, PARAMETER}) + @interface Repeatable { + + /** + * @return the repeated {@link InTestsUseStrings} annotations. + */ + InTestsUseStrings[] value(); + } + + /** + * @return {@link String} values that should be tried. + */ + String[] value() default {}; +} diff --git a/src/main/java/com/diffblue/cover/annotations/InterestingTestFactory.java b/src/main/java/com/diffblue/cover/annotations/InterestingTestFactory.java new file mode 100644 index 0000000..0eb68a6 --- /dev/null +++ b/src/main/java/com/diffblue/cover/annotations/InterestingTestFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.diffblue.cover.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** Indicates the annotated method as a useful factory method for use in tests. */ +@Retention(RUNTIME) +@Target(METHOD) +public @interface InterestingTestFactory {} diff --git a/src/main/java/com/diffblue/cover/annotations/MockDecision.java b/src/main/java/com/diffblue/cover/annotations/MockDecision.java index 43d2db4..4a329f2 100644 --- a/src/main/java/com/diffblue/cover/annotations/MockDecision.java +++ b/src/main/java/com/diffblue/cover/annotations/MockDecision.java @@ -12,10 +12,14 @@ * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ - package com.diffblue.cover.annotations; +/** + * A decision indicating that a particular annotation indicating that mocking should be required vs + * recommended vs allowed vs forbidden from mocking. + */ public enum MockDecision { + /** Mocking is required, other instantiations are not permitted. */ REQUIRED, diff --git a/src/test/java/com/example/PalindromeExample.java b/src/test/java/com/example/PalindromeExample.java new file mode 100644 index 0000000..7fd0ac9 --- /dev/null +++ b/src/test/java/com/example/PalindromeExample.java @@ -0,0 +1,49 @@ +/* + * Copyright 2024 Diffblue Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package com.example; + +import com.diffblue.cover.annotations.InTestsUseLongs; +import com.diffblue.cover.annotations.InTestsUseStrings; + +public class PalindromeExample { + @InTestsUseLongs({1L, 123454321L, 12345L}) + public boolean isPalindrome(long value) { + return isPalindrome(Long.toString(value)); + } + + @InTestsUseStrings({"Madam I'm Adam", "Nurses run", "Clearly not a palindrome!"}) + public boolean isPalindrome(String text) { + int left = 0, right = text.length() - 1; + while (left < right) { + final char leftChar = text.charAt(left); + if (!Character.isLetterOrDigit(leftChar)) { + ++left; + continue; + } + final char rightChar = text.charAt(right); + if (!Character.isLetterOrDigit(rightChar)) { + --right; + continue; + } + if (Character.toLowerCase(leftChar) == Character.toLowerCase(rightChar)) { + ++left; + --right; + continue; + } + return false; + } + return true; + } +}