Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.jetbrains.annotations.Nullable;

import java.time.Duration;
import java.util.Objects;
import java.util.Optional;

/**
Expand Down Expand Up @@ -120,8 +121,8 @@
* shared between threads without synchronization.</p>
*
* <h2>Equality and Hashing</h2>
* <p>This class does not override {@code equals()} and {@code hashCode()}.
* Each instance is unique and identity-based comparison is used.</p>
* <p>Two {@code MigrationResult} instances are considered equal if they have the same
* success status, source and target versions, domain, and duration.</p>
*
* @author Erik Pförtner
* @see MigrationService
Expand Down Expand Up @@ -429,6 +430,46 @@ public int getVersionSpan() {
return Math.abs(this.toVersion.getVersion() - this.fromVersion.getVersion());
}

/**
* Indicates whether some other object is "equal to" this migration result.
*
* <p>Two {@code MigrationResult} instances are considered equal if and only if they
* have the same success status, source version, target version, domain, and duration.</p>
*
* @param obj the reference object with which to compare; may be {@code null}
* @return {@code true} if this result is equal to the specified object; {@code false} otherwise
* @see #hashCode()
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof MigrationResult other)) {
return false;
}
return this.success == other.success
&& Objects.equals(this.fromVersion, other.fromVersion)
&& Objects.equals(this.toVersion, other.toVersion)
&& Objects.equals(this.domain, other.domain)
&& Objects.equals(this.duration, other.duration);
}

/**
* Returns a hash code value for this migration result.
*
* <p>The hash code is computed based on the success status, source version, target version,
* domain, and duration. This implementation satisfies the general contract of
* {@link Object#hashCode()}.</p>
*
* @return a hash code value for this migration result
* @see #equals(Object)
*/
@Override
public int hashCode() {
return Objects.hash(this.success, this.fromVersion, this.toVersion, this.domain, this.duration);
}

/**
* Returns a human-readable string representation of this result.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,83 @@ void getDurationReturnsMigrationDuration() {
}
}

@Nested
@DisplayName("equals and hashCode")
class EqualsAndHashCode {

@Test
@DisplayName("equals() returns true for same values")
void equalsReturnsTrueForSameValues() {
TaggedDynamic data = mock(TaggedDynamic.class);

MigrationResult a = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);
MigrationResult b = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);

assertThat(a).isEqualTo(b);
}

@Test
@DisplayName("equals() returns false for different success status")
void equalsReturnsFalseForDifferentSuccess() {
TaggedDynamic data = mock(TaggedDynamic.class);

MigrationResult success = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);
MigrationResult failure = MigrationResult.failure(
FROM_VERSION, TO_VERSION, DOMAIN, DURATION, new RuntimeException("error")
);

assertThat(success).isNotEqualTo(failure);
}

@Test
@DisplayName("equals() returns false for different versions")
void equalsReturnsFalseForDifferentVersions() {
TaggedDynamic data = mock(TaggedDynamic.class);

MigrationResult a = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);
MigrationResult b = MigrationResult.success(
data, FROM_VERSION, new DataVersion(300), DOMAIN, DURATION
);

assertThat(a).isNotEqualTo(b);
}

@Test
@DisplayName("hashCode() is consistent for equal objects")
void hashCodeConsistentForEqualObjects() {
TaggedDynamic data = mock(TaggedDynamic.class);

MigrationResult a = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);
MigrationResult b = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);

assertThat(a.hashCode()).isEqualTo(b.hashCode());
}

@Test
@DisplayName("equals() returns false for null")
void equalsReturnsFalseForNull() {
TaggedDynamic data = mock(TaggedDynamic.class);

MigrationResult result = MigrationResult.success(
data, FROM_VERSION, TO_VERSION, DOMAIN, DURATION
);

assertThat(result).isNotEqualTo(null);
}
}

@Nested
@DisplayName("toString")
class ToStringMethod {
Expand Down
Loading