Repository: pgjdbc/pgjdbc
Pull request #1494 (2019-06-03 14:29:48)

Make LogSequenceNumber implement Comparable<LogSequenceNumber>
Regarding #1493:

added a Java 6 - compatible `compareTo` implementation for `LogSequenceNumber`, so it implements `Comparable<LogSequenceNumber>`.

AppVeyorBot: :white_check_mark: [Build pgjdbc 1.0.275 completed](https://ci.appveyor.com/project/davecramer/pgjdbc/builds/25004898) (commit https://github.com/pgjdbc/pgjdbc/commit/8092a7200c by @maltalex)
codecov-io: # [Codecov](https://codecov.io/gh/pgjdbc/pgjdbc/pull/1494?src=pr&el=h1) Report
> Merging [#1494](https://codecov.io/gh/pgjdbc/pgjdbc/pull/1494?src=pr&el=desc) into [master](https://codecov.io/gh/pgjdbc/pgjdbc/commit/12ef697a3d34b616716ea9c2c8cb4c9447e2c4c3?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `100%`.



```diff
@@             Coverage Diff              @@
##             master    #1494      +/-   ##
============================================
+ Coverage      68.8%   68.81%   +0.01%     
- Complexity     3930     3932       +2     
============================================
  Files           179      179              
  Lines         16458    16461       +3     
  Branches       2672     2673       +1     
============================================
+ Hits          11324    11328       +4     
+ Misses         3889     3888       -1     
  Partials       1245     1245
```

AppVeyorBot: :white_check_mark: [Build pgjdbc 1.0.276 completed](https://ci.appveyor.com/project/davecramer/pgjdbc/builds/25007556) (commit https://github.com/pgjdbc/pgjdbc/commit/e7769e5e40 by @maltalex)
davecramer: @maltalex  I think it would be useful to attempt to prove that our unsigned comparison works. Not that I am doubting that it works, just that if the code is there we should test it.
maltalex: @davecramer Sure, I can add more tests. Do you have a specific test in mind? I feel like I covered basic comparisons as well as the edge cases like comparing a "positive" with a "negative", comparing two "negatives" etc.

Would you like to see something like a comparison of every pair of numbers from a pre-generated sorted list of numbers?
davecramer: @maltalex whoops sorry I missed the negative case when I first looked


Patch:
diff --git a/pgjdbc/src/main/java/org/postgresql/replication/LogSequenceNumber.java b/pgjdbc/src/main/java/org/postgresql/replication/LogSequenceNumber.java
index 422ddc55..1886a7da 100644
--- a/pgjdbc/src/main/java/org/postgresql/replication/LogSequenceNumber.java
+++ b/pgjdbc/src/main/java/org/postgresql/replication/LogSequenceNumber.java
@@ -10,7 +10,7 @@ import java.nio.ByteBuffer;
 /**
  * LSN (Log Sequence Number) data which is a pointer to a location in the XLOG.
  */
-public final class LogSequenceNumber {
+public final class LogSequenceNumber implements Comparable<LogSequenceNumber> {
   /**
    * Zero is used indicate an invalid pointer. Bootstrap skips the first possible WAL segment,
    * initializing the first WAL page at XLOG_SEG_SIZE, so no XLOG record can begin at zero.
@@ -105,4 +105,14 @@ public final class LogSequenceNumber {
   public String toString() {
     return "LSN{" + asString() + '}';
   }
+
+  @Override
+  public int compareTo(LogSequenceNumber o) {
+    if (value == o.value) {
+      return 0;
+    }
+    //Unsigned comparison
+    return value + Long.MIN_VALUE < o.value + Long.MIN_VALUE ? -1 : 1;
+  }
+
 }


Test patch:
diff --git a/pgjdbc/src/test/java/org/postgresql/replication/LogSequenceNumberTest.java b/pgjdbc/src/test/java/org/postgresql/replication/LogSequenceNumberTest.java
index 30cd7747..abec6eb4 100644
--- a/pgjdbc/src/test/java/org/postgresql/replication/LogSequenceNumberTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/replication/LogSequenceNumberTest.java
@@ -96,4 +96,49 @@ public class LogSequenceNumberTest {
 
     assertThat(first.hashCode(), equalTo(second.hashCode()));
   }
+
+  @Test
+  public void testCompareToSameValue() throws Exception {
+    LogSequenceNumber first = LogSequenceNumber.valueOf("0/15D690F8");
+    LogSequenceNumber second = LogSequenceNumber.valueOf("0/15D690F8");
+
+    assertThat(first.compareTo(second), equalTo(0));
+    assertThat(second.compareTo(first), equalTo(0));
+  }
+
+  @Test
+  public void testCompareToPositiveValues() throws Exception {
+    LogSequenceNumber first = LogSequenceNumber.valueOf(1234);
+    LogSequenceNumber second = LogSequenceNumber.valueOf(4321);
+
+    assertThat(first.compareTo(second), equalTo(-1));
+    assertThat(second.compareTo(first), equalTo(1));
+  }
+
+  @Test
+  public void testCompareToNegativeValues() throws Exception {
+    LogSequenceNumber first = LogSequenceNumber.valueOf(0x8000000000000000L);
+    LogSequenceNumber second = LogSequenceNumber.valueOf(0x8000000000000001L);
+
+    assertThat(first.compareTo(second), equalTo(-1));
+    assertThat(second.compareTo(first), equalTo(1));
+  }
+
+  @Test
+  public void testCompareToMixedSign() throws Exception {
+    LogSequenceNumber first = LogSequenceNumber.valueOf(1);
+    LogSequenceNumber second = LogSequenceNumber.valueOf(0x8000000000000001L);
+
+    assertThat(first.compareTo(second), equalTo(-1));
+    assertThat(second.compareTo(first), equalTo(1));
+  }
+
+  @Test
+  public void testCompareToWithInvalid() throws Exception {
+    LogSequenceNumber first = LogSequenceNumber.INVALID_LSN;
+    LogSequenceNumber second = LogSequenceNumber.valueOf(1);
+
+    assertThat(first.compareTo(second), equalTo(-1));
+    assertThat(second.compareTo(first), equalTo(1));
+  }
 }