Skip to content

Commit 05abea5

Browse files
authored
refactor(test-support): rename to AuditFinalStateSequence (#772)
1 parent f1f25b9 commit 05abea5

File tree

14 files changed

+114
-85
lines changed

14 files changed

+114
-85
lines changed

core/flamingock-test-support/src/main/java/io/flamingock/support/FlamingockTestSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* FAILED(FailedMigrationChange.class)
4343
* )
4444
* .whenRun()
45-
* .thenExpectAuditSequenceStrict(
45+
* .thenExpectAuditFinalStateSequence(
4646
* APPLIED(SchemaV2Change.class)
4747
* .withAuthor("dev-team"),
4848
* APPLIED(DataMigrationChange.class)

core/flamingock-test-support/src/main/java/io/flamingock/support/domain/AuditEntryDefinition.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
* APPLIED(MigrationV1.class)
8282
* )
8383
* .whenRun()
84-
* .thenExpectAuditSequenceStrict(
84+
* .thenExpectAuditFinalStateSequence(
8585
* APPLIED(NewChange.class)
8686
* )
8787
* .verify();

core/flamingock-test-support/src/main/java/io/flamingock/support/stages/ThenStage.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
* <h2>Example with Multiple Assertions</h2>
3838
* <pre>{@code
3939
* .whenRun()
40-
* .thenExpectAuditSequenceStrict(
40+
* .thenExpectAuditFinalStateSequence(
4141
* AuditEntryDefinition.APPLIED("change-1")
4242
* )
43-
* .andExpectAuditSequenceStrict(
43+
* .andExpectAuditFinalStateSequence(
4444
* AuditEntryDefinition.APPLIED("change-2")
4545
* )
4646
* .verify(); // Execution and verification happen here
@@ -52,24 +52,23 @@
5252
public interface ThenStage {
5353

5454
/**
55-
* Adds an additional strict expectation for the audit entry sequence.
55+
* Adds an additional expectation that the final state sequence of audit entries matches
56+
* the given definitions exactly.
5657
*
57-
* <p>This method has the same semantics as
58-
* {@link WhenStage#thenExpectAuditSequenceStrict(AuditEntryDefinition...)}
59-
* but allows chaining multiple sequence expectations.</p>
58+
* <p>This validates only <strong>final states</strong> (APPLIED, FAILED, ROLLED_BACK, ROLLBACK_FAILED),
59+
* filtering out intermediate states like STARTED.</p>
60+
*
61+
* <p><strong>Exact matching:</strong> The number of definitions must match the number of
62+
* final-state entries in the audit log. This is not a subset check.</p>
6063
*
61-
* <p><b>Strict validation</b> means:</p>
62-
* <ul>
63-
* <li>The number of actual audit entries must exactly match the number of definitions</li>
64-
* <li>The order of audit entries must exactly match the order of definitions</li>
65-
* <li>Each audit entry is validated against its corresponding definition</li>
66-
* </ul>
64+
* <p><strong>Field validation:</strong> Only fields set in each definition are validated.
65+
* See {@link AuditEntryDefinition} for details on class-based vs string-based factories.</p>
6766
*
68-
* @param definitions the expected audit entries in exact order
67+
* @param definitions the expected audit entry definitions, in exact order
6968
* @return this stage for method chaining
7069
* @see AuditEntryDefinition
7170
*/
72-
ThenStage andExpectAuditSequenceStrict(AuditEntryDefinition... definitions);
71+
ThenStage andExpectAuditFinalStateSequence(AuditEntryDefinition... definitions);
7372

7473
/**
7574
* Adds an expectation that the execution should throw a specific exception.

core/flamingock-test-support/src/main/java/io/flamingock/support/stages/ThenStageImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import io.flamingock.support.precondition.PreconditionInserter;
2121
import io.flamingock.support.validation.ValidationHandler;
2222
import io.flamingock.support.validation.ValidatorArgs;
23-
import io.flamingock.support.validation.impl.AuditSequenceStrictValidator;
23+
import io.flamingock.support.validation.impl.AuditFinalStateSequenceValidator;
2424
import io.flamingock.support.validation.impl.DefaultExceptionValidator;
2525

2626
import java.util.ArrayList;
@@ -39,9 +39,9 @@ final class ThenStageImpl implements ThenStage {
3939
}
4040

4141
@Override
42-
public ThenStage andExpectAuditSequenceStrict(AuditEntryDefinition... definitions) {
42+
public ThenStage andExpectAuditFinalStateSequence(AuditEntryDefinition... definitions) {
4343
List<AuditEntryDefinition> definitionsList = definitions != null ? Arrays.asList(definitions) : Collections.<AuditEntryDefinition>emptyList();
44-
validators.add(new AuditSequenceStrictValidator.Args(definitionsList));
44+
validators.add(new AuditFinalStateSequenceValidator.Args(definitionsList));
4545
return this;
4646
}
4747

core/flamingock-test-support/src/main/java/io/flamingock/support/stages/WhenStage.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
* <h2>Example</h2>
3939
* <pre>{@code
4040
* .whenRun()
41-
* .thenExpectAuditSequenceStrict(
41+
* .thenExpectAuditFinalStateSequence(
4242
* AuditEntryDefinition.APPLIED("change-1"),
4343
* AuditEntryDefinition.APPLIED("change-2")
4444
* )
@@ -52,23 +52,24 @@
5252
public interface WhenStage {
5353

5454
/**
55-
* Defines a strict expectation for the audit entry sequence.
55+
* Asserts that the final state sequence of audit entries matches the given definitions exactly.
5656
*
57-
* <p><b>Strict validation</b> means:</p>
58-
* <ul>
59-
* <li>The number of actual audit entries must exactly match the number of definitions</li>
60-
* <li>The order of audit entries must exactly match the order of definitions</li>
61-
* <li>Each audit entry is validated against its corresponding definition</li>
62-
* </ul>
57+
* <p>This validates only <strong>final states</strong> (APPLIED, FAILED, ROLLED_BACK, ROLLBACK_FAILED),
58+
* filtering out intermediate states like STARTED. The actual audit log may contain multiple entries
59+
* per change (e.g., STARTED then APPLIED), but only the final outcome is validated.</p>
6360
*
64-
* <p>For each {@link AuditEntryDefinition}, only the fields explicitly set via
65-
* {@code withXxx()} methods are verified. The change ID and status are always verified.</p>
61+
* <p><strong>Exact matching:</strong> The number of definitions must match the number of
62+
* final-state entries in the audit log. This is not a subset check.</p>
6663
*
67-
* @param definitions the expected audit entries in exact order
68-
* @return the {@link ThenStage} for chaining additional assertions or calling {@code verify()}
64+
* <p><strong>Field validation:</strong> Only fields set in each definition are validated.
65+
* Use class-based factories (e.g., {@code APPLIED(MyChange.class)}) to auto-extract fields
66+
* from annotations, or string-based factories with {@code withXxx()} methods for fine-grained control.</p>
67+
*
68+
* @param definitions the expected audit entry definitions, in exact order
69+
* @return a ThenStage for adding additional expectations or calling verify()
6970
* @see AuditEntryDefinition
7071
*/
71-
ThenStage thenExpectAuditSequenceStrict(AuditEntryDefinition... definitions);
72+
ThenStage thenExpectAuditFinalStateSequence(AuditEntryDefinition... definitions);
7273

7374
/**
7475
* Defines an expectation that the execution should throw a specific exception.

core/flamingock-test-support/src/main/java/io/flamingock/support/stages/WhenStageImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ public class WhenStageImpl implements WhenStage {
2929
}
3030

3131
@Override
32-
public ThenStage thenExpectAuditSequenceStrict(AuditEntryDefinition... definitions) {
33-
return new ThenStageImpl(testContext).andExpectAuditSequenceStrict(definitions);
32+
public ThenStage thenExpectAuditFinalStateSequence(AuditEntryDefinition... definitions) {
33+
return new ThenStageImpl(testContext).andExpectAuditFinalStateSequence(definitions);
3434
}
3535

3636
@Override

core/flamingock-test-support/src/main/java/io/flamingock/support/validation/ValidatorArgs.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* <h2>Implementation</h2>
3636
* <p>Implementations are typically static inner classes within their corresponding validators:</p>
3737
* <pre>{@code
38-
* public class AuditSequenceStrictValidator implements SimpleValidator {
38+
* public class AuditFinalStateSequenceValidator implements SimpleValidator {
3939
* // ... validator implementation
4040
*
4141
* public static class Args implements ValidatorArgs {
@@ -55,7 +55,7 @@
5555
* <h2>Usage in Framework</h2>
5656
* <p>The framework uses these argument carriers as follows:</p>
5757
* <ol>
58-
* <li>User calls expectation method (e.g., {@code thenExpectAuditSequenceStrict(...)})</li>
58+
* <li>User calls expectation method (e.g., {@code thenExpectAuditFinalStateSequence(...)})</li>
5959
* <li>Stage creates an {@code Args} instance and stores it in the validators list</li>
6060
* <li>When {@code verify()} is called, the {@link ValidationHandler} constructs actual
6161
* validators using {@link ValidatorFactory#getValidator(ValidatorArgs)}</li>

core/flamingock-test-support/src/main/java/io/flamingock/support/validation/ValidatorFactory.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import io.flamingock.internal.common.core.audit.AuditReader;
1919
import io.flamingock.support.domain.AuditEntryDefinition;
20-
import io.flamingock.support.validation.impl.AuditSequenceStrictValidator;
20+
import io.flamingock.support.validation.impl.AuditFinalStateSequenceValidator;
2121
import io.flamingock.support.validation.impl.DefaultExceptionValidator;
2222

2323
import java.util.List;
@@ -31,18 +31,18 @@ public ValidatorFactory(AuditReader auditReader) {
3131
this.auditReader = auditReader;
3232
}
3333

34-
public Validator getAuditSeqStrictValidator(List<AuditEntryDefinition> definitions) {
35-
return new AuditSequenceStrictValidator(auditReader, definitions);
34+
public Validator getAuditFinalStateSequenceValidator(List<AuditEntryDefinition> definitions) {
35+
return new AuditFinalStateSequenceValidator(auditReader, definitions);
3636
}
3737

3838
public Validator getExceptionValidator(Class<? extends Throwable> exceptionClass, Consumer<Throwable> exceptionConsumer) {
3939
return new DefaultExceptionValidator(exceptionClass, exceptionConsumer);
4040
}
4141

4242
public Validator getValidator(ValidatorArgs args) {
43-
if (args instanceof AuditSequenceStrictValidator.Args) {
44-
AuditSequenceStrictValidator.Args a = (AuditSequenceStrictValidator.Args) args;
45-
return new AuditSequenceStrictValidator(auditReader, a.getExpectations());
43+
if (args instanceof AuditFinalStateSequenceValidator.Args) {
44+
AuditFinalStateSequenceValidator.Args a = (AuditFinalStateSequenceValidator.Args) args;
45+
return new AuditFinalStateSequenceValidator(auditReader, a.getExpectations());
4646
}
4747

4848
if (args instanceof DefaultExceptionValidator.Args) {

core/flamingock-test-support/src/main/java/io/flamingock/support/validation/impl/AuditEntryExpectation.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* against expected definitions. Users should not interact with this class directly;
3131
* they should use {@link AuditEntryDefinition} instead.</p>
3232
*/
33+
3334
public class AuditEntryExpectation {
3435

3536
private final AuditEntryDefinition definition;

core/flamingock-test-support/src/main/java/io/flamingock/support/validation/impl/AuditSequenceStrictValidator.java renamed to core/flamingock-test-support/src/main/java/io/flamingock/support/validation/impl/AuditFinalStateSequenceValidator.java

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.flamingock.internal.common.core.audit.AuditEntry;
1919
import io.flamingock.internal.common.core.audit.AuditReader;
2020
import io.flamingock.support.domain.AuditEntryDefinition;
21+
import io.flamingock.support.stages.ThenStage;
2122
import io.flamingock.support.validation.SimpleValidator;
2223
import io.flamingock.support.validation.ValidatorArgs;
2324
import io.flamingock.support.validation.error.*;
@@ -28,36 +29,66 @@
2829
import java.util.stream.Collectors;
2930

3031
/**
31-
* Validator that performs strict sequence validation of audit entries.
32+
* Validates that the final state sequence of audit entries matches the expected definitions exactly.
3233
*
33-
* <p>This validator verifies that the actual audit entries match the expected
34-
* sequence exactly, both in count and in field values. Checking:</p>
34+
* <p>This validator focuses on the <strong>final state</strong> of each change, filtering out
35+
* intermediate states like {@code STARTED}. It validates only the states that represent
36+
* actual outcomes: {@code APPLIED}, {@code FAILED}, {@code ROLLED_BACK}, {@code ROLLBACK_FAILED}.</p>
37+
*
38+
* <p><strong>Exact sequence validation:</strong></p>
3539
* <ul>
36-
* <li>Exact count match between expected and actual entries</li>
37-
* <li>Strict field-by-field validation for each entry at each index</li>
38-
* <li>Order preservation (expected[0] must match actual[0], etc.)</li>
40+
* <li>The number of actual entries must exactly match the number of expected definitions</li>
41+
* <li>Order is preserved: expected[0] must match actual[0], expected[1] must match actual[1], etc.</li>
3942
* </ul>
43+
*
44+
* <p>This is not a "contains" validator - if the audit log has 3 changes, you must
45+
* provide exactly 3 expected definitions.</p>
46+
*
47+
* <p><strong>Field validation:</strong></p>
48+
* <p>Only fields that are set in the {@link AuditEntryDefinition} are validated. The {@code changeId}
49+
* and {@code state} are always compared (they are required). Additional fields depend on how the
50+
* definition is constructed:</p>
51+
* <ul>
52+
* <li>Class-based factory methods (e.g., {@code APPLIED(MyChange.class)}) auto-extract fields
53+
* from annotations: author, className, methodName, targetSystemId, recoveryStrategy, order, transactional</li>
54+
* <li>String-based factory methods (e.g., {@code APPLIED("change-id")}) only set changeId and state</li>
55+
* <li>Use {@code withXxx()} methods to add or override specific fields to validate</li>
56+
* <li>Fields that are null in the definition are not compared</li>
57+
* </ul>
58+
*
59+
* <p><strong>Example:</strong></p>
60+
* <pre>{@code
61+
* testSupport.givenBuilderFromContext()
62+
* .whenRun()
63+
* .thenExpectAuditFinalStateSequence(
64+
* APPLIED(CreateUsersChange.class), // validates fields from annotations
65+
* APPLIED("template-change-id"), // validates only changeId and state
66+
* FAILED(BrokenChange.class).withErrorTrace("Expected error") // adds error trace validation
67+
* )
68+
* .verify();
69+
* }</pre>
70+
*
71+
* @see AuditEntryDefinition
72+
* @see ThenStage#andExpectAuditFinalStateSequence(AuditEntryDefinition...)
4073
*/
41-
public class AuditSequenceStrictValidator implements SimpleValidator {
74+
public class AuditFinalStateSequenceValidator implements SimpleValidator {
4275

43-
private static final String VALIDATOR_NAME = "Audit Sequence (Strict)";
76+
private static final String VALIDATOR_NAME = "Audit Final State Sequence";
4477

45-
private final AuditReader auditReader;
4678
private final List<AuditEntryExpectation> expectations;
4779
private final List<AuditEntry> actualEntries;
4880
private static final List<AuditEntry.Status> EXCLUDED_STATES = Collections.singletonList(
4981
AuditEntry.Status.STARTED
5082
);
5183

52-
public AuditSequenceStrictValidator(AuditReader auditReader, List<AuditEntryDefinition> definitions) {
53-
this.auditReader = auditReader;
84+
public AuditFinalStateSequenceValidator(AuditReader auditReader, List<AuditEntryDefinition> definitions) {
5485
this.expectations = definitions != null
5586
? definitions.stream()
5687
.map(AuditEntryExpectation::new)
5788
.collect(Collectors.toList())
5889
: new ArrayList<>();
5990

60-
this.actualEntries = auditReader.getAuditHistory().stream()
91+
this.actualEntries = auditReader.getAuditHistory().stream()
6192
.filter(entry -> !EXCLUDED_STATES.contains(entry.getState()))
6293
.sorted()
6394
.collect(Collectors.toList());
@@ -66,13 +97,12 @@ public AuditSequenceStrictValidator(AuditReader auditReader, List<AuditEntryDefi
6697
/**
6798
* Internal constructor for direct list initialization (used by tests).
6899
*/
69-
AuditSequenceStrictValidator(List<AuditEntryDefinition> expectedDefinitions, List<AuditEntry> actualEntries, AuditReader auditReader) {
100+
AuditFinalStateSequenceValidator(List<AuditEntryDefinition> expectedDefinitions, List<AuditEntry> actualEntries) {
70101
this.expectations = expectedDefinitions != null
71102
? expectedDefinitions.stream()
72103
.map(AuditEntryExpectation::new)
73104
.collect(Collectors.toList())
74105
: new ArrayList<>();
75-
this.auditReader = auditReader;
76106
this.actualEntries = actualEntries != null ? actualEntries : new ArrayList<>();
77107
}
78108

0 commit comments

Comments
 (0)