use of org.neo4j.test.Race in project neo4j by neo4j.
the class KernelTransactionsTest method shouldBeAbleToSnapshotDuringHeavyLoad.
@Test
public void shouldBeAbleToSnapshotDuringHeavyLoad() throws Throwable {
// GIVEN
final KernelTransactions transactions = newKernelTransactions();
Race race = new Race();
final int threads = 50;
final AtomicBoolean end = new AtomicBoolean();
final AtomicReferenceArray<KernelTransactionsSnapshot> snapshots = new AtomicReferenceArray<>(threads);
// Representing "transaction" threads
for (int i = 0; i < threads; i++) {
final int threadIndex = i;
race.addContestant(() -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
while (!end.get()) {
try (KernelTransaction transaction = getKernelTransaction(transactions)) {
parkNanos(MILLISECONDS.toNanos(random.nextInt(3)));
if (snapshots.get(threadIndex) == null) {
snapshots.set(threadIndex, transactions.get());
parkNanos(MILLISECONDS.toNanos(random.nextInt(3)));
}
} catch (TransactionFailureException e) {
throw new RuntimeException(e);
}
}
});
}
// Just checks snapshots
race.addContestant(() -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
int snapshotsLeft = 1_000;
while (snapshotsLeft > 0) {
int threadIndex = random.nextInt(threads);
KernelTransactionsSnapshot snapshot = snapshots.get(threadIndex);
if (snapshot != null && snapshot.allClosed()) {
snapshotsLeft--;
snapshots.set(threadIndex, null);
}
}
// End condition of this test can be described as:
// when 1000 snapshots have been seen as closed.
// setting this boolean to true will have all other threads end as well so that race.go() will end
end.set(true);
});
// WHEN
race.go();
}
use of org.neo4j.test.Race in project neo4j by neo4j.
the class LegacyBatchIndexApplierTest method shouldOrderTransactionsMakingLegacyIndexChanges.
@Test
public void shouldOrderTransactionsMakingLegacyIndexChanges() throws Throwable {
// GIVEN
Map<String, Integer> names = MapUtil.genericMap("first", 0, "second", 1);
Map<String, Integer> keys = MapUtil.genericMap("key", 0);
String applierName = "test-applier";
LegacyIndexApplierLookup applierLookup = mock(LegacyIndexApplierLookup.class);
when(applierLookup.newApplier(anyString(), anyBoolean())).thenReturn(mock(TransactionApplier.class));
IndexConfigStore config = newIndexConfigStore(names, applierName);
// WHEN multiple legacy index transactions are running, they should be done in order
SynchronizedArrayIdOrderingQueue queue = new SynchronizedArrayIdOrderingQueue(10);
final AtomicLong lastAppliedTxId = new AtomicLong(-1);
Race race = new Race();
for (long i = 0; i < 100; i++) {
final long txId = i;
race.addContestant(() -> {
try (LegacyBatchIndexApplier applier = new LegacyBatchIndexApplier(config, applierLookup, queue, INTERNAL)) {
TransactionToApply txToApply = new TransactionToApply(new PhysicalTransactionRepresentation(new ArrayList<>()));
FakeCommitment commitment = new FakeCommitment(txId, mock(TransactionIdStore.class));
commitment.setHasLegacyIndexChanges(true);
txToApply.commitment(commitment, txId);
TransactionApplier txApplier = applier.startTx(txToApply);
// Make sure threads are unordered
Thread.sleep(ThreadLocalRandom.current().nextInt(5));
// THEN
assertTrue(lastAppliedTxId.compareAndSet(txId - 1, txId));
// Closing manually instead of using try-with-resources since we have no additional work to do in
// txApplier
txApplier.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
queue.offer(txId);
}
race.go();
}
use of org.neo4j.test.Race in project neo4j by neo4j.
the class NodeLabelsCacheTest method shouldSupportConcurrentGet.
@Test
public void shouldSupportConcurrentGet() throws Throwable {
// GIVEN
int highLabelId = 10, numberOfNodes = 100;
int[][] expectedLabels = new int[numberOfNodes][];
NodeLabelsCache cache = new NodeLabelsCache(NumberArrayFactory.AUTO, highLabelId);
for (int i = 0; i < numberOfNodes; i++) {
cache.put(i, asLongArray(expectedLabels[i] = randomLabels(random.nextInt(5), highLabelId)));
}
// WHEN
Race getRace = new Race();
for (int i = 0; i < 10; i++) {
getRace.addContestant(new LabelGetter(cache, expectedLabels, numberOfNodes));
}
// THEN expected labels should be had (asserted in LabelGetter), and no exceptions (propagated by go())
getRace.go();
}
use of org.neo4j.test.Race in project neo4j by neo4j.
the class TerminationOfSlavesDuringPullUpdatesTest method slavesTerminateOrReadConsistentDataWhenApplyingBatchLargerThanSafeZone.
@Test
public void slavesTerminateOrReadConsistentDataWhenApplyingBatchLargerThanSafeZone() throws Throwable {
long safeZone = TimeUnit.MILLISECONDS.toMillis(0);
clusterRule.withSharedSetting(HaSettings.id_reuse_safe_zone_time, String.valueOf(safeZone));
// given
final ClusterManager.ManagedCluster cluster = clusterRule.startCluster();
HighlyAvailableGraphDatabase master = cluster.getMaster();
// when
// ... slaves and master has node with long string property
long entityId = action.createInitialEntity(master);
cluster.sync();
// ... and property is removed on master
action.removeProperties(master, entityId);
Thread.sleep(100);
// ... and maintenance is called to make sure "safe" ids are freed to be reused
forceMaintenance(master);
// ... and a new property is created on master that
action.setNewProperties(master, entityId);
final HighlyAvailableGraphDatabase slave = cluster.getAnySlave();
Race race = new Race();
final AtomicBoolean end = new AtomicBoolean(false);
for (int i = 0; i < READER_CONTESTANTS; i++) {
race.addContestant(readContestant(action, entityId, slave, end));
}
race.addContestant(pullUpdatesContestant(slave, end));
race.go();
}
use of org.neo4j.test.Race in project neo4j by neo4j.
the class NodeIdReuseStressIT method nodeIdsReused.
@Test
public void nodeIdsReused() throws Throwable {
createInitialNodes(db);
long initialHighestNodeId = highestNodeId(db);
Race race = new Race();
for (int i = 0; i < CONTESTANTS_COUNT; i++) {
if (i % 2 == 0) {
race.addContestant(new NodeCreator(db));
} else {
race.addContestant(new NodeRemover(db));
}
}
race.go();
int writeContestants = CONTESTANTS_COUNT / 2;
int createdNodes = writeContestants * OPERATIONS_COUNT;
long highestNodeIdWithoutReuse = initialHighestNodeId + createdNodes;
long currentHighestNodeId = highestNodeId(db);
assertThat(currentHighestNodeId, lessThan(highestNodeIdWithoutReuse));
}
Aggregations