XOrShiftPRNG implements PseudoRandom { public long nextLong() { this.seed ^= this.seed >> 12; this.seed ^= this.seed << 25; this.seed ^= this.seed >> 27; return this.seed * 2685821657736338717L; } XOrShiftPRNG(final long seed); long nextLong(); @Override long nextLong(long startInclusive,
      long endInclusive); @Override long getInitialSeed();  }
@Test public void xOrShiftPrngGeneratesOnlyLongPossibleWhenIntervalIsZeroWide() { generatesExactly(testee, prng -> prng.nextLong(0L, 0L), 0L); }
@Test public void xOrShiftPrngGeneratesExtremeLongs() { generatesExactly(testee, prng -> prng.nextLong(Long.MIN_VALUE, Long.MIN_VALUE + 3), Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, Long.MIN_VALUE + 3); }
@Test public void shouldGenerateUpToLongMax() { XOrShiftPRNG testee = new XOrShiftPRNG(0); long actual = testee.nextLong(Long.MAX_VALUE, Long.MAX_VALUE); assertThat(actual).isEqualTo(Long.MAX_VALUE); }
@Test public void shouldGenerateFromLowerLimit() { XOrShiftPRNG testee = new XOrShiftPRNG(0); Set<Long> generated = new HashSet<>(); for (int i = 0; i != 10; i++) { generated.add(testee.nextLong(Long.MIN_VALUE, Long.MIN_VALUE + 1)); } assertThat(generated).contains(Long.MIN_VALUE); assertThat(generated).contains(Long.MIN_VALUE + 1); }
@Test public void shouldGenerateAcrossFullRange() { generatesAtLeastXUniqueValues(testee, prng -> prng.nextLong(Long.MIN_VALUE, Long.MAX_VALUE), 1000); }
@Test public void shouldGenerateAcrossReducedMaxRange() { generatesAtLeastXUniqueValues(testee, prng -> prng.nextLong(Long.MIN_VALUE, Long.MAX_VALUE -2 ), 1000); }
@Test public void shouldGenerateAcrossReducedMinRange() { generatesAtLeastXUniqueValues(testee, prng -> prng.nextLong(Long.MIN_VALUE + 2, Long.MAX_VALUE), 1000); }
@Test public void shouldGenerateAcrossHalfDomain() { generatesAtLeastXUniqueValues(testee, prng -> prng.nextLong(Long.MIN_VALUE, Long.MAX_VALUE / 2), 1000); }
@Test public void shouldGenerateAcrossSmallDomain() { generatesAtLeastXUniqueValues(testee, prng -> prng.nextLong(-1000, 1000), 500); }
@Test public void valuesObeyConstraintsInLargeRange() { long min = Long.MIN_VALUE + 1000; long max = Long.MAX_VALUE - 1000; allValuesMatch(testee, prng -> prng.nextLong(min,max), l -> l >= min && l <= max ); }
@Test public void errorsNicelyWhenNonSensicalRangeRequested() { try { testee.nextLong(1, 0); fail(); } catch(IllegalArgumentException ex) { assertThat(ex).hasMessageContaining("Invalid range 1 to 0"); } }