use of org.junit.jupiter.params.provider.ValueSource in project neo4j by neo4j.
the class GenerateIndexUpdatesStepTest method shouldSendSingleBatchIfBelowMaxSizeThreshold.
@ValueSource(booleans = { true, false })
@ParameterizedTest
void shouldSendSingleBatchIfBelowMaxSizeThreshold(boolean alsoWrite) throws Exception {
// given
StubStorageCursors data = someUniformData(10);
TestPropertyScanConsumer scanConsumer = new TestPropertyScanConsumer();
GenerateIndexUpdatesStep<StorageNodeCursor> step = new GenerateIndexUpdatesStep(new SimpleStageControl(), DEFAULT, data, alwaysTrue(), new NodeCursorBehaviour(data), new int[] { LABEL }, scanConsumer, null, NO_LOCKING, 1, mebiBytes(1), alsoWrite, PageCacheTracer.NULL, INSTANCE);
// when
CapturingBatchSender<GeneratedIndexUpdates> sender = new CapturingBatchSender<>();
step.process(allNodeIds(data), sender, NULL);
// then
if (alsoWrite) {
assertThat(sender.batches).isEmpty();
assertThat(scanConsumer.batches.size()).isEqualTo(1);
assertThat(scanConsumer.batches.get(0).size()).isEqualTo(10);
} else {
assertThat(sender.batches.size()).isEqualTo(1);
assertThat(scanConsumer.batches).isEmpty();
}
}
use of org.junit.jupiter.params.provider.ValueSource in project neo4j by neo4j.
the class GenerateIndexUpdatesStepTest method shouldGenerateEntityTokenUpdates.
@ValueSource(booleans = { true, false })
@ParameterizedTest
void shouldGenerateEntityTokenUpdates(boolean alsoWrite) throws Exception {
// given
StubStorageCursors data = someUniformData(10);
TestTokenScanConsumer scanConsumer = new TestTokenScanConsumer();
GenerateIndexUpdatesStep<StorageNodeCursor> step = new GenerateIndexUpdatesStep<>(new SimpleStageControl(), DEFAULT, data, alwaysTrue(), new NodeCursorBehaviour(data), new int[] { LABEL }, null, scanConsumer, NO_LOCKING, 1, mebiBytes(1), alsoWrite, PageCacheTracer.NULL, INSTANCE);
Set<TestTokenScanConsumer.Record> expectedUpdates = new HashSet<>();
try (StorageNodeCursor cursor = data.allocateNodeCursor(NULL)) {
cursor.scan();
while (cursor.next()) {
expectedUpdates.add(new TestTokenScanConsumer.Record(cursor.entityReference(), cursor.labels()));
}
}
// when
CapturingBatchSender<GeneratedIndexUpdates> sender = new CapturingBatchSender<>();
step.process(allNodeIds(data), sender, NULL);
// then
if (alsoWrite) {
for (TestTokenScanConsumer.Record tokenUpdate : scanConsumer.batches.get(0)) {
assertThat(expectedUpdates.remove(tokenUpdate)).isTrue();
}
} else {
GeneratedIndexUpdates updates = sender.batches.get(0);
updates.completeBatch();
for (TestTokenScanConsumer.Record tokenUpdate : scanConsumer.batches.get(0)) {
assertThat(expectedUpdates.remove(tokenUpdate)).isTrue();
}
}
assertThat(expectedUpdates).isEmpty();
}
use of org.junit.jupiter.params.provider.ValueSource in project neo4j by neo4j.
the class StoreScanStageTest method shouldGenerateUpdatesInParallel.
@ValueSource(booleans = { true, false })
@ParameterizedTest(name = "parallelWrite={0}")
void shouldGenerateUpdatesInParallel(boolean parallelWrite) {
// given
StubStorageCursors data = someData();
EntityIdIterator entityIdIterator = new CursorEntityIdIterator<>(data.allocateNodeCursor(NULL));
var propertyConsumer = new ThreadCapturingPropertyConsumer();
var tokenConsumer = new ThreadCapturingTokenConsumer();
ControlledLockFunction lockFunction = new ControlledLockFunction();
StoreScanStage<StorageNodeCursor> scan = new StoreScanStage<>(dbConfig, config, ct -> entityIdIterator, NO_EXTERNAL_UPDATES, new AtomicBoolean(true), data, new int[] { LABEL }, alwaysTrue(), propertyConsumer, tokenConsumer, new NodeCursorBehaviour(data), lockFunction, parallelWrite, jobScheduler, PageCacheTracer.NULL, EmptyMemoryTracker.INSTANCE);
// when
runScan(scan);
// then it completes and we see > 1 threads
assertThat(lockFunction.seenThreads.size()).isGreaterThan(1);
if (parallelWrite) {
assertThat(propertyConsumer.seenThreads.size()).isGreaterThan(1);
assertThat(tokenConsumer.seenThreads.size()).isGreaterThan(1);
} else {
assertThat(propertyConsumer.seenThreads.size()).isEqualTo(1);
assertThat(tokenConsumer.seenThreads.size()).isEqualTo(1);
}
}
use of org.junit.jupiter.params.provider.ValueSource in project neo4j by neo4j.
the class RelationshipLockHelperTest method shouldTakeAllRelevantLocksForDeletion.
@ParameterizedTest
@ValueSource(ints = { 1, 10, 100, 1000 })
void shouldTakeAllRelevantLocksForDeletion(int numNodes) {
// Given
MutableLongObjectMap<RecordAccess.RecordProxy<RelationshipRecord, Void>> proxies = LongObjectMaps.mutable.empty();
MutableLongBag expectedLocks = LongBags.mutable.empty();
MutableLongSet idsToDelete = LongSets.mutable.empty();
int maxId = numNodes * 10;
for (int i = 0; i < numNodes; i++) {
long id = random.nextInt(maxId);
if (idsToDelete.add(id)) {
VolatileRelationshipRecord record = new VolatileRelationshipRecord(id, expectedLocks, maxId);
var proxy = mock(RecordAccess.RecordProxy.class);
when(proxy.forReadingLinkage()).thenAnswer(invocation -> new RelationshipRecord(record.maybeChange()));
proxies.put(id, proxy);
}
}
RecordAccess<RelationshipRecord, Void> relRecords = mock(RecordAccess.class);
when(relRecords.getOrLoad(Mockito.anyLong(), Mockito.any(), Mockito.any())).thenAnswer(invocation -> proxies.get(invocation.getArgument(0)));
TrackingResourceLocker locks = new TrackingResourceLocker(random, NO_MONITOR).withStrictAssertionsOn(ResourceTypes.RELATIONSHIP);
// When
RelationshipLockHelper.lockRelationshipsInOrder(idsAsBatch(idsToDelete), NULL_REFERENCE.longValue(), relRecords, locks, CursorContext.NULL, EmptyMemoryTracker.INSTANCE);
// Then
assertThat(locks.getExclusiveLocks(ResourceTypes.RELATIONSHIP).toSortedArray()).containsExactly(expectedLocks.toSet().toSortedArray());
}
use of org.junit.jupiter.params.provider.ValueSource in project neo4j by neo4j.
the class PropertyDeleterTest method shouldHandlePropertyChainDeletionOnUnusedRecord.
@ValueSource(booleans = { true, false })
@ParameterizedTest
void shouldHandlePropertyChainDeletionOnUnusedRecord(boolean log) {
// given
startStore(log);
NodeStore nodeStore = neoStores.getNodeStore();
NodeRecord node = nodeStore.newRecord();
node.setId(nodeStore.nextId(NULL));
List<PropertyBlock> properties = new ArrayList<>();
for (int i = 0; i < 20; i++) {
properties.add(encodedValue(i, random.nextValue()));
}
DirectRecordAccessSet initialChanges = new DirectRecordAccessSet(neoStores, idGeneratorFactory, NULL);
long firstPropId = propertyCreator.createPropertyChain(node, properties.iterator(), initialChanges.getPropertyRecords());
node.setNextProp(firstPropId);
// should update all the changed records directly into the store
initialChanges.commit();
// create a cycle in the property chain A -> B
// ^---v
List<Value> valuesInTheFirstTwoRecords = new ArrayList<>();
PropertyRecord firstPropRecord = propertyStore.getRecord(firstPropId, propertyStore.newRecord(), RecordLoad.NORMAL, NULL);
readValuesFromPropertyRecord(firstPropRecord, valuesInTheFirstTwoRecords);
long secondPropId = firstPropRecord.getNextProp();
PropertyRecord secondPropRecord = propertyStore.getRecord(secondPropId, propertyStore.newRecord(), RecordLoad.NORMAL, NULL);
readValuesFromPropertyRecord(secondPropRecord, valuesInTheFirstTwoRecords);
long thirdPropId = secondPropRecord.getNextProp();
PropertyRecord thirdPropRecord = propertyStore.getRecord(thirdPropId, propertyStore.newRecord(), RecordLoad.NORMAL, NULL);
thirdPropRecord.setInUse(false);
propertyStore.updateRecord(thirdPropRecord, NULL);
// when
DirectRecordAccessSet changes = new DirectRecordAccessSet(neoStores, idGeneratorFactory, NULL);
deleter.deletePropertyChain(node, changes.getPropertyRecords());
changes.commit();
// then
assertEquals(Record.NO_NEXT_PROPERTY.longValue(), node.getNextProp());
assertFalse(propertyStore.getRecord(firstPropId, propertyStore.newRecord(), RecordLoad.CHECK, NULL).inUse());
assertFalse(propertyStore.getRecord(secondPropId, propertyStore.newRecord(), RecordLoad.CHECK, NULL).inUse());
assertLogContains("Deleted inconsistent property chain with unused record", log);
}
Aggregations