+74
-3
@@ -28,6 +28,9 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -64,9 +67,77 @@ class SimilarAsinImageEmbedderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultsImageDownloadPoolToEight() {
|
||||
assertEquals(8, new SimilarAsinProperties().getImageDownloadPoolSize());
|
||||
assertEquals(8, embedder.downloadPoolSize());
|
||||
void defaultsImageDownloadPoolToTwoAndCapsItByVisibleCpu() {
|
||||
assertEquals(2, new SimilarAsinProperties().getImageDownloadPoolSize());
|
||||
assertEquals(Math.min(2, SimilarAsinImageEmbedder.cpuBoundPoolLimit()), embedder.downloadPoolSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
void clampsOversizedImagePoolConfigurationByVisibleCpu() {
|
||||
SimilarAsinProperties configured = new SimilarAsinProperties();
|
||||
configured.setImageDownloadPoolSize(Integer.MAX_VALUE);
|
||||
SimilarAsinImageEmbedder limited = new SimilarAsinImageEmbedder(configured, createOssStorageService());
|
||||
try {
|
||||
assertEquals(SimilarAsinImageEmbedder.cpuBoundPoolLimit(), limited.downloadPoolSize());
|
||||
} finally {
|
||||
limited.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void concurrentRequestsForSameUrlDownloadAndResizeOnlyOnce() throws Exception {
|
||||
SimilarAsinImageEmbedder shared = new SimilarAsinImageEmbedder(
|
||||
properties(2, 5, null), createOssStorageService());
|
||||
AtomicInteger networkCalls = new AtomicInteger();
|
||||
CountDownLatch releaseNetwork = new CountDownLatch(1);
|
||||
CountDownLatch firstNetworkCall = new CountDownLatch(1);
|
||||
replaceHttpClient(shared, new OkHttpClient.Builder()
|
||||
.addInterceptor(chain -> {
|
||||
networkCalls.incrementAndGet();
|
||||
firstNetworkCall.countDown();
|
||||
try {
|
||||
if (!releaseNetwork.await(2, TimeUnit.SECONDS)) {
|
||||
throw new IOException("test network release timed out");
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("test network interrupted", ex);
|
||||
}
|
||||
return response(chain.request(), 200, "OK", createJpegBytes());
|
||||
})
|
||||
.build());
|
||||
ExecutorService callers = Executors.newFixedThreadPool(2);
|
||||
CountDownLatch start = new CountDownLatch(1);
|
||||
try {
|
||||
Future<SimilarAsinImageEmbedder.ResizedImage> first = callers.submit(() -> {
|
||||
start.await();
|
||||
return shared.fetchAndResizeForCache("https://images.example.com/shared.jpg");
|
||||
});
|
||||
Future<SimilarAsinImageEmbedder.ResizedImage> second = callers.submit(() -> {
|
||||
start.await();
|
||||
return shared.fetchAndResizeForCache("https://images.example.com/shared.jpg");
|
||||
});
|
||||
|
||||
start.countDown();
|
||||
assertTrue(firstNetworkCall.await(1, TimeUnit.SECONDS));
|
||||
Thread.sleep(100L);
|
||||
releaseNetwork.countDown();
|
||||
|
||||
assertNotNull(first.get(2, TimeUnit.SECONDS));
|
||||
assertNotNull(second.get(2, TimeUnit.SECONDS));
|
||||
assertEquals(1, networkCalls.get());
|
||||
} finally {
|
||||
releaseNetwork.countDown();
|
||||
callers.shutdownNow();
|
||||
shared.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void largeJpegDecodeUsesPowerOfTwoSourceSubsampling() {
|
||||
assertEquals(1, SimilarAsinImageEmbedder.jpegSourceSubsampling(2559, 1200));
|
||||
assertEquals(2, SimilarAsinImageEmbedder.jpegSourceSubsampling(3200, 2400));
|
||||
assertEquals(4, SimilarAsinImageEmbedder.jpegSourceSubsampling(6000, 4000));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user