use of io.trino.testing.TestingConnectorBehavior.SUPPORTS_UPDATE in project trino by trinodb.
the class BaseConnectorTest method testUpdateRowConcurrently.
// Repeat test with invocationCount for better test coverage, since the tested aspect is inherently non-deterministic.
@Test(timeOut = 60_000, invocationCount = 4)
public void testUpdateRowConcurrently() throws Exception {
if (!hasBehavior(SUPPORTS_UPDATE)) {
// Covered by testUpdate
return;
}
int threads = 4;
CyclicBarrier barrier = new CyclicBarrier(threads);
ExecutorService executor = newFixedThreadPool(threads);
try (TestTable table = new TestTable(getQueryRunner()::execute, "test_concurrent_update", IntStream.range(0, threads).mapToObj(i -> format("col%s integer", i)).collect(joining(", ", "(", ")")))) {
String tableName = table.getName();
assertUpdate(format("INSERT INTO %s VALUES (%s)", tableName, join(",", nCopies(threads, "0"))), 1);
List<Future<Boolean>> futures = IntStream.range(0, threads).mapToObj(threadNumber -> executor.submit(() -> {
barrier.await(10, SECONDS);
try {
String columnName = "col" + threadNumber;
getQueryRunner().execute(format("UPDATE %s SET %s = %s + 1", tableName, columnName, columnName));
return true;
} catch (Exception e) {
RuntimeException trinoException = getTrinoExceptionCause(e);
try {
verifyConcurrentUpdateFailurePermissible(trinoException);
} catch (Throwable verifyFailure) {
if (trinoException != e && verifyFailure != e) {
verifyFailure.addSuppressed(e);
}
throw verifyFailure;
}
return false;
}
})).collect(toImmutableList());
String expected = futures.stream().map(future -> tryGetFutureValue(future, 10, SECONDS).orElseThrow(() -> new RuntimeException("Wait timed out"))).map(success -> success ? "1" : "0").collect(joining(",", "VALUES (", ")"));
assertThat(query("TABLE " + tableName)).matches(expected);
} finally {
executor.shutdownNow();
executor.awaitTermination(10, SECONDS);
}
}
Aggregations