package org.webpieces.httpfrontend.api; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.webpieces.data.api.DataWrapper; import org.webpieces.httpcommon.api.ResponseId; import org.webpieces.httpcommon.api.ResponseListener; import org.webpieces.httpparser.api.dto.HttpRequest; import org.webpieces.httpparser.api.dto.HttpResponse; import com.webpieces.http2parser.api.dto.lib.Http2Header; class MockResponseListener implements ResponseListener { private ConcurrentHashMap<ResponseId, List<Object>> responseLog = new ConcurrentHashMap<>(); private ConcurrentHashMap<ResponseId, Boolean> completed = new ConcurrentHashMap<>(); private ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1); private int delayMs = 0; public MockResponseListener(int delayMs) { this.delayMs = delayMs; } public MockResponseListener() { } private List<Object> responseListForId(ResponseId id) { List<Object> list = responseLog.get(id); if(list == null) { list = new ArrayList<>(); responseLog.put(id, list); } return list; } @Override public CompletableFuture<Void> incomingData(DataWrapper data, ResponseId id, boolean isLastData) { responseListForId(id).add(data); if(isLastData) { completed.put(id, true); synchronized (this) { this.notifyAll(); } } CompletableFuture<Void> future = new CompletableFuture<>(); // Wait a little bit before completing scheduledExecutorService.schedule(() -> future.complete(null), delayMs, TimeUnit.MILLISECONDS); return future; } @Override public void incomingTrailer(List<Http2Header> headerList, ResponseId id, boolean isComplete) { throw new UnsupportedOperationException(); } @Override public void incomingResponse(HttpResponse resp, HttpRequest req, ResponseId id, boolean isComplete) { responseListForId(id).add(resp); if(isComplete) { completed.put(id, true); synchronized (this) { this.notifyAll(); } } } public synchronized ConcurrentHashMap<ResponseId, List<Object>> getResponseLog(long waitTimeMs, int count) { try { return getResponseLogImpl(waitTimeMs, count); } catch (InterruptedException e) { throw new RuntimeException("failed waiting", e); } } private synchronized ConcurrentHashMap<ResponseId, List<Object>> getResponseLogImpl(long waitTimeMs, int count) throws InterruptedException { long start = System.currentTimeMillis(); while(completed.size() < count) { this.wait(waitTimeMs+500); if(completed.size() >= count) return responseLog; long time = System.currentTimeMillis() - start; if(time > waitTimeMs) throw new IllegalStateException("While waiting for "+count+" responses, some or all never came. count that came="+completed.size()); } return responseLog; } @Override public void failure(Throwable e) { } public void clear() { completed.clear(); responseLog.clear(); } }