protected IdGenerator instantiate( FileSystemAbstraction fs, File fileName, int grabSize, long maxValue, boolean aggressiveReuse, IdType idType, LongSupplier highId ) { return new IdGeneratorImpl( fs, fileName, grabSize, maxValue, aggressiveReuse, idType, highId ); }
@Override protected IdGenerator openIdGenerator( int grabSize ) { return new IdGeneratorImpl( fs, idGeneratorFile(), grabSize, 1000, false, IdType.NODE, () -> 0L ); }
@Test public void constructorShouldCallHighIdSupplierOnNonExistingIdFile() { // Given // An empty file (default, nothing to do) // and a mock supplier to test against LongSupplier highId = mock( LongSupplier.class ); when( highId.getAsLong() ).thenReturn( 0L ); // necessary, otherwise it runs into NPE in the constructor below // When // The id generator is started IdGeneratorImpl idGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, false, IdType.NODE, highId ); // Then // The highId supplier must have been called to get the high id verify( highId ).getAsLong(); idGenerator.close(); }
@Test public void shouldBeAbleToReadWrittenGenerator() { // Given IdGeneratorImpl.createGenerator( fsr.get(), file, 42, false ); IdGeneratorImpl idGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, false, IdType.NODE, () -> 42L ); idGenerator.close(); // When idGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, false, IdType.NODE, () -> 0L ); // Then assertThat( idGenerator.getHighId(), equalTo( 42L ) ); }
@Test public void constructorShouldNotCallHighIdSupplierOnCleanIdFile() { // Given // A non empty, clean id file IdContainer.createEmptyIdFile( fsr.get(), file, 42, true ); // and a mock supplier to test against LongSupplier highId = mock( LongSupplier.class ); // When // An IdGenerator is created over the previous properly closed file IdGenerator idGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, false, IdType.NODE, highId ); idGenerator.close(); // Then // The supplier must have remained untouched verifyZeroInteractions( highId ); } }
@Test( expected = IllegalArgumentException.class ) public void grabSizeCannotBeNegative() { IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); new IdGeneratorImpl( fs, idGeneratorFile(), -1, 100, false, IdType.NODE, () -> 0L ).close(); }
@Test public void testStickyGenerator() { try { IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); IdGenerator idGen = new IdGeneratorImpl( fs, idGeneratorFile(), 3, 1000, false, IdType.NODE, () -> 0L ); try { new IdGeneratorImpl( fs, idGeneratorFile(), 3, 1000, false, IdType.NODE, () -> 0L ); fail( "Opening sticky id generator should throw exception" ); } catch ( StoreFailureException e ) { // good } closeIdGenerator( idGen ); } finally { File file = idGeneratorFile(); if ( file.exists() ) { assertTrue( file.delete() ); } } }
@Test( expected = IllegalArgumentException.class ) public void grabSizeCannotBeZero() { IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); new IdGeneratorImpl( fs, idGeneratorFile(), 0, 100, false, IdType.NODE, () -> 0L ).close(); }
@Test public void shouldNotAcceptMinusOne() { // GIVEN IdGeneratorImpl.createGenerator( fsr.get(), file, 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, false, IdType.NODE, () -> 0L ); expectedException.expect( NegativeIdException.class ); // WHEN idGenerator.setHighId( -1 ); }
@Test public void correctDefragCountWhenHaveIdsInFile() { IdGeneratorImpl.createGenerator( fsr.get(), file, 100, false ); IdGenerator idGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, true, IdType.NODE, () -> 100L ); idGenerator.freeId( 5 ); idGenerator.close(); IdGenerator reloadedIdGenerator = new IdGeneratorImpl( fsr.get(), file, 100, 100, true, IdType.NODE, () -> 100L ); assertEquals( 1, reloadedIdGenerator.getDefragCount() ); assertEquals( 5, reloadedIdGenerator.nextId() ); assertEquals( 0, reloadedIdGenerator.getDefragCount() ); }
/** * It should be fine to set high id to {@link IdGeneratorImpl#INTEGER_MINUS_ONE}. * It will just be never returned from {@link IdGeneratorImpl#nextId()}. */ @Test public void highIdCouldBeSetToReservedId() { IdGeneratorImpl.createGenerator( fsr.get(), file, 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fsr.get(), file, 1, Long.MAX_VALUE, false, IdType.NODE, () -> 0L ); idGenerator.setHighId( IdGeneratorImpl.INTEGER_MINUS_ONE ); assertEquals( IdGeneratorImpl.INTEGER_MINUS_ONE + 1, idGenerator.nextId() ); }
@Test public void mustOverwriteExistingFileIfRequested() { IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1008, 1000, false, IdType.NODE, () -> 0L ); long[] firstFirstIds = new long[]{idGenerator.nextId(), idGenerator.nextId(), idGenerator.nextId()}; idGenerator.close(); IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1008, 1000, false, IdType.NODE, () -> 0L ); long[] secondFirstIds = new long[]{idGenerator.nextId(), idGenerator.nextId(), idGenerator.nextId()}; idGenerator.close(); // Basically, recreating the id file should be the same as start over with the ids. assertThat( secondFirstIds, is( firstFirstIds ) ); }
@Test public void throwsWhenGivenHighIdIsTooHigh() { long maxId = 10; IdGeneratorImpl.createGenerator( fsr.get(), file, 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fsr.get(), file, 1, maxId, false, IdType.RELATIONSHIP_TYPE_TOKEN, () -> 0L ); expectedException.expect( IdCapacityExceededException.class ); expectedException.expectMessage( "Maximum id limit for RELATIONSHIP_TYPE_TOKEN has been reached. Generated id 11 is out of permitted range [0, 10]." ); idGenerator.setHighId( maxId + 1 ); }
IdGenerator idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1008, 1000, false, IdType.NODE, () -> 0L ); try
@Test public void delete() { IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); IdGeneratorImpl idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 10, 1000, false, IdType.NODE, () -> 0L ); long id = idGenerator.nextId(); idGenerator.nextId(); idGenerator.freeId( id ); idGenerator.close(); idGenerator.delete(); assertFalse( idGeneratorFile().exists() ); IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 10, 1000, false, IdType.NODE, () -> 0L ); assertEquals( id, idGenerator.nextId() ); idGenerator.close(); }
@Test public void throwsWhenNextIdIsTooHigh() { long maxId = 10; IdGeneratorImpl.createGenerator( fsr.get(), file, 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fsr.get(), file, 1, maxId, false, IdType.NODE, () -> 0L ); for ( long i = 0; i <= maxId; i++ ) { idGenerator.nextId(); } expectedException.expect( IdCapacityExceededException.class ); expectedException.expectMessage( "Maximum id limit for NODE has been reached. Generated id 11 is out of " + "permitted range [0, 10]." ); idGenerator.nextId(); }
@Test public void makeSureMagicMinusOneCannotBeReturnedEvenIfFreed() { IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1, new NodeRecordFormat().getMaxId(), false, IdType.NODE, () -> 0L ); long magicMinusOne = (long) Math.pow( 2, 32 ) - 1; idGenerator.setHighId( magicMinusOne ); assertEquals( magicMinusOne + 1, idGenerator.nextId() ); idGenerator.freeId( magicMinusOne - 1 ); idGenerator.freeId( magicMinusOne ); closeIdGenerator( idGenerator ); idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1, new NodeRecordFormat().getMaxId(), false, IdType.NODE, () -> 0L ); assertEquals( magicMinusOne - 1, idGenerator.nextId() ); assertEquals( magicMinusOne + 2, idGenerator.nextId() ); closeIdGenerator( idGenerator ); }
private void makeSureMagicMinusOneIsSkipped( RecordFormat format ) { deleteIdGeneratorFile(); IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); IdGenerator idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1, format.getMaxId(), false, IdType.NODE, () -> 0L ); long id = (long) Math.pow( 2, 32 ) - 3; idGenerator.setHighId( id ); assertEquals( id, idGenerator.nextId() ); assertEquals( id + 1, idGenerator.nextId() ); // Here we make sure that id+2 (integer -1) is skipped assertEquals( id + 3, idGenerator.nextId() ); assertEquals( id + 4, idGenerator.nextId() ); assertEquals( id + 5, idGenerator.nextId() ); closeIdGenerator( idGenerator ); }
private void makeSureIdCapacityCannotBeExceeded( RecordFormat format ) { deleteIdGeneratorFile(); IdGeneratorImpl.createGenerator( fs, idGeneratorFile(), 0, false ); long maxValue = format.getMaxId(); IdGenerator idGenerator = new IdGeneratorImpl( fs, idGeneratorFile(), 1, maxValue - 1, false, IdType.NODE, () -> 0L ); long id = maxValue - 2; idGenerator.setHighId( id ); assertEquals( id, idGenerator.nextId() ); assertEquals( id + 1, idGenerator.nextId() ); try { idGenerator.nextId(); fail( "Id capacity shouldn't be able to be exceeded for " + format ); } catch ( StoreFailureException e ) { // Good } closeIdGenerator( idGenerator ); }
@Test public void shouldReadDefragCountUsingStaticMethod() throws Exception { EphemeralFileSystemAbstraction fs = fsr.get(); IdGeneratorImpl.createGenerator( fs, file, 0, false ); IdGeneratorImpl idGenerator = new IdGeneratorImpl( fs, file, 1, 10000, false, IdType.NODE, () -> 0L ); idGenerator.nextId(); long a = idGenerator.nextId(); idGenerator.nextId(); long b = idGenerator.nextId(); idGenerator.nextId(); idGenerator.freeId( a ); idGenerator.freeId( b ); long expectedDefragCount = idGenerator.getDefragCount(); idGenerator.close(); long actualDefragCount = IdGeneratorImpl.readDefragCount( fs, file ); assertEquals( 2, expectedDefragCount ); assertEquals( expectedDefragCount, actualDefragCount ); }