Skip to content

Commit 0545df3

Browse files
committed
test: downgrade test suite syntax for Java 8 CI compatibility
- Replaced Java 10 'var' keyword with explicit type declarations. - Converted Java 15 Text Blocks (""") to standard string concatenation. - Replaced Java 16 'record' classes with traditional POJOs. - Swapped Java 9 'List.of()' with 'Arrays.asList()'. - Ensured all test sources compile and execute flawlessly on the JDK 8 runner of the new GitHub Actions build matrix.
1 parent 2411aaa commit 0545df3

File tree

10 files changed

+179
-103
lines changed

10 files changed

+179
-103
lines changed

sift-annotations/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ java {
1212
withSourcesJar()
1313
}
1414

15-
tasks.named('compileJava') {
15+
tasks.withType(JavaCompile).configureEach {
1616
options.release.set(8)
1717
}
1818

sift-annotations/src/test/java/com/mirkoddd/sift/annotations/SiftAnnotationTest.java

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,23 @@ public String getRegex() {
7575

7676
/**
7777
* A mock DTO simulating a real-world usage of the annotation.
78+
* Converted from Record to Java 8 Class.
7879
*/
79-
public record MockRegistrationDto(
80-
@SiftMatch(
81-
value = NumericOnlyRule.class,
82-
message = "The provided value must contain only numeric characters."
83-
)
84-
String pinCode
85-
) {}
80+
public static class MockRegistrationDto {
81+
@SiftMatch(
82+
value = NumericOnlyRule.class,
83+
message = "The provided value must contain only numeric characters."
84+
)
85+
private final String pinCode;
86+
87+
public MockRegistrationDto(String pinCode) {
88+
this.pinCode = pinCode;
89+
}
90+
91+
public String pinCode() {
92+
return pinCode;
93+
}
94+
}
8695

8796
// ===================================================================================
8897
// TEST CASES (Standard Validation)
@@ -146,15 +155,33 @@ public String getRegex() {
146155
}
147156
}
148157

149-
public record DtoWithoutFlags(
150-
@SiftMatch(value = StrictHelloRule.class)
151-
String greeting
152-
) {}
158+
// Converted from Record to Java 8 Class
159+
public static class DtoWithoutFlags {
160+
@SiftMatch(value = StrictHelloRule.class)
161+
private final String greeting;
162+
163+
public DtoWithoutFlags(String greeting) {
164+
this.greeting = greeting;
165+
}
166+
167+
public String greeting() {
168+
return greeting;
169+
}
170+
}
171+
172+
// Converted from Record to Java 8 Class
173+
public static class DtoWithInsensitiveFlag {
174+
@SiftMatch(value = StrictHelloRule.class, flags = {SiftMatchFlag.CASE_INSENSITIVE})
175+
private final String greeting;
176+
177+
public DtoWithInsensitiveFlag(String greeting) {
178+
this.greeting = greeting;
179+
}
153180

154-
public record DtoWithInsensitiveFlag(
155-
@SiftMatch(value = StrictHelloRule.class, flags = {SiftMatchFlag.CASE_INSENSITIVE})
156-
String greeting
157-
) {}
181+
public String greeting() {
182+
return greeting;
183+
}
184+
}
158185

159186
@Test
160187
@DisplayName("Should enforce case sensitivity when no flags are provided")
@@ -193,15 +220,24 @@ public interface CriticalError extends Payload {}
193220

194221
/**
195222
* A mock DTO testing Jakarta's advanced groups and payload features.
223+
* Converted from Record to Java 8 Class.
196224
*/
197-
public record AdvancedDto(
198-
@SiftMatch(
199-
value = NumericOnlyRule.class,
200-
groups = RegistrationPhase.class,
201-
payload = CriticalError.class
202-
)
203-
String value
204-
) {}
225+
public static class AdvancedDto {
226+
@SiftMatch(
227+
value = NumericOnlyRule.class,
228+
groups = RegistrationPhase.class,
229+
payload = CriticalError.class
230+
)
231+
private final String value;
232+
233+
public AdvancedDto(String value) {
234+
this.value = value;
235+
}
236+
237+
public String value() {
238+
return value;
239+
}
240+
}
205241

206242
@Test
207243
@DisplayName("Should correctly handle Jakarta Validation groups and payloads")
@@ -241,11 +277,20 @@ public String getRegex() {
241277

242278
/**
243279
* A mock DTO testing the error handling when a rule is invalid.
280+
* Converted from Record to Java 8 Class.
244281
*/
245-
public record BrokenDto(
246-
@SiftMatch(BrokenRule.class)
247-
String value
248-
) {}
282+
public static class BrokenDto {
283+
@SiftMatch(BrokenRule.class)
284+
private final String value;
285+
286+
public BrokenDto(String value) {
287+
this.value = value;
288+
}
289+
290+
public String value() {
291+
return value;
292+
}
293+
}
249294

250295
@Test
251296
@DisplayName("Should throw an exception when the Rule class cannot be instantiated")
@@ -262,5 +307,4 @@ void whenRuleIsInvalid_thenInitializationThrowsException() {
262307
assertTrue(exception.getCause().getMessage().contains("Failed to initialize SiftRegexProvider"),
263308
"The exception message should match the one thrown in the catch block");
264309
}
265-
266310
}

sift-core/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ java {
1212
withSourcesJar()
1313
}
1414

15-
tasks.named('compileJava') {
15+
tasks.withType(JavaCompile).configureEach {
1616
options.release.set(8)
1717
}
1818

sift-core/src/test/java/com/mirkoddd/sift/core/SiftCookbookTest.java

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@
2121
import org.junit.jupiter.api.DisplayName;
2222
import org.junit.jupiter.api.Test;
2323

24+
import java.util.Arrays;
2425
import java.util.List;
2526
import java.util.regex.Pattern;
2627

2728
import static org.junit.jupiter.api.Assertions.assertEquals;
2829
import static org.junit.jupiter.api.Assertions.assertFalse;
2930
import static org.junit.jupiter.api.Assertions.assertTrue;
3031

32+
import com.mirkoddd.sift.core.dsl.CharacterClassConnectorStep;
3133
import com.mirkoddd.sift.core.dsl.ConnectorStep;
3234
import com.mirkoddd.sift.core.dsl.SiftContext;
35+
import com.mirkoddd.sift.core.dsl.SiftPattern;
36+
import com.mirkoddd.sift.core.dsl.VariableCharacterClassConnectorStep;
37+
import com.mirkoddd.sift.core.dsl.VariableConnectorStep;
3338

3439
/**
3540
* Validates the real-world examples provided in the COOKBOOK.md file.
@@ -63,16 +68,16 @@ void testUuidValidatorRecipe() {
6368
// Define the basic building blocks using fromAnywhere() (in this case is the static Fragment shortcut exactly())
6469
// This ensures these blocks don't carry a '^' anchor, allowing them
6570
// to be safely placed in the middle or end of our final chain.
66-
var hex8 = exactly(8).hexDigits();
67-
var hex4 = exactly(4).hexDigits();
68-
var hex12 = exactly(12).hexDigits();
69-
var separator = exactly(1).character('-');
71+
CharacterClassConnectorStep<SiftContext.Fragment> hex8 = exactly(8).hexDigits();
72+
CharacterClassConnectorStep<SiftContext.Fragment> hex4 = exactly(4).hexDigits();
73+
CharacterClassConnectorStep<SiftContext.Fragment> hex12 = exactly(12).hexDigits();
74+
ConnectorStep<SiftContext.Fragment> separator = exactly(1).character('-');
7075

7176
// Compose reusable intermediate blocks
72-
var hex4andSeparator = hex4.followedBy(separator);
77+
ConnectorStep<SiftContext.Fragment> hex4andSeparator = hex4.followedBy(separator);
7378

7479
// define the list of steps to follow in the final pattern
75-
List<ConnectorStep<SiftContext.Fragment>> steps = List.of(
80+
List<ConnectorStep<SiftContext.Fragment>> steps = Arrays.asList(
7681
separator,
7782
hex4andSeparator,
7883
hex4andSeparator,
@@ -99,20 +104,20 @@ void testUuidValidatorRecipe() {
99104
@DisplayName("Recipe 2: Parsing Log Files (TSV Format with discrete semantic parts)")
100105
void testLogParserRecipe() {
101106
// Define discrete temporal components
102-
var year = Sift.fromAnywhere().exactly(4).digits();
103-
var month = Sift.fromAnywhere().exactly(2).digits();
104-
var day = Sift.fromAnywhere().exactly(2).digits(); // same as month, but more readable
105-
var dash = Sift.fromAnywhere().character('-'); // you could also use literal("-"), less verbose
107+
CharacterClassConnectorStep<SiftContext.Fragment> year = Sift.fromAnywhere().exactly(4).digits();
108+
CharacterClassConnectorStep<SiftContext.Fragment> month = Sift.fromAnywhere().exactly(2).digits();
109+
CharacterClassConnectorStep<SiftContext.Fragment> day = Sift.fromAnywhere().exactly(2).digits(); // same as month, but more readable
110+
ConnectorStep<SiftContext.Fragment> dash = Sift.fromAnywhere().character('-'); // you could also use literal("-"), less verbose
106111

107-
var dateBlock = year.followedBy(List.of(dash, month, dash, day));
112+
ConnectorStep<SiftContext.Fragment> dateBlock = year.followedBy(Arrays.asList(dash, month, dash, day));
108113

109114
// Define structural components
110-
var tab = Sift.fromAnywhere().tab();
111-
var newline = Sift.fromAnywhere().newline();
115+
ConnectorStep<SiftContext.Fragment> tab = Sift.fromAnywhere().tab();
116+
ConnectorStep<SiftContext.Fragment> newline = Sift.fromAnywhere().newline();
112117

113118
// Define payload components
114-
var logLevel = Sift.fromAnywhere().oneOrMore().upperCaseLetters();
115-
var message = Sift.fromAnywhere().oneOrMore().anyCharacter();
119+
ConnectorStep<SiftContext.Fragment> logLevel = Sift.fromAnywhere().oneOrMore().upperCaseLetters();
120+
ConnectorStep<SiftContext.Fragment> message = Sift.fromAnywhere().oneOrMore().anyCharacter();
116121

117122
// Assemble the final pattern like a natural language sentence
118123
String logParserRegex = dateBlock
@@ -125,7 +130,7 @@ void testLogParserRecipe() {
125130

126131
// you can also be more concise:
127132
String altLogParserRegex = dateBlock
128-
.followedBy(List.of(tab, logLevel, tab, message, newline))
133+
.followedBy(Arrays.asList(tab, logLevel, tab, message, newline))
129134
.shake();
130135

131136
// or be more verbose
@@ -156,17 +161,17 @@ void testStrictTokenValidatorRecipe() {
156161
// Notice the use of fromStart() here.
157162
// We enforce that the token MUST begin with this exact prefix,
158163
// anchoring the entire evaluation to the start of the string.
159-
var prefix = Sift.fromStart().exactly(2).upperCaseLetters();
164+
CharacterClassConnectorStep<SiftContext.Root> prefix = Sift.fromStart().exactly(2).upperCaseLetters();
160165

161166
// The rest of the blocks use fromAnywhere() for composition
162-
var body = Sift.fromAnywhere().between(4, 6).alphanumeric();
163-
var suffix = Sift.fromAnywhere().oneOrMore().punctuation();
167+
CharacterClassConnectorStep<SiftContext.Fragment> body = Sift.fromAnywhere().between(4, 6).alphanumeric();
168+
ConnectorStep<SiftContext.Fragment> suffix = Sift.fromAnywhere().oneOrMore().punctuation();
164169

165-
var underscore = Sift.fromAnywhere().character('_');
170+
ConnectorStep<SiftContext.Fragment> underscore = Sift.fromAnywhere().character('_');
166171

167172
// Create logical compound blocks
168-
var prefixWithUnderscore = prefix.followedBy(underscore);
169-
var bodyWithUnderscore = body.followedBy(underscore);
173+
ConnectorStep<SiftContext.Root> prefixWithUnderscore = prefix.followedBy(underscore);
174+
ConnectorStep<SiftContext.Fragment> bodyWithUnderscore = body.followedBy(underscore);
170175

171176
// Final assembly
172177
String securityTokenRegex = prefixWithUnderscore
@@ -191,7 +196,7 @@ void testStrictTokenValidatorRecipe() {
191196
@DisplayName("Recipe 4: IP Address Validation (Highly Reusable Blocks)")
192197
void testIpAddressValidatorRecipe() {
193198
// built-in pattern for IPv4
194-
var libIPv4 = SiftCatalog.ipv4();
199+
SiftPattern<SiftContext.Fragment> libIPv4 = SiftCatalog.ipv4();
195200

196201
// Building the IPv4 structure using the built-in pattern, enforcing anchor start and anchor end
197202
String ipv4Regex = Sift.fromStart()
@@ -224,27 +229,27 @@ void testAdvancedExtractionRecipe() {
224229
char closeBracket = '>';
225230
String closingTagPrefix = "</";
226231

227-
var tagName = Sift.fromAnywhere().oneOrMore().alphanumeric();
228-
var tagContent = Sift.fromAnywhere().oneOrMore().anyCharacter();
232+
VariableCharacterClassConnectorStep<SiftContext.Fragment> tagName = Sift.fromAnywhere().oneOrMore().alphanumeric();
233+
VariableConnectorStep<SiftContext.Fragment> tagContent = Sift.fromAnywhere().oneOrMore().anyCharacter();
229234

230235
// 1. Defining Named Captures to extract specific data blocks
231-
var groupTag = SiftPatterns.capture("tag", tagName);
232-
var groupContent = SiftPatterns.capture("content", tagContent);
236+
NamedCapture groupTag = SiftPatterns.capture("tag", tagName);
237+
NamedCapture groupContent = SiftPatterns.capture("content", tagContent);
233238

234-
var openTag = Sift.fromAnywhere()
239+
ConnectorStep<SiftContext.Fragment> openTag = Sift.fromAnywhere()
235240
.character(openBracket)
236241
.then().namedCapture(groupTag)
237242
.then().character(closeBracket);
238243

239-
var content = Sift.fromAnywhere().namedCapture(groupContent);
244+
ConnectorStep<SiftContext.Fragment> content = Sift.fromAnywhere().namedCapture(groupContent);
240245

241-
var closeTag = Sift.fromAnywhere()
246+
ConnectorStep<SiftContext.Fragment> closeTag = Sift.fromAnywhere()
242247
.pattern(literal(closingTagPrefix))
243248
.then().backreference(groupTag)
244249
.then().character(closeBracket);
245250

246251
// 2. Building the pattern. Notice how SiftGlobalFlag is elegantly applied at the root!
247-
var htmlTagPattern = Sift
252+
SiftPattern<SiftContext.Root> htmlTagPattern = Sift
248253
.filteringWith(SiftGlobalFlag.CASE_INSENSITIVE)
249254
.fromStart()
250255
.pattern(openTag)
@@ -277,17 +282,17 @@ void testLookaheadAndAnyOfRecipe() {
277282
// Goal 1: Validate a complex password using Lookaheads
278283
// Must contain at least one uppercase, one digit, and be at least 8 chars long.
279284

280-
var requiresUppercase = Sift.fromAnywhere()
285+
ConnectorStep<SiftContext.Fragment> requiresUppercase = Sift.fromAnywhere()
281286
.pattern(SiftPatterns.positiveLookahead(
282287
Sift.fromAnywhere().zeroOrMore().anyCharacter().then().exactly(1).upperCaseLetters()
283288
));
284289

285-
var requiresDigit = Sift.fromAnywhere()
290+
ConnectorStep<SiftContext.Fragment> requiresDigit = Sift.fromAnywhere()
286291
.pattern(SiftPatterns.positiveLookahead(
287292
Sift.fromAnywhere().zeroOrMore().anyCharacter().then().exactly(1).digits()
288293
));
289294

290-
var passwordPattern = Sift.fromStart()
295+
String passwordPattern = Sift.fromStart()
291296
.pattern(requiresUppercase)
292297
.then().pattern(requiresDigit)
293298
.then().between(8, 64).anyCharacter()
@@ -301,13 +306,13 @@ void testLookaheadAndAnyOfRecipe() {
301306

302307
// Goal 2: Match specific keywords using Alternation (anyOf)
303308
// Extracting valid HTTP methods
304-
var httpMethodPattern = Sift.fromStart()
309+
String httpMethodPattern = Sift.fromStart()
305310
.pattern(SiftPatterns.anyOf(
306-
SiftPatterns.literal("GET"),
307-
SiftPatterns.literal("POST"),
308-
SiftPatterns.literal("PUT"),
309-
SiftPatterns.literal("DELETE"),
310-
SiftPatterns.literal("PATCH")
311+
literal("GET"),
312+
literal("POST"),
313+
literal("PUT"),
314+
literal("DELETE"),
315+
literal("PATCH")
311316
))
312317
.andNothingElse()
313318
.shake();
@@ -323,7 +328,7 @@ void testReDoSMitigationRecipe() {
323328
// We use the possessive modifier (.withoutBacktracking()) to tell the engine to NEVER give back
324329
// matched characters. This prevents infinite loop evaluations.
325330

326-
var safePayloadExtractor = Sift.fromStart()
331+
String safePayloadExtractor = Sift.fromStart()
327332
.character('{')
328333
// We use wordCharacters() so it stops capturing BEFORE the '}'.
329334
// Using .withoutBacktracking() prevents the engine from trying alternative
@@ -342,7 +347,7 @@ void testReDoSMitigationRecipe() {
342347
assertDoesNotMatch(safePayloadExtractor, "{invalid payload}");
343348

344349
// Example of LAZY matching (finding the shortest path instead of greedy)
345-
var lazyTagExtractor = Sift.fromStart()
350+
String lazyTagExtractor = Sift.fromStart()
346351
.character('<')
347352
.then().oneOrMore().anyCharacter().asFewAsPossible() // Translates to "+?"
348353
.then().character('>')

sift-core/src/test/java/com/mirkoddd/sift/core/SiftLogMiningTest.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,16 @@ class SiftLogMiningTest {
4242
// 1. THE WALL OF TEXT
4343
// =================================================================================
4444
// Simulates a messy server log file with mixed formats and noise.
45-
// Using Text Blocks for readability.
46-
private final String SERVER_LOGS = """
47-
[INFO] [2026-02-18] System: Booting up services... OK.
48-
[INFO] [2026-02-18] User: 'Mirko' -> {Action: Login} - IP: 192.168.1.1
49-
[WARN] [2026-02-18] Disk: Usage at 85%.
50-
garbage_data_noise_#$@#$
51-
[ERR] [2026-02-18] User: 'HackBot' -> {Action: Inject} - BLOCKED
52-
[INFO] [2026-02-18] User: 'Alice' -> {Action: Upload} - File: data.csv
53-
[DEBUG] Connection established.
54-
[INFO] [2026-02-18] User: 'Bob' -> {Action: Logout}
55-
""";
45+
// Converted to Java 8 compliant string concatenation.
46+
private final String SERVER_LOGS =
47+
"[INFO] [2026-02-18] System: Booting up services... OK.\n" +
48+
"[INFO] [2026-02-18] User: 'Mirko' -> {Action: Login} - IP: 192.168.1.1\n" +
49+
"[WARN] [2026-02-18] Disk: Usage at 85%.\n" +
50+
"garbage_data_noise_#$@#$\n" +
51+
"[ERR] [2026-02-18] User: 'HackBot' -> {Action: Inject} - BLOCKED\n" +
52+
"[INFO] [2026-02-18] User: 'Alice' -> {Action: Upload} - File: data.csv\n" +
53+
"[DEBUG] Connection established.\n" +
54+
"[INFO] [2026-02-18] User: 'Bob' -> {Action: Logout}\n";
5655

5756
// =================================================================================
5857
// 2. THE GRAMMAR (The "Business Language")

0 commit comments

Comments
 (0)