Skip to content

Commit 86eeec2

Browse files
committed
Add test to verify the distributor creates sessions in parallel
1 parent 3f896ba commit 86eeec2

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

java/server/test/org/openqa/selenium/grid/distributor/local/LocalDistributorTest.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,27 @@
5858
import java.time.Duration;
5959
import java.time.Instant;
6060
import java.util.ArrayList;
61+
import java.util.Collections;
62+
import java.util.HashSet;
6163
import java.util.List;
6264
import java.util.Map;
6365
import java.util.Optional;
6466
import java.util.Set;
6567
import java.util.UUID;
6668
import java.util.concurrent.Callable;
69+
import java.util.concurrent.CompletableFuture;
70+
import java.util.concurrent.ConcurrentHashMap;
71+
import java.util.concurrent.ConcurrentSkipListSet;
72+
import java.util.concurrent.CountDownLatch;
73+
import java.util.concurrent.ExecutionException;
74+
import java.util.concurrent.ExecutorService;
6775
import java.util.concurrent.Executors;
6876
import java.util.concurrent.Future;
6977
import java.util.concurrent.TimeUnit;
78+
import java.util.concurrent.atomic.AtomicBoolean;
79+
import java.util.concurrent.atomic.AtomicInteger;
7080

81+
import static java.util.Collections.newSetFromMap;
7182
import static org.assertj.core.api.Assertions.assertThat;
7283
import static org.assertj.core.api.Assertions.fail;
7384
import static org.openqa.selenium.grid.data.Availability.DRAINING;
@@ -372,6 +383,82 @@ public void testDrainNodeFromNode() {
372383
assertThat(localNode.isDraining()).isTrue();
373384
}
374385

386+
@Test
387+
public void slowStartingNodesShouldNotCauseReservationsToBeSerialized() {
388+
NewSessionQueue queue = new LocalNewSessionQueue(
389+
tracer,
390+
bus,
391+
new DefaultSlotMatcher(),
392+
Duration.ofSeconds(2),
393+
Duration.ofSeconds(2),
394+
registrationSecret);
395+
396+
LocalDistributor distributor = new LocalDistributor(
397+
tracer,
398+
bus,
399+
clientFactory,
400+
new LocalSessionMap(tracer, bus),
401+
queue,
402+
new GridModel(bus),
403+
new DefaultSlotSelector(),
404+
registrationSecret,
405+
Duration.ofMinutes(5),
406+
false);
407+
408+
Capabilities caps = new ImmutableCapabilities("browserName", "cheese");
409+
410+
long delay = 4000;
411+
LocalNode node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)
412+
.add(caps, new TestSessionFactory(caps, (id, c) -> {
413+
try {
414+
Thread.sleep(delay);
415+
} catch (InterruptedException e) {
416+
e.printStackTrace();
417+
}
418+
return new Handler(c);
419+
}))
420+
.build();
421+
422+
distributor.add(node);
423+
424+
Set<Future<Either<SessionNotCreatedException, CreateSessionResponse>>> futures =
425+
newSetFromMap(new ConcurrentHashMap<>());
426+
ExecutorService service = Executors.newFixedThreadPool(2);
427+
428+
long start = System.currentTimeMillis();
429+
futures.add(
430+
service.submit(() -> distributor.newSession(new SessionRequest(
431+
new RequestId(UUID.randomUUID()),
432+
Instant.now(),
433+
Set.of(W3C),
434+
Set.of(caps),
435+
Map.of(),
436+
Map.of()))));
437+
futures.add(
438+
service.submit(() -> distributor.newSession(new SessionRequest(
439+
new RequestId(UUID.randomUUID()),
440+
Instant.now(),
441+
Set.of(W3C),
442+
Set.of(caps),
443+
Map.of(),
444+
Map.of()))));
445+
446+
futures.forEach(f -> {
447+
try {
448+
f.get();
449+
} catch (InterruptedException e) {
450+
fail("Interrupted");
451+
} catch (ExecutionException e) {
452+
throw new RuntimeException(e);
453+
}
454+
});
455+
456+
// If the sessions are created serially, then we expect the first
457+
// session to take up to `delay` ms to complete, followed by the
458+
// second session.
459+
assertThat(System.currentTimeMillis() - start).isLessThan(delay * 2);
460+
}
461+
375462
private class Handler extends Session implements HttpHandler {
376463

377464
private Handler(Capabilities capabilities) {

0 commit comments

Comments
 (0)