Skip to content

Commit 9d73475

Browse files
Anmol202005rdiachenko
authored andcommitted
Implemented Input Files based testing
1 parent 4f798b8 commit 9d73475

File tree

11 files changed

+346
-28
lines changed

11 files changed

+346
-28
lines changed

config/import-control-test.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
<allow pkg="org.junit"/>
88
<allow pkg="org.openrewrite"/>
99
<allow pkg="org.checkstyle"/>
10-
</import-control>
10+
<allow pkg="java.io"/>
11+
<allow pkg="java.nio"/>
12+
</import-control>

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@
111111
<activeRecipes>
112112
<recipe>org.checkstyle.autofix.CheckstyleAutoFix</recipe>
113113
</activeRecipes>
114+
<exclusions>
115+
<exclusion>src/test/resources/**</exclusion>
116+
</exclusions>
114117
<recipeArtifactCoordinates>
115118
<coordinate>org.checkstyle.autofix:checkstyle-openrewrite-recipes:1.0.0</coordinate>
116119
</recipeArtifactCoordinates>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package org.checkstyle.autofix;
2+
3+
import org.openrewrite.ExecutionContext;
4+
import org.openrewrite.Recipe;
5+
import org.openrewrite.TreeVisitor;
6+
import org.openrewrite.java.JavaIsoVisitor;
7+
import org.openrewrite.java.tree.J;
8+
9+
/**
10+
* Recipe to rename classes starting with 'Input' to 'Output'.
11+
* For example, a class named InputExample will be renamed to OutputExample.
12+
*/
13+
public class ClassRenameRecipe extends Recipe {
14+
15+
@Override
16+
public String getDisplayName() {
17+
return "Rename Input-prefixed classes";
18+
}
19+
20+
@Override
21+
public String getDescription() {
22+
return "Renames classes from InputXxx to OutputXxx.";
23+
}
24+
25+
@Override
26+
public TreeVisitor<?, ExecutionContext> getVisitor() {
27+
return new ClassRenameVisitor();
28+
}
29+
30+
/**
31+
* A visitor that traverse Java AST nodes and renames classes starting with "Input" to "Output".
32+
*/
33+
private static final class ClassRenameVisitor extends JavaIsoVisitor<ExecutionContext> {
34+
35+
/** The prefix to match in class names. */
36+
private static final String FROM_PREFIX = "Input";
37+
/** The prefix to replace with in class names. */
38+
private static final String TO_PREFIX = "Output";
39+
40+
@Override
41+
public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl,
42+
ExecutionContext executionContext) {
43+
final String newName = renameIfMatch(classDecl.getSimpleName());
44+
final J.ClassDeclaration result;
45+
if (newName != null) {
46+
result = classDecl.withName(classDecl.getName().withSimpleName(newName));
47+
}
48+
else {
49+
result = classDecl;
50+
}
51+
return result;
52+
}
53+
54+
@Override
55+
public J.NewClass visitNewClass(J.NewClass constructorNode,
56+
ExecutionContext executionContext) {
57+
J.NewClass result = constructorNode;
58+
if (constructorNode.getClazz() instanceof J.Identifier) {
59+
final J.Identifier clazz = (J.Identifier) constructorNode.getClazz();
60+
final String newName = renameIfMatch(clazz.getSimpleName());
61+
if (newName != null) {
62+
result = constructorNode.withClazz(clazz.withSimpleName(newName));
63+
}
64+
}
65+
return result;
66+
}
67+
68+
/**
69+
* Checks if a given class name starts with the FROM_PREFIX
70+
* and returns the renamed version with TO_PREFIX.
71+
*
72+
* @param originalName The original class name.
73+
* @return The new class name with TO_PREFIX if matched, otherwise null.
74+
*/
75+
private String renameIfMatch(String originalName) {
76+
final String result;
77+
if (originalName.startsWith(FROM_PREFIX)) {
78+
result = TO_PREFIX + originalName.substring(FROM_PREFIX.length());
79+
}
80+
else {
81+
result = null;
82+
}
83+
return result;
84+
}
85+
}
86+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.checkstyle.autofix.recipe;
2+
3+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
4+
import static org.openrewrite.java.Assertions.java;
5+
6+
import java.io.IOException;
7+
import java.nio.file.Files;
8+
import java.nio.file.Paths;
9+
10+
import org.checkstyle.autofix.ClassRenameRecipe;
11+
import org.openrewrite.Recipe;
12+
import org.openrewrite.test.RewriteTest;
13+
14+
/**
15+
* Base test class for recipe testing that provides common functionality
16+
* for reading test files and executing recipe tests with preprocessing.
17+
*/
18+
public abstract class AbstractRecipeTest implements RewriteTest {
19+
20+
private static final String BASE_TEST_RESOURCES_PATH = "src/test/resources/org"
21+
+ "/checkstyle/autofix/recipe/";
22+
23+
/**
24+
* Creates a preprocessing recipe that normalizes class names from InputXxx to OutputXxx.
25+
* This allows test files to have descriptive names while maintaining consistent class names.
26+
*
27+
* @return the preprocessing recipe
28+
*/
29+
private Recipe createPreprocessingRecipe() {
30+
return new ClassRenameRecipe();
31+
}
32+
33+
/**
34+
* Creates the main recipe that should be tested.
35+
* Subclasses must implement this method to provide their specific recipe.
36+
*
37+
* @return the main recipe to test
38+
*/
39+
protected abstract Recipe getRecipe();
40+
41+
/**
42+
* Tests a recipe with the given recipe path and test case name.
43+
* Expects input and output files to follow the naming convention:
44+
* - Input: {recipePath}/{testCaseName}/Input{testCaseName}.java
45+
* - Output: {recipePath}/{testCaseName}/Output{testCaseName}.java
46+
* The method automatically applies preprocessing to normalize class names
47+
* before running the main recipe.
48+
*
49+
* @param recipePath the recipe-specific path.
50+
* @param testCaseName the name of the test case (should match directory and file names)
51+
* @throws IOException if files cannot be read
52+
*/
53+
protected void testRecipe(String recipePath, String testCaseName) throws IOException {
54+
final String testCaseDir = testCaseName.toLowerCase();
55+
final String inputFileName = "Input" + testCaseName + ".java";
56+
final String outputFileName = "Output" + testCaseName + ".java";
57+
58+
final String beforeCode = Files.readString(Paths.get(BASE_TEST_RESOURCES_PATH
59+
+ recipePath + "/" + testCaseDir + "/" + inputFileName));
60+
61+
final String afterCode = Files.readString(Paths.get(BASE_TEST_RESOURCES_PATH
62+
+ recipePath + "/" + testCaseDir + "/" + outputFileName));
63+
64+
final Recipe preprocessing = createPreprocessingRecipe();
65+
final Recipe mainRecipe = getRecipe();
66+
67+
assertDoesNotThrow(() -> {
68+
rewriteRun(
69+
spec -> spec.recipes(preprocessing, mainRecipe),
70+
java(beforeCode, afterCode)
71+
);
72+
});
73+
}
74+
}
Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,29 @@
11
package org.checkstyle.autofix.recipe;
22

3-
import static org.junit.jupiter.api.Assertions.assertTrue;
4-
import static org.openrewrite.java.Assertions.java;
3+
import java.io.IOException;
54

65
import org.junit.jupiter.api.Test;
7-
import org.openrewrite.test.RecipeSpec;
8-
import org.openrewrite.test.RewriteTest;
6+
import org.openrewrite.Recipe;
97

10-
public class UpperEllRecipeTest implements RewriteTest {
8+
public class UpperEllRecipeTest extends AbstractRecipeTest {
119

1210
@Override
13-
public void defaults(RecipeSpec spec) {
14-
spec.recipe(new UpperEllRecipe());
11+
protected Recipe getRecipe() {
12+
return new UpperEllRecipe();
1513
}
1614

1715
@Test
18-
void fixesLowercase() {
19-
rewriteRun(
16+
void hexOctalLiteralTest() throws IOException {
17+
testRecipe("upperell", "HexOctalLiteral");
18+
}
2019

21-
java(
22-
"class Test {\n"
23-
+ " int value1 = 123l;\n"
24-
+ " long value2 = 0x123l;\n"
25-
+ " long value3 = 0123l;\n"
26-
+ " long value4 = 0b101l;\n"
27-
+ " String value5 = null;\n"
28-
+ "}\n",
29-
"class Test {\n"
30-
+ " int value1 = 123L;\n"
31-
+ " long value2 = 0x123L;\n"
32-
+ " long value3 = 0123L;\n"
33-
+ " long value4 = 0b101L;\n"
34-
+ " String value5 = null;\n"
35-
+ "}\n"
36-
)
37-
);
38-
assertTrue(true, "Test completed successfully");
20+
@Test
21+
void complexLongLiterals() throws IOException {
22+
testRecipe("upperell", "ComplexLongLiterals");
23+
}
24+
25+
@Test
26+
void stringAndCommentTest() throws IOException {
27+
testRecipe("upperell", "StringAndComments");
3928
}
4029
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.checkstyle.autofix.recipe.upperell.complexlongliterals;
2+
3+
public class InputComplexLongLiterals {
4+
private long withUnderscores = 1_000_000l;
5+
private long multipleUnderscores = 1_234_567_890l;
6+
7+
private long maxLong = 9223372036854775807l;
8+
private long minLong = -9223372036854775808l;
9+
10+
private Long nullLong = null;
11+
private Long simpleLong = 1234l;
12+
private Long negativeLong = -5678l;
13+
private Long underscoreLong = 1_000_000l;
14+
Long maxLongObject = 9223372036854775807l;
15+
Long minLongObject = -9223372036854775808l;
16+
17+
public long calculate(long input1, long input2) {
18+
return input1 + input2 + 1000l;
19+
}
20+
21+
public void lambdaUsage() {
22+
java.util.function.LongSupplier supplier = () -> 42l;
23+
java.util.Arrays.asList(1l, 2l, 3l).forEach(System.out::println);
24+
}
25+
26+
public java.util.List<Long> getNumbers() {
27+
return java.util.Arrays.asList(100l, 200l, 300l);
28+
}
29+
30+
public void longObjectOperations() {
31+
Long a = null;
32+
Long b = 1234l;
33+
Long c = Long.valueOf(5678l);
34+
Long d = new Long(9999l);
35+
36+
Long conditional = (a != null) ? a : 0l;
37+
long primitive = b != null ? b : 0l;
38+
Long boxed = primitive + 1000l;
39+
}
40+
41+
public Long methodReturningLong(Long param) {
42+
if (param == null) {
43+
return 12345l;
44+
}
45+
return param + 6789l;
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.checkstyle.autofix.recipe.upperell.complexlongliterals;
2+
3+
public class OutputComplexLongLiterals {
4+
private long withUnderscores = 1_000_000L;
5+
private long multipleUnderscores = 1_234_567_890L;
6+
7+
private long maxLong = 9223372036854775807L;
8+
private long minLong = -9223372036854775808L;
9+
10+
private Long nullLong = null;
11+
private Long simpleLong = 1234L;
12+
private Long negativeLong = -5678L;
13+
private Long underscoreLong = 1_000_000L;
14+
Long maxLongObject = 9223372036854775807L;
15+
Long minLongObject = -9223372036854775808L;
16+
17+
public long calculate(long input1, long input2) {
18+
return input1 + input2 + 1000L;
19+
}
20+
21+
public void lambdaUsage() {
22+
java.util.function.LongSupplier supplier = () -> 42L;
23+
java.util.Arrays.asList(1L, 2L, 3L).forEach(System.out::println);
24+
}
25+
26+
public java.util.List<Long> getNumbers() {
27+
return java.util.Arrays.asList(100L, 200L, 300L);
28+
}
29+
30+
public void longObjectOperations() {
31+
Long a = null;
32+
Long b = 1234L;
33+
Long c = Long.valueOf(5678L);
34+
Long d = new Long(9999L);
35+
36+
Long conditional = (a != null) ? a : 0L;
37+
long primitive = b != null ? b : 0L;
38+
Long boxed = primitive + 1000L;
39+
}
40+
41+
public Long methodReturningLong(Long param) {
42+
if (param == null) {
43+
return 12345L;
44+
}
45+
return param + 6789L;
46+
}
47+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.checkstyle.autofix.recipe.upperell.hexoctalliteral;
2+
3+
public class InputHexOctalLiteral {
4+
private long hexLower = 0x1ABCl;
5+
private long hexUpper = 0X2DEFl;
6+
private long octal = 0777l;
7+
private long binary = 0b1010l;
8+
private long decimal = 12345l;
9+
10+
public void calculateValues() {
11+
long hexResult = 0xDEADBEEFl;
12+
long octalResult = 01234l;
13+
long binaryResult = 0b11110000l;
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.checkstyle.autofix.recipe.upperell.hexoctalliteral;
2+
3+
public class OutputHexOctalLiteral {
4+
private long hexLower = 0x1ABCL;
5+
private long hexUpper = 0X2DEFL;
6+
private long octal = 0777L;
7+
private long binary = 0b1010L;
8+
private long decimal = 12345L;
9+
10+
public void calculateValues() {
11+
long hexResult = 0xDEADBEEFL;
12+
long octalResult = 01234L;
13+
long binaryResult = 0b11110000L;
14+
}
15+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.checkstyle.autofix.recipe.upperell.stringandcomments;
2+
3+
public class InputStringAndComments {
4+
/**
5+
* This comment mentions 123l but should not change
6+
*/
7+
private String message = "The value 456l should not change in strings";
8+
private String code = "long value = 789l;"; // This 789l in string should not change
9+
10+
// Only this actual long literal should change
11+
private long actualLong = 999l;
12+
13+
/*
14+
* Multi-line comment with 111l should not change
15+
*/
16+
public void method() {
17+
// Single line comment with 222l should not change
18+
long value = 333l; // This should change
19+
}
20+
}

0 commit comments

Comments
 (0)