From 610c02c66e3ed32bdaab0dc48fd7ee43e90e81ba Mon Sep 17 00:00:00 2001 From: mikereiche Date: Mon, 15 Jun 2020 13:00:25 -0700 Subject: [PATCH] DATACOUCH-484 - test to demonstrate that parameters are thread-safe --- .../couchbase/domain/AirportRepository.java | 4 + ...chbaseRepositoryQueryIntegrationTests.java | 86 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java b/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java index d643e685..36c82c94 100644 --- a/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java +++ b/src/test/java/org/springframework/data/couchbase/domain/AirportRepository.java @@ -18,6 +18,7 @@ package org.springframework.data.couchbase.domain; import java.util.List; +import org.springframework.data.couchbase.repository.Query; import org.springframework.data.couchbase.repository.ScanConsistency; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; @@ -33,4 +34,7 @@ public interface AirportRepository extends PagingAndSortingRepository findAllByIata(String iata); + @Query("#{#n1ql.selectEntity} where iata = $1") + List getAllByIata(String iata); + } diff --git a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java index 5974b050..3575a72c 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java @@ -19,6 +19,10 @@ package org.springframework.data.couchbase.repository; import static org.junit.jupiter.api.Assertions.*; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -75,6 +79,88 @@ public class CouchbaseRepositoryQueryIntegrationTests extends ClusterAwareIntegr System.err.println(airports); } + @Test + void threadSafeParametersTest() { + String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" }; + Future[] future = new Future[iatas.length]; + ExecutorService executorService = Executors.newFixedThreadPool(iatas.length); + + try { + Callable[] suppliers = new Callable[iatas.length]; + for (int i = 0; i < iatas.length; i++) { + Airport airport = new Airport("airports::" + iatas[i], iatas[i] /*iata*/, iatas[i] /* lcao */); + airportRepository.save(airport); + final int idx = i; + suppliers[i] = () -> { + System.out.println(Thread.currentThread() + " " + iatas[idx] + " ->"); + try { + Thread.sleep(iatas.length - idx); // so they are executed out-of-order + } catch (InterruptedException ie) { + ; + } + String foundName = airportRepository.findAllByIata(iatas[idx]).get(0).getIata(); + System.out.println(Thread.currentThread() + " " + iatas[idx] + " <- "); + assertEquals(iatas[idx], foundName); + return iatas[idx].equals(foundName); + }; + } + for (int i = 0; i < iatas.length; i++) { + future[i] = executorService.submit(suppliers[i]); + } + for (int i = 0; i < iatas.length; i++) { + future[i].get(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + for (int i = 0; i < iatas.length; i++) { + Airport airport = new Airport("airports::" + iatas[i], iatas[i] /*iata*/, iatas[i] /* lcao */); + airportRepository.delete(airport); + } + } + } + + @Test + void threadSafeStringParametersTest() { + String[] iatas = { "JFK", "IAD", "SFO", "SJC", "SEA", "LAX", "PHX" }; + Future[] future = new Future[iatas.length]; + ExecutorService executorService = Executors.newFixedThreadPool(iatas.length); + + try { + Callable[] suppliers = new Callable[iatas.length]; + for (int i = 0; i < iatas.length; i++) { + Airport airport = new Airport("airports::" + iatas[i], iatas[i] /*iata*/, iatas[i] /* lcao */); + airportRepository.save(airport); + final int idx = i; + suppliers[i] = () -> { + System.out.println(Thread.currentThread() + " " + iatas[idx] + " ->"); + try { + Thread.sleep(iatas.length - idx); // so they are executed out-of-order + } catch (InterruptedException ie) { + ; + } + String foundName = airportRepository.getAllByIata(iatas[idx]).get(0).getIata(); + System.out.println(Thread.currentThread() + " " + iatas[idx] + " <- "); + assertEquals(iatas[idx], foundName); + return iatas[idx].equals(foundName); + }; + } + for (int i = 0; i < iatas.length; i++) { + future[i] = executorService.submit(suppliers[i]); + } + for (int i = 0; i < iatas.length; i++) { + future[i].get(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + for (int i = 0; i < iatas.length; i++) { + Airport airport = new Airport("airports::" + iatas[i], iatas[i] /*iata*/, iatas[i] /* lcao */); + airportRepository.delete(airport); + } + } + } + @Configuration @EnableCouchbaseRepositories("org.springframework.data.couchbase") static class Config extends AbstractCouchbaseConfiguration {