How to use complete method of org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue class

Best Selenium code snippet using org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue.complete

Source:DistributorTest.java Github

copy

Full Screen

1// Licensed to the Software Freedom Conservancy (SFC) under one2// or more contributor license agreements. See the NOTICE file3// distributed with this work for additional information4// regarding copyright ownership. The SFC licenses this file5// to you under the Apache License, Version 2.0 (the6// "License"); you may not use this file except in compliance7// with the License. You may obtain a copy of the License at8//9// http://www.apache.org/licenses/LICENSE-2.010//11// Unless required by applicable law or agreed to in writing,12// software distributed under the License is distributed on an13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY14// KIND, either express or implied. See the License for the15// specific language governing permissions and limitations16// under the License.17package org.openqa.selenium.grid.distributor;18import com.google.common.collect.ImmutableMap;19import com.google.common.collect.ImmutableSet;20import org.junit.Assert;21import org.junit.Before;22import org.junit.Ignore;23import org.junit.Test;24import org.openqa.selenium.Capabilities;25import org.openqa.selenium.ImmutableCapabilities;26import org.openqa.selenium.MutableCapabilities;27import org.openqa.selenium.NoSuchSessionException;28import org.openqa.selenium.SessionNotCreatedException;29import org.openqa.selenium.TimeoutException;30import org.openqa.selenium.events.EventBus;31import org.openqa.selenium.events.local.GuavaEventBus;32import org.openqa.selenium.grid.data.Availability;33import org.openqa.selenium.grid.data.CreateSessionRequest;34import org.openqa.selenium.grid.data.CreateSessionResponse;35import org.openqa.selenium.grid.data.DistributorStatus;36import org.openqa.selenium.grid.data.NodeDrainComplete;37import org.openqa.selenium.grid.data.NodeHeartBeatEvent;38import org.openqa.selenium.grid.data.NodeStatus;39import org.openqa.selenium.grid.data.Session;40import org.openqa.selenium.grid.data.Slot;41import org.openqa.selenium.grid.distributor.local.LocalDistributor;42import org.openqa.selenium.grid.distributor.remote.RemoteDistributor;43import org.openqa.selenium.grid.node.HealthCheck;44import org.openqa.selenium.grid.node.Node;45import org.openqa.selenium.grid.node.local.LocalNode;46import org.openqa.selenium.grid.security.Secret;47import org.openqa.selenium.grid.sessionmap.SessionMap;48import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap;49import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;50import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueuer;51import org.openqa.selenium.grid.testing.EitherAssert;52import org.openqa.selenium.grid.testing.PassthroughHttpClient;53import org.openqa.selenium.grid.testing.TestSessionFactory;54import org.openqa.selenium.grid.web.CombinedHandler;55import org.openqa.selenium.internal.Either;56import org.openqa.selenium.net.PortProber;57import org.openqa.selenium.remote.Dialect;58import org.openqa.selenium.remote.NewSessionPayload;59import org.openqa.selenium.remote.SessionId;60import org.openqa.selenium.remote.http.HttpClient;61import org.openqa.selenium.remote.http.HttpHandler;62import org.openqa.selenium.remote.http.HttpRequest;63import org.openqa.selenium.remote.http.HttpResponse;64import org.openqa.selenium.remote.tracing.DefaultTestTracer;65import org.openqa.selenium.remote.tracing.Tracer;66import org.openqa.selenium.support.ui.FluentWait;67import org.openqa.selenium.support.ui.Wait;68import java.io.IOException;69import java.io.UncheckedIOException;70import java.net.MalformedURLException;71import java.net.URI;72import java.net.URISyntaxException;73import java.net.URL;74import java.time.Duration;75import java.time.Instant;76import java.util.HashMap;77import java.util.HashSet;78import java.util.Map;79import java.util.Set;80import java.util.UUID;81import java.util.concurrent.CountDownLatch;82import java.util.concurrent.TimeUnit;83import java.util.concurrent.atomic.AtomicBoolean;84import java.util.concurrent.atomic.AtomicReference;85import java.util.logging.Logger;86import java.util.stream.Collectors;87import static org.assertj.core.api.Assertions.assertThat;88import static org.assertj.core.api.Assertions.fail;89import static org.junit.Assert.assertFalse;90import static org.junit.Assert.assertTrue;91import static org.openqa.selenium.grid.data.Availability.DOWN;92import static org.openqa.selenium.grid.data.Availability.UP;93import static org.openqa.selenium.remote.http.Contents.utf8String;94import static org.openqa.selenium.remote.http.HttpMethod.POST;95public class DistributorTest {96 private static final Logger LOG = Logger.getLogger("Distributor Test");97 private final Secret registrationSecret = new Secret("hellim");98 private final Wait<Object> wait = new FluentWait<>(new Object()).withTimeout(Duration.ofSeconds(5));99 private Tracer tracer;100 private EventBus bus;101 private Distributor local;102 private Capabilities stereotype;103 private Capabilities caps;104 private URI nodeUri;105 private URI routableUri;106 private static <A, B> EitherAssert<A, B> assertThatEither(Either<A, B> either) {107 return new EitherAssert<>(either);108 }109 @Before110 public void setUp() throws URISyntaxException {111 nodeUri = new URI("http://example:5678");112 routableUri = new URI("http://localhost:1234");113 tracer = DefaultTestTracer.createTracer();114 bus = new GuavaEventBus();115 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);116 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(117 tracer,118 bus,119 Duration.ofSeconds(2),120 Duration.ofSeconds(2));121 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(122 tracer,123 bus,124 localNewSessionQueue,125 registrationSecret);126 local = new LocalDistributor(127 tracer,128 bus,129 HttpClient.Factory.createDefault(),130 sessions,131 queuer,132 registrationSecret,133 Duration.ofMinutes(5));134 stereotype = new ImmutableCapabilities("browserName", "cheese");135 caps = new ImmutableCapabilities("browserName", "cheese");136 }137 @Test138 public void creatingANewSessionWithoutANodeEndsInFailure() {139 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {140 Either<SessionNotCreatedException, CreateSessionResponse> result =141 local.newSession(createRequest(payload));142 assertThatEither(result).isLeft();143 }144 }145 @Test146 public void shouldStartHeartBeatOnNodeRegistration() {147 EventBus bus = new GuavaEventBus();148 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);149 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(150 tracer,151 bus,152 Duration.ofSeconds(2),153 Duration.ofSeconds(2));154 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(155 tracer,156 bus,157 localNewSessionQueue,158 registrationSecret);159 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)160 .add(161 caps,162 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))163 .heartbeatPeriod(Duration.ofSeconds(10))164 .build();165 Distributor distributor = new LocalDistributor(166 tracer,167 bus,168 new PassthroughHttpClient.Factory(node),169 sessions,170 queuer,171 registrationSecret,172 Duration.ofMinutes(5));173 distributor.add(node);174 AtomicBoolean heartbeatStarted = new AtomicBoolean();175 CountDownLatch latch = new CountDownLatch(1);176 bus.addListener(NodeHeartBeatEvent.listener(nodeStatus -> {177 latch.countDown();178 if (node.getId().equals(nodeStatus.getId())) {179 heartbeatStarted.set(true);180 }181 }));182 waitToHaveCapacity(distributor);183 boolean eventFired = false;184 try {185 eventFired = latch.await(30, TimeUnit.SECONDS);186 } catch (InterruptedException e) {187 Assert.fail("Thread Interrupted");188 }189 assertThat(eventFired).isTrue();190 assertThat(heartbeatStarted).isTrue();191 }192 @Test193 public void shouldBeAbleToAddANodeAndCreateASession() {194 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);195 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(196 tracer,197 bus,198 Duration.ofSeconds(2),199 Duration.ofSeconds(2));200 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(201 tracer,202 bus,203 localNewSessionQueue,204 registrationSecret);205 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)206 .add(207 caps,208 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))209 .build();210 Distributor distributor = new LocalDistributor(211 tracer,212 bus,213 new PassthroughHttpClient.Factory(node),214 sessions,215 queuer,216 registrationSecret,217 Duration.ofMinutes(5));218 distributor.add(node);219 waitToHaveCapacity(distributor);220 MutableCapabilities sessionCaps = new MutableCapabilities(caps);221 sessionCaps.setCapability("sausages", "gravy");222 try (NewSessionPayload payload = NewSessionPayload.create(sessionCaps)) {223 Either<SessionNotCreatedException, CreateSessionResponse> result =224 distributor.newSession(createRequest(payload));225 assertThatEither(result).isRight();226 Session session = result.right().getSession();227 assertThat(session.getCapabilities()).isEqualTo(sessionCaps);228 assertThat(session.getUri()).isEqualTo(routableUri);229 }230 }231 @Test232 public void creatingASessionAddsItToTheSessionMap() {233 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);234 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(235 tracer,236 bus,237 Duration.ofSeconds(2),238 Duration.ofSeconds(2));239 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(240 tracer,241 bus,242 localNewSessionQueue,243 registrationSecret);244 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)245 .add(246 caps,247 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))248 .build();249 LocalDistributor distributor = new LocalDistributor(250 tracer,251 bus,252 new PassthroughHttpClient.Factory(node),253 sessions,254 queuer,255 registrationSecret,256 Duration.ofMinutes(5));257 distributor.add(node);258 waitToHaveCapacity(distributor);259 MutableCapabilities sessionCaps = new MutableCapabilities(caps);260 sessionCaps.setCapability("sausages", "gravy");261 try (NewSessionPayload payload = NewSessionPayload.create(sessionCaps)) {262 Either<SessionNotCreatedException, CreateSessionResponse> result =263 distributor.newSession(createRequest(payload));264 assertThatEither(result).isRight();265 Session returned = result.right().getSession();266 Session session = sessions.get(returned.getId());267 assertThat(session.getCapabilities()).isEqualTo(sessionCaps);268 assertThat(session.getUri()).isEqualTo(routableUri);269 }270 }271 @Test272 public void shouldBeAbleToRemoveANode() throws MalformedURLException {273 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);274 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(275 tracer,276 bus,277 Duration.ofSeconds(2),278 Duration.ofSeconds(2));279 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(280 tracer,281 bus,282 localNewSessionQueue,283 registrationSecret);284 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)285 .add(286 caps,287 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))288 .build();289 Distributor local = new LocalDistributor(290 tracer,291 bus,292 new PassthroughHttpClient.Factory(node),293 sessions,294 queuer,295 registrationSecret,296 Duration.ofMinutes(5));297 Distributor distributor = new RemoteDistributor(298 tracer,299 new PassthroughHttpClient.Factory(local),300 new URL("http://does.not.exist"),301 registrationSecret);302 distributor.add(node);303 distributor.remove(node.getId());304 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {305 Either<SessionNotCreatedException, CreateSessionResponse> result =306 local.newSession(createRequest(payload));307 assertThatEither(result).isLeft();308 }309 }310 @Test311 public void testDrainingNodeDoesNotAcceptNewSessions() {312 SessionMap sessions = new LocalSessionMap(tracer, bus);313 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(314 tracer,315 bus,316 Duration.ofSeconds(2),317 Duration.ofSeconds(2));318 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(319 tracer,320 bus,321 localNewSessionQueue,322 registrationSecret);323 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)324 .add(325 caps,326 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))327 .build();328 Distributor distributor = new LocalDistributor(329 tracer,330 bus,331 new PassthroughHttpClient.Factory(node),332 sessions,333 queuer,334 registrationSecret,335 Duration.ofMinutes(5));336 distributor.add(node);337 distributor.drain(node.getId());338 assertTrue(node.isDraining());339 NewSessionPayload payload = NewSessionPayload.create(caps);340 Either<SessionNotCreatedException, CreateSessionResponse> result =341 distributor.newSession(createRequest(payload));342 assertThatEither(result).isLeft();343 }344 @Test345 public void testDrainedNodeShutsDownOnceEmpty() throws InterruptedException {346 SessionMap sessions = new LocalSessionMap(tracer, bus);347 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(348 tracer,349 bus,350 Duration.ofSeconds(2),351 Duration.ofSeconds(2));352 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(353 tracer,354 bus,355 localNewSessionQueue,356 registrationSecret);357 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)358 .add(359 caps,360 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))361 .build();362 CountDownLatch latch = new CountDownLatch(1);363 bus.addListener(NodeDrainComplete.listener(ignored -> latch.countDown()));364 Distributor distributor = new LocalDistributor(365 tracer,366 bus,367 new PassthroughHttpClient.Factory(node),368 sessions,369 queuer,370 registrationSecret,371 Duration.ofMinutes(5));372 distributor.add(node);373 waitToHaveCapacity(distributor);374 distributor.drain(node.getId());375 latch.await(5, TimeUnit.SECONDS);376 assertThat(latch.getCount()).isEqualTo(0);377 assertThat(distributor.getAvailableNodes().size()).isEqualTo(0);378 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {379 Either<SessionNotCreatedException, CreateSessionResponse> result =380 distributor.newSession(createRequest(payload));381 assertThatEither(result).isLeft();382 }383 }384 @Test385 public void drainedNodeDoesNotShutDownIfNotEmpty() throws InterruptedException {386 SessionMap sessions = new LocalSessionMap(tracer, bus);387 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(388 tracer,389 bus,390 Duration.ofSeconds(2),391 Duration.ofSeconds(2));392 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(393 tracer,394 bus,395 localNewSessionQueue,396 registrationSecret);397 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)398 .add(399 caps,400 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))401 .build();402 CountDownLatch latch = new CountDownLatch(1);403 bus.addListener(NodeDrainComplete.listener(ignored -> latch.countDown()));404 Distributor distributor = new LocalDistributor(405 tracer,406 bus,407 new PassthroughHttpClient.Factory(node),408 sessions,409 queuer,410 registrationSecret,411 Duration.ofMinutes(5));412 distributor.add(node);413 waitToHaveCapacity(distributor);414 NewSessionPayload payload = NewSessionPayload.create(caps);415 Either<SessionNotCreatedException, CreateSessionResponse> session =416 distributor.newSession(createRequest(payload));417 assertThatEither(session).isRight();418 distributor.drain(node.getId());419 latch.await(5, TimeUnit.SECONDS);420 assertThat(latch.getCount()).isEqualTo(1);421 assertThat(distributor.getAvailableNodes().size()).isEqualTo(1);422 }423 @Test424 public void drainedNodeShutsDownAfterSessionsFinish() throws InterruptedException {425 SessionMap sessions = new LocalSessionMap(tracer, bus);426 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(427 tracer,428 bus,429 Duration.ofSeconds(2),430 Duration.ofSeconds(2));431 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(432 tracer,433 bus,434 localNewSessionQueue,435 registrationSecret);436 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)437 .add(438 caps,439 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))440 .add(441 caps,442 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))443 .build();444 CountDownLatch latch = new CountDownLatch(1);445 bus.addListener(NodeDrainComplete.listener(ignored -> latch.countDown()));446 Distributor distributor = new LocalDistributor(447 tracer,448 bus,449 new PassthroughHttpClient.Factory(node),450 sessions,451 queuer,452 registrationSecret,453 Duration.ofMinutes(5));454 distributor.add(node);455 waitToHaveCapacity(distributor);456 NewSessionPayload payload = NewSessionPayload.create(caps);457 Either<SessionNotCreatedException, CreateSessionResponse> firstResponse =458 distributor.newSession(createRequest(payload));459 Either<SessionNotCreatedException, CreateSessionResponse> secondResponse =460 distributor.newSession(createRequest(payload));461 distributor.drain(node.getId());462 assertThat(distributor.getAvailableNodes().size()).isEqualTo(1);463 node.stop(firstResponse.right().getSession().getId());464 node.stop(secondResponse.right().getSession().getId());465 latch.await(5, TimeUnit.SECONDS);466 assertThat(latch.getCount()).isEqualTo(0);467 assertThat(distributor.getAvailableNodes().size()).isEqualTo(0);468 }469 @Test470 public void registeringTheSameNodeMultipleTimesOnlyCountsTheFirstTime() {471 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)472 .add(473 caps,474 new TestSessionFactory((id, c) -> new Session(id, nodeUri, stereotype, c, Instant.now())))475 .build();476 local.add(node);477 local.add(node);478 DistributorStatus status = local.getStatus();479 assertThat(status.getNodes().size()).isEqualTo(1);480 }481 @Test482 public void theMostLightlyLoadedNodeIsSelectedFirst() {483 // Create enough hosts so that we avoid the scheduler returning hosts in:484 // * insertion order485 // * reverse insertion order486 // * sorted with most heavily used first487 SessionMap sessions = new LocalSessionMap(tracer, bus);488 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(489 tracer,490 bus,491 Duration.ofSeconds(2),492 Duration.ofSeconds(2));493 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(494 tracer,495 bus,496 localNewSessionQueue,497 registrationSecret);498 Node lightest = createNode(caps, 10, 0);499 Node medium = createNode(caps, 10, 4);500 Node heavy = createNode(caps, 10, 6);501 Node massive = createNode(caps, 10, 8);502 CombinedHandler handler = new CombinedHandler();503 handler.addHandler(lightest);504 handler.addHandler(medium);505 handler.addHandler(heavy);506 handler.addHandler(massive);507 Distributor distributor = new LocalDistributor(508 tracer,509 bus,510 new PassthroughHttpClient.Factory(handler),511 sessions,512 queuer,513 registrationSecret,514 Duration.ofMinutes(5))515 .add(heavy)516 .add(medium)517 .add(lightest)518 .add(massive);519 wait.until(obj -> distributor.getStatus().getNodes().size() == 4);520 wait.until(obj -> distributor.getStatus().hasCapacity());521 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {522 Either<SessionNotCreatedException, CreateSessionResponse> result =523 distributor.newSession(createRequest(payload));524 assertThatEither(result).isRight();525 Session session = result.right().getSession();526 assertThat(session.getUri()).isEqualTo(lightest.getStatus().getUri());527 }528 }529 @Test530 public void shouldUseLastSessionCreatedTimeAsTieBreaker() {531 SessionMap sessions = new LocalSessionMap(tracer, bus);532 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(533 tracer,534 bus,535 Duration.ofSeconds(2),536 Duration.ofSeconds(2));537 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(538 tracer,539 bus,540 localNewSessionQueue,541 registrationSecret);542 Node leastRecent = createNode(caps, 5, 0);543 CombinedHandler handler = new CombinedHandler();544 handler.addHandler(sessions);545 handler.addHandler(leastRecent);546 Distributor distributor = new LocalDistributor(547 tracer,548 bus,549 new PassthroughHttpClient.Factory(handler),550 sessions,551 queuer,552 registrationSecret,553 Duration.ofMinutes(5))554 .add(leastRecent);555 waitToHaveCapacity(distributor);556 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {557 distributor.newSession(createRequest(payload));558 // Will be "leastRecent" by default559 }560 Node middle = createNode(caps, 5, 0);561 handler.addHandler(middle);562 distributor.add(middle);563 waitForAllNodesToHaveCapacity(distributor, 2);564 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {565 Either<SessionNotCreatedException, CreateSessionResponse> result =566 distributor.newSession(createRequest(payload));567 assertThatEither(result).isRight();568 Session session = result.right().getSession();569 // Least lightly loaded is middle570 assertThat(session.getUri()).isEqualTo(middle.getStatus().getUri());571 }572 Node mostRecent = createNode(caps, 5, 0);573 handler.addHandler(mostRecent);574 distributor.add(mostRecent);575 waitForAllNodesToHaveCapacity(distributor, 3);576 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {577 Either<SessionNotCreatedException, CreateSessionResponse> result =578 distributor.newSession(createRequest(payload));579 assertThatEither(result).isRight();580 Session session = result.right().getSession();581 // Least lightly loaded is most recent582 assertThat(session.getUri()).isEqualTo(mostRecent.getStatus().getUri());583 }584 // All the nodes should be equally loaded.585 Map<Capabilities, Integer> expected = getFreeStereotypeCounts(mostRecent.getStatus());586 assertThat(getFreeStereotypeCounts(leastRecent.getStatus())).isEqualTo(expected);587 assertThat(getFreeStereotypeCounts(middle.getStatus())).isEqualTo(expected);588 // All nodes are now equally loaded. We should be going in time order now589 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {590 Either<SessionNotCreatedException, CreateSessionResponse> result =591 distributor.newSession(createRequest(payload));592 assertThatEither(result).isRight();593 Session session = result.right().getSession();594 assertThat(session.getUri()).isEqualTo(leastRecent.getStatus().getUri());595 }596 }597 private Map<Capabilities, Integer> getFreeStereotypeCounts(NodeStatus status) {598 Map<Capabilities, Integer> toReturn = new HashMap<>();599 for (Slot slot : status.getSlots()) {600 int count = toReturn.getOrDefault(slot.getStereotype(), 0);601 count++;602 toReturn.put(slot.getStereotype(), count);603 }604 return toReturn;605 }606 @Test607 public void shouldIncludeHostsThatAreUpInHostList() {608 CombinedHandler handler = new CombinedHandler();609 SessionMap sessions = new LocalSessionMap(tracer, bus);610 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(611 tracer,612 bus,613 Duration.ofSeconds(2),614 Duration.ofSeconds(2));615 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(616 tracer,617 bus,618 localNewSessionQueue,619 registrationSecret);620 handler.addHandler(sessions);621 URI uri = createUri();622 Node alwaysDown = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)623 .add(624 caps,625 new TestSessionFactory((id, c) -> new Session(id, uri, stereotype, c, Instant.now())))626 .advanced()627 .healthCheck(() -> new HealthCheck.Result(DOWN, "Boo!"))628 .build();629 handler.addHandler(alwaysDown);630 Node alwaysUp = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)631 .add(632 caps,633 new TestSessionFactory((id, c) -> new Session(id, uri, stereotype, c, Instant.now())))634 .advanced()635 .healthCheck(() -> new HealthCheck.Result(UP, "Yay!"))636 .build();637 handler.addHandler(alwaysUp);638 LocalDistributor distributor = new LocalDistributor(639 tracer,640 bus,641 new PassthroughHttpClient.Factory(handler),642 sessions,643 queuer,644 registrationSecret,645 Duration.ofMinutes(5));646 handler.addHandler(distributor);647 distributor.add(alwaysDown);648 // Should be unable to create a session because the node is down.649 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {650 Either<SessionNotCreatedException, CreateSessionResponse> result =651 distributor.newSession(createRequest(payload));652 assertThatEither(result).isLeft();653 }654 distributor.add(alwaysUp);655 waitToHaveCapacity(distributor);656 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {657 Either<SessionNotCreatedException, CreateSessionResponse> result =658 distributor.newSession(createRequest(payload));659 assertThatEither(result).isRight();660 }661 }662 @Test663 public void shouldNotScheduleAJobIfAllSlotsAreBeingUsed() {664 SessionMap sessions = new LocalSessionMap(tracer, bus);665 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(666 tracer,667 bus,668 Duration.ofSeconds(2),669 Duration.ofSeconds(2));670 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(671 tracer,672 bus,673 localNewSessionQueue,674 registrationSecret);675 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)676 .add(caps, new TestSessionFactory((id, c) -> new Session(677 id, nodeUri, stereotype, c, Instant.now())))678 .build();679 Distributor distributor = new LocalDistributor(680 tracer,681 bus,682 new PassthroughHttpClient.Factory(node),683 sessions,684 queuer,685 registrationSecret,686 Duration.ofMinutes(5));687 distributor.add(node);688 waitToHaveCapacity(distributor);689 // Use up the one slot available690 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {691 Either<SessionNotCreatedException, CreateSessionResponse> result =692 distributor.newSession(createRequest(payload));693 assertThatEither(result).isRight();694 }695 // Now try and create a session.696 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {697 Either<SessionNotCreatedException, CreateSessionResponse> result =698 distributor.newSession(createRequest(payload));699 assertThatEither(result).isLeft();700 }701 }702 @Test703 public void shouldReleaseSlotOnceSessionEnds() {704 SessionMap sessions = new LocalSessionMap(tracer, bus);705 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(706 tracer,707 bus,708 Duration.ofSeconds(2),709 Duration.ofSeconds(2));710 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(711 tracer,712 bus,713 localNewSessionQueue,714 registrationSecret);715 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)716 .add(caps, new TestSessionFactory((id, c) -> new Session(717 id, nodeUri, stereotype, c, Instant.now())))718 .build();719 Distributor distributor = new LocalDistributor(720 tracer,721 bus,722 new PassthroughHttpClient.Factory(node),723 sessions,724 queuer,725 registrationSecret,726 Duration.ofMinutes(5));727 distributor.add(node);728 waitToHaveCapacity(distributor);729 // Use up the one slot available730 Session session;731 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {732 Either<SessionNotCreatedException, CreateSessionResponse> result =733 distributor.newSession(createRequest(payload));734 assertThatEither(result).isRight();735 session = result.right().getSession();736 // Make sure the session map has the session737 sessions.get(session.getId());738 node.stop(session.getId());739 // Now wait for the session map to say the session is gone.740 wait.until(obj -> {741 try {742 sessions.get(session.getId());743 return false;744 } catch (NoSuchSessionException e) {745 return true;746 }747 });748 }749 waitToHaveCapacity(distributor);750 // And we should now be able to create another session.751 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {752 Either<SessionNotCreatedException, CreateSessionResponse> result =753 distributor.newSession(createRequest(payload));754 assertThatEither(result).isRight();755 }756 }757 @Test758 public void shouldNotStartASessionIfTheCapabilitiesAreNotSupported() {759 CombinedHandler handler = new CombinedHandler();760 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);761 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(762 tracer,763 bus,764 Duration.ofSeconds(2),765 Duration.ofSeconds(2));766 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(767 tracer,768 bus,769 localNewSessionQueue,770 registrationSecret);771 handler.addHandler(handler);772 Distributor distributor = new LocalDistributor(773 tracer,774 bus,775 new PassthroughHttpClient.Factory(handler),776 sessions,777 queuer,778 registrationSecret,779 Duration.ofMinutes(5));780 handler.addHandler(distributor);781 Node node = createNode(caps, 1, 0);782 handler.addHandler(node);783 distributor.add(node);784 waitToHaveCapacity(distributor);785 ImmutableCapabilities unmatched =786 new ImmutableCapabilities("browserName", "transit of venus");787 try (NewSessionPayload payload = NewSessionPayload.create(unmatched)) {788 Either<SessionNotCreatedException, CreateSessionResponse> result =789 distributor.newSession(createRequest(payload));790 assertThatEither(result).isLeft();791 }792 }793 @Test794 public void attemptingToStartASessionWhichFailsMarksAsTheSlotAsAvailable() {795 SessionMap sessions = new LocalSessionMap(tracer, bus);796 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(797 tracer,798 bus,799 Duration.ofSeconds(2),800 Duration.ofSeconds(2));801 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(802 tracer,803 bus,804 localNewSessionQueue,805 registrationSecret);806 LocalNode node = LocalNode.builder(tracer, bus, routableUri, routableUri, registrationSecret)807 .add(caps, new TestSessionFactory((id, caps) -> {808 throw new SessionNotCreatedException("OMG");809 }))810 .build();811 Distributor distributor = new LocalDistributor(812 tracer,813 bus,814 new PassthroughHttpClient.Factory(node),815 sessions,816 queuer,817 registrationSecret,818 Duration.ofMinutes(5));819 distributor.add(node);820 waitToHaveCapacity(distributor);821 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {822 Either<SessionNotCreatedException, CreateSessionResponse> result =823 distributor.newSession(createRequest(payload));824 assertThatEither(result).isLeft();825 }826 assertThat(distributor.getStatus().hasCapacity()).isTrue();827 }828 @Test829 public void shouldReturnNodesThatWereDownToPoolOfNodesOnceTheyMarkTheirHealthCheckPasses() {830 CombinedHandler handler = new CombinedHandler();831 SessionMap sessions = new LocalSessionMap(tracer, bus);832 handler.addHandler(sessions);833 AtomicReference<Availability> isUp = new AtomicReference<>(DOWN);834 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(835 tracer,836 bus,837 Duration.ofSeconds(2),838 Duration.ofSeconds(2));839 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(840 tracer,841 bus,842 localNewSessionQueue,843 registrationSecret);844 URI uri = createUri();845 Node node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)846 .add(847 caps,848 new TestSessionFactory((id, caps) -> new Session(id, uri, stereotype, caps, Instant.now())))849 .advanced()850 .healthCheck(() -> new HealthCheck.Result(isUp.get(), "TL;DR"))851 .build();852 handler.addHandler(node);853 LocalDistributor distributor = new LocalDistributor(854 tracer,855 bus,856 new PassthroughHttpClient.Factory(handler),857 sessions,858 queuer,859 registrationSecret,860 Duration.ofMinutes(5));861 handler.addHandler(distributor);862 distributor.add(node);863 // Should be unable to create a session because the node is down.864 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {865 Either<SessionNotCreatedException, CreateSessionResponse> result =866 distributor.newSession(createRequest(payload));867 assertThatEither(result).isLeft();868 }869 // Mark the node as being up870 isUp.set(UP);871 // Kick the machinery to ensure that everything is fine.872 distributor.refresh();873 // Because the node is now up and running, we should now be able to create a session874 try (NewSessionPayload payload = NewSessionPayload.create(caps)) {875 Either<SessionNotCreatedException, CreateSessionResponse> result =876 distributor.newSession(createRequest(payload));877 assertThatEither(result).isRight();878 }879 }880 private Set<Node> createNodeSet(Distributor distributor, int count, Capabilities...capabilities) {881 Set<Node> nodeSet = new HashSet<>();882 for (int i=0; i<count; i++) {883 URI uri = createUri();884 LocalNode.Builder builder = LocalNode.builder(tracer, bus, uri, uri, registrationSecret);885 for (Capabilities caps: capabilities) {886 builder.add(887 caps,888 new TestSessionFactory((id, hostCaps) -> new HandledSession(uri, hostCaps)));889 }890 Node node = builder.build();891 distributor.add(node);892 nodeSet.add(node);893 }894 return nodeSet;895 }896 @Test897 public void shouldPrioritizeHostsWithTheMostSlotsAvailableForASessionType() {898 // Consider the case where you have 1 Windows machine and 5 linux machines. All of these hosts899 // can run Chrome and Firefox sessions, but only one can run Edge sessions. Ideally, the machine900 // able to run Edge would be sorted last.901 //Create the Distributor902 CombinedHandler handler = new CombinedHandler();903 SessionMap sessions = new LocalSessionMap(tracer, bus);904 handler.addHandler(sessions);905 LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue(906 tracer,907 bus,908 Duration.ofSeconds(2),909 Duration.ofSeconds(2));910 LocalNewSessionQueuer queuer = new LocalNewSessionQueuer(911 tracer,912 bus,913 localNewSessionQueue,914 registrationSecret);915 LocalDistributor distributor = new LocalDistributor(916 tracer,917 bus,918 new PassthroughHttpClient.Factory(handler),919 sessions,920 queuer,921 registrationSecret,922 Duration.ofMinutes(5));923 handler.addHandler(distributor);924 //Create all three Capability types925 Capabilities edge = new ImmutableCapabilities("browserName", "edge");926 Capabilities firefox = new ImmutableCapabilities("browserName", "firefox");927 Capabilities chrome = new ImmutableCapabilities("browserName", "chrome");928 //Store our "expected results" sets for the various browser-specific nodes929 Set<Node> edgeNodes = createNodeSet(distributor, 3, edge, chrome, firefox);930 //chromeNodes is all these new nodes PLUS all the Edge nodes from before931 Set<Node> chromeNodes = createNodeSet(distributor,5, chrome, firefox);932 chromeNodes.addAll(edgeNodes);933 //all nodes support firefox, so add them to the firefoxNodes set934 Set<Node> firefoxNodes = createNodeSet(distributor,3, firefox);935 firefoxNodes.addAll(edgeNodes);936 firefoxNodes.addAll(chromeNodes);937 waitForAllNodesToHaveCapacity(distributor, 11);938 //Assign 5 Chrome and 5 Firefox sessions to the distributor, make sure they don't go to the Edge node939 for (int i=0; i<5; i++) {940 try (NewSessionPayload chromePayload = NewSessionPayload.create(chrome);941 NewSessionPayload firefoxPayload = NewSessionPayload.create(firefox)) {942 Either<SessionNotCreatedException, CreateSessionResponse> chromeResult =943 distributor.newSession(createRequest(chromePayload));944 assertThatEither(chromeResult).isRight();945 Session chromeSession = chromeResult.right().getSession();946 //Ensure the Uri of the Session matches one of the Chrome Nodes, not the Edge Node947 assertThat(948 chromeSession.getUri()).isIn(949 chromeNodes950 .stream().map(Node::getStatus).collect(Collectors.toList()) //List of getStatus() from the Set951 .stream().map(NodeStatus::getUri).collect(Collectors.toList()) //List of getUri() from the Set952 );953 Either<SessionNotCreatedException, CreateSessionResponse> firefoxResult =954 distributor.newSession(createRequest(firefoxPayload));955 assertThatEither(firefoxResult).isRight();956 Session firefoxSession = firefoxResult.right().getSession();957 LOG.info(String.format("Firefox Session %d assigned to %s", i, chromeSession.getUri()));958 boolean inFirefoxNodes = firefoxNodes.stream().anyMatch(node -> node.getUri().equals(firefoxSession.getUri()));959 boolean inChromeNodes = chromeNodes.stream().anyMatch(node -> node.getUri().equals(chromeSession.getUri()));960 //This could be either, or, or both961 assertTrue(inFirefoxNodes || inChromeNodes);962 }963 }964 //The Chrome Nodes should be full at this point, but Firefox isn't... so send an Edge session and make sure it routes to an Edge node965 try (NewSessionPayload edgePayload = NewSessionPayload.create(edge)) {966 Either<SessionNotCreatedException, CreateSessionResponse> edgeResult =967 distributor.newSession(createRequest(edgePayload));968 assertThatEither(edgeResult).isRight();969 Session edgeSession = edgeResult.right().getSession();970 assertTrue(edgeNodes.stream().anyMatch(node -> node.getUri().equals(edgeSession.getUri())));971 }972 }973 private Node createNode(Capabilities stereotype, int count, int currentLoad) {974 URI uri = createUri();975 LocalNode.Builder builder = LocalNode.builder(tracer, bus, uri, uri, registrationSecret);976 for (int i = 0; i < count; i++) {977 builder.add(stereotype, new TestSessionFactory((id, caps) -> new HandledSession(uri, caps)));978 }979 LocalNode node = builder.build();980 for (int i = 0; i < currentLoad; i++) {981 // Ignore the session. We're just creating load.982 node.newSession(new CreateSessionRequest(983 ImmutableSet.copyOf(Dialect.values()),984 stereotype,985 ImmutableMap.of()));986 }987 return node;988 }989 @Test990 @Ignore991 public void shouldCorrectlySetSessionCountsWhenStartedAfterNodeWithSession() {992 fail("write me!");993 }994 @Test995 public void statusShouldIndicateThatDistributorIsNotAvailableIfNodesAreDown()996 throws URISyntaxException {997 Capabilities capabilities = new ImmutableCapabilities("cheese", "peas");998 URI uri = new URI("http://example.com");999 Node node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)1000 .add(1001 capabilities,1002 new TestSessionFactory((id, caps) -> new Session(id, uri, stereotype, caps, Instant.now())))1003 .advanced()1004 .healthCheck(() -> new HealthCheck.Result(DOWN, "TL;DR"))1005 .build();1006 local.add(node);1007 DistributorStatus status = local.getStatus();1008 assertFalse(status.hasCapacity());1009 }1010 @Test1011 public void disabledNodeShouldNotAcceptNewRequests()1012 throws URISyntaxException1013 {1014 Capabilities capabilities = new ImmutableCapabilities("cheese", "peas");1015 URI uri = new URI("http://example.com");1016 Node node = LocalNode.builder(tracer, bus, uri, uri, registrationSecret)1017 .add(1018 capabilities,1019 new TestSessionFactory((id, caps) -> new Session(id, uri, stereotype, caps, Instant.now())))1020 .advanced()1021 .healthCheck(() -> new HealthCheck.Result(DOWN, "TL;DR"))1022 .build();1023 local.add(node);1024 DistributorStatus status = local.getStatus();1025 assertFalse(status.hasCapacity());1026 }1027 private HttpRequest createRequest(NewSessionPayload payload) {1028 StringBuilder builder = new StringBuilder();1029 try {1030 payload.writeTo(builder);1031 } catch (IOException e) {1032 throw new UncheckedIOException(e);1033 }1034 HttpRequest request = new HttpRequest(POST, "/se/grid/distributor/session");1035 request.setContent(utf8String(builder.toString()));1036 return request;1037 }1038 private URI createUri() {1039 try {1040 return new URI("http://localhost:" + PortProber.findFreePort());1041 } catch (URISyntaxException e) {1042 throw new RuntimeException(e);1043 }1044 }1045 private void waitToHaveCapacity(Distributor distributor) {1046 new FluentWait<>(distributor)1047 .withTimeout(Duration.ofSeconds(5))1048 .pollingEvery(Duration.ofMillis(100))1049 .until(d -> d.getStatus().hasCapacity());1050 }1051 private void waitForAllNodesToHaveCapacity(Distributor distributor, int nodeCount) {1052 try {1053 new FluentWait<>(distributor)1054 .withTimeout(Duration.ofSeconds(5))1055 .pollingEvery(Duration.ofMillis(100))1056 .until(d -> {1057 Set<NodeStatus> nodes = d.getStatus().getNodes();1058 return nodes.size() == nodeCount && nodes.stream().allMatch(1059 node -> node.getAvailability() == UP && node.hasCapacity());1060 });1061 } catch (TimeoutException ex) {1062 Set<NodeStatus> nodes = distributor.getStatus().getNodes();1063 System.out.println("*************");1064 System.out.println("" + nodes.size());1065 nodes.forEach(node -> System.out.println("" + node.hasCapacity()));1066 }1067 }1068 class HandledSession extends Session implements HttpHandler {1069 HandledSession(URI uri, Capabilities caps) {1070 super(new SessionId(UUID.randomUUID()), uri, stereotype, caps, Instant.now());1071 }1072 @Override1073 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {1074 // no-op1075 return new HttpResponse();1076 }1077 }1078}...

Full Screen

Full Screen

Source:LocalNewSessionQueueTest.java Github

copy

Full Screen

...176 "value", ImmutableMap.of(177 "sessionId", sessionId,178 "capabilities", capabilities)))179 .getBytes(UTF_8));180 queue.complete(reqId, Either.right(sessionResponse));181 }));182 HttpResponse httpResponse = queue.addToQueue(sessionRequest);183 assertThat(isPresent.get()).isTrue();184 assertEquals(httpResponse.getStatus(), HTTP_OK);185 }186 @Test187 public void shouldBeAbleToAddToQueueAndGetErrorResponse() {188 bus.addListener(NewSessionRequestEvent.listener(reqId ->189 queue.complete(reqId, Either.left(new SessionNotCreatedException("Error")))));190 HttpResponse httpResponse = queue.addToQueue(sessionRequest);191 assertEquals(httpResponse.getStatus(), HTTP_INTERNAL_ERROR);192 }193 @Test194 public void shouldBeAbleToRemoveFromQueue() {195 Optional<SessionRequest> httpRequest = queue.remove(new RequestId(UUID.randomUUID()));196 assertFalse(httpRequest.isPresent());197 }198 @Test199 public void shouldBeClearQueue() {200 RequestId requestId = new RequestId(UUID.randomUUID());201 localQueue.injectIntoQueue(sessionRequest);202 int count = queue.clearQueue();203 assertEquals(count, 1);204 assertFalse(queue.remove(requestId).isPresent());205 }206 @Test207 public void shouldBeAbleToGetQueueContents() {208 localQueue.injectIntoQueue(sessionRequest);209 List<Set<Capabilities>> response = queue.getQueueContents()210 .stream()211 .map(SessionRequestCapability::getDesiredCapabilities)212 .collect(Collectors.toList());213 assertThat(response).hasSize(1);214 assertEquals(Set.of(CAPS), response.get(0));215 }216 @Test217 public void shouldBeClearQueueAndFireRejectedEvent() throws InterruptedException {218 AtomicBoolean result = new AtomicBoolean(false);219 RequestId requestId = sessionRequest.getRequestId();220 CountDownLatch latch = new CountDownLatch(1);221 bus.addListener(222 NewSessionRejectedEvent.listener(223 response -> {224 result.set(response.getRequestId().equals(requestId));225 latch.countDown();226 }));227 localQueue.injectIntoQueue(sessionRequest);228 queue.remove(requestId);229 queue.retryAddToQueue(sessionRequest);230 int count = queue.clearQueue();231 assertThat(latch.await(2, SECONDS)).isTrue();232 assertThat(result.get()).isTrue();233 assertEquals(count, 1);234 assertFalse(queue.remove(requestId).isPresent());235 }236 @Test237 public void removingARequestIdThatDoesNotExistInTheQueueShouldNotBeAnError() {238 localQueue.injectIntoQueue(sessionRequest);239 Optional<SessionRequest> httpRequest = queue.remove(new RequestId(UUID.randomUUID()));240 assertFalse(httpRequest.isPresent());241 }242 @Test243 public void shouldBeAbleToAddAgainToQueue() {244 localQueue.injectIntoQueue(sessionRequest);245 Optional<SessionRequest> removed = queue.remove(sessionRequest.getRequestId());246 assertThat(removed).isPresent();247 boolean added = queue.retryAddToQueue(sessionRequest);248 assertTrue(added);249 }250 @Test251 public void shouldBeAbleToRetryRequest() {252 AtomicBoolean isPresent = new AtomicBoolean(false);253 AtomicBoolean retrySuccess = new AtomicBoolean(false);254 AtomicInteger count = new AtomicInteger(0);255 bus.addListener(256 NewSessionRequestEvent.listener(257 reqId -> {258 // Keep a count of event fired259 count.incrementAndGet();260 Optional<SessionRequest> sessionRequest = this.queue.remove(reqId);261 isPresent.set(sessionRequest.isPresent());262 if (count.get() == 1) {263 retrySuccess.set(queue.retryAddToQueue(sessionRequest.get()));264 }265 // Only if it was retried after an interval, the count is 2266 if (count.get() == 2) {267 ImmutableCapabilities capabilities =268 new ImmutableCapabilities("browserName", "edam");269 try {270 SessionId sessionId = new SessionId("123");271 Session session =272 new Session(273 sessionId,274 new URI("http://example.com"),275 CAPS,276 capabilities,277 Instant.now());278 CreateSessionResponse sessionResponse =279 new CreateSessionResponse(280 session,281 JSON.toJson(282 ImmutableMap.of(283 "value",284 ImmutableMap.of(285 "sessionId", sessionId,286 "capabilities", capabilities)))287 .getBytes(UTF_8));288 queue.complete(reqId, Either.right(sessionResponse));289 } catch (URISyntaxException e) {290 throw new RuntimeException(e);291 }292 }293 }));294 HttpResponse httpResponse = queue.addToQueue(sessionRequest);295 assertThat(isPresent.get()).isTrue();296 assertThat(retrySuccess.get()).isTrue();297 assertEquals(httpResponse.getStatus(), HTTP_OK);298 }299 @Test(timeout = 5000)300 public void shouldBeAbleToHandleMultipleSessionRequestsAtTheSameTime() {301 bus.addListener(NewSessionRequestEvent.listener(reqId -> {302 queue.remove(reqId);303 ImmutableCapabilities capabilities = new ImmutableCapabilities("browserName", "chrome");304 try {305 SessionId sessionId = new SessionId(UUID.randomUUID());306 Session session =307 new Session(308 sessionId,309 new URI("http://example.com"),310 CAPS,311 capabilities,312 Instant.now());313 CreateSessionResponse sessionResponse = new CreateSessionResponse(314 session,315 JSON.toJson(316 ImmutableMap.of(317 "value", ImmutableMap.of(318 "sessionId", sessionId,319 "capabilities", capabilities)))320 .getBytes(UTF_8));321 queue.complete(reqId, Either.right(sessionResponse));322 } catch (URISyntaxException e) {323 queue.complete(reqId, Either.left(new SessionNotCreatedException(e.getMessage())));324 }325 }));326 ExecutorService executor = Executors.newFixedThreadPool(2);327 Callable<HttpResponse> callable = () -> {328 SessionRequest sessionRequest = new SessionRequest(329 new RequestId(UUID.randomUUID()),330 Instant.now(),331 Set.of(W3C),332 Set.of(CAPS),333 Map.of(),334 Map.of());335 return queue.addToQueue(sessionRequest);336 };337 Future<HttpResponse> firstRequest = executor.submit(callable);...

Full Screen

Full Screen

Source:LocalDistributorTest.java Github

copy

Full Screen

...380 throw new RuntimeException(e);381 }382 });383 // If the sessions are created serially, then we expect the first384 // session to take up to `delay` ms to complete, followed by the385 // second session.386 assertThat(System.currentTimeMillis() - start).isLessThan(delay * 2);387 }388 private class Handler extends Session implements HttpHandler {389 private Handler(Capabilities capabilities) {390 super(new SessionId(UUID.randomUUID()), uri, new ImmutableCapabilities(), capabilities, Instant.now());391 }392 @Override393 public HttpResponse execute(HttpRequest req) throws UncheckedIOException {394 return new HttpResponse();395 }396 }397}...

Full Screen

Full Screen

Source:LocalNewSessionQueue.java Github

copy

Full Screen

...58 * <p>59 * The lifecycle of a request can be described as:60 * <ol>61 * <li>User adds an item on to the queue using {@link #addToQueue(SessionRequest)}. This62 * will block until the request completes in some way.63 * <li>After being added, a {@link NewSessionRequestEvent} is fired. Listeners should use64 * this as an indication to call {@link #remove(RequestId)} to get the session request.65 * <li>If the session request is completed, then {@link #complete(RequestId, Either)} must66 * be called. This will not only ensure that {@link #addToQueue(SessionRequest)}67 * returns, but will also fire a {@link NewSessionRejectedEvent} if the session was68 * rejected. Positive completions of events are assumed to be notified on the event bus69 * by other listeners.70 * <li>If the request cannot be handled right now, call71 * {@link #retryAddToQueue(SessionRequest)} to return the session request to the front72 * of the queue.73 * </ol>74 * <p>75 * There is a background thread that will reap {@link SessionRequest}s that have timed out.76 * This means that a request can either complete by a listener calling77 * {@link #complete(RequestId, Either)} directly, or by being reaped by the thread.78 */79@ManagedService(objectName = "org.seleniumhq.grid:type=SessionQueue,name=LocalSessionQueue",80 description = "New session queue")81public class LocalNewSessionQueue extends NewSessionQueue implements Closeable {82 private final EventBus bus;83 private final SlotMatcher slotMatcher;84 private final Duration requestTimeout;85 private final Map<RequestId, Data> requests;86 private final Map<RequestId, TraceContext> contexts;87 private final Deque<SessionRequest> queue;88 private final ReadWriteLock lock = new ReentrantReadWriteLock();89 private final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(r -> {90 Thread thread = new Thread(r);91 thread.setDaemon(true);92 thread.setName("Local New Session Queue");93 return thread;94 });95 public LocalNewSessionQueue(96 Tracer tracer,97 EventBus bus,98 SlotMatcher slotMatcher,99 Duration retryPeriod,100 Duration requestTimeout,101 Secret registrationSecret) {102 super(tracer, registrationSecret);103 this.slotMatcher = Require.nonNull("Slot matcher", slotMatcher);104 this.bus = Require.nonNull("Event bus", bus);105 Require.nonNull("Retry period", retryPeriod);106 if (retryPeriod.isNegative() || retryPeriod.isZero()) {107 throw new IllegalArgumentException("Retry period must be positive");108 }109 this.requestTimeout = Require.nonNull("Request timeout", requestTimeout);110 if (requestTimeout.isNegative() || requestTimeout.isZero()) {111 throw new IllegalArgumentException("Request timeout must be positive");112 }113 this.requests = new ConcurrentHashMap<>();114 this.queue = new ConcurrentLinkedDeque<>();115 this.contexts = new ConcurrentHashMap<>();116 service.scheduleAtFixedRate(this::timeoutSessions, retryPeriod.toMillis(), retryPeriod.toMillis(), MILLISECONDS);117 new JMXHelper().register(this);118 }119 public static NewSessionQueue create(Config config) {120 LoggingOptions loggingOptions = new LoggingOptions(config);121 Tracer tracer = loggingOptions.getTracer();122 EventBusOptions eventBusOptions = new EventBusOptions(config);123 SessionRequestOptions requestOptions = new SessionRequestOptions(config);124 SecretOptions secretOptions = new SecretOptions(config);125 SlotMatcher slotMatcher = new DistributorOptions(config).getSlotMatcher();126 return new LocalNewSessionQueue(127 tracer,128 eventBusOptions.getEventBus(),129 slotMatcher,130 requestOptions.getSessionRequestRetryInterval(),131 requestOptions.getSessionRequestTimeout(),132 secretOptions.getRegistrationSecret());133 }134 private void timeoutSessions() {135 Instant now = Instant.now();136 Lock readLock = lock.readLock();137 readLock.lock();138 Set<RequestId> ids;139 try {140 ids = requests.entrySet().stream()141 .filter(entry -> isTimedOut(now, entry.getValue()))142 .map(Map.Entry::getKey)143 .collect(Collectors.toSet());144 } finally {145 readLock.unlock();146 }147 Lock writeLock = lock.writeLock();148 try {149 for (RequestId id : ids) {150 failDueToTimeout(id);151 }152 } finally {153 writeLock.unlock();154 }155 }156 private boolean isTimedOut(Instant now, Data data) {157 return data.endTime.isBefore(now);158 }159 @Override160 public HttpResponse addToQueue(SessionRequest request) {161 Require.nonNull("New session request", request);162 Require.nonNull("Request id", request.getRequestId());163 TraceContext context = TraceSessionRequest.extract(tracer, request);164 try (Span span = context.createSpan("sessionqueue.add_to_queue")) {165 contexts.put(request.getRequestId(), context);166 Data data = injectIntoQueue(request);167 if (isTimedOut(Instant.now(), data)) {168 failDueToTimeout(request.getRequestId());169 }170 Either<SessionNotCreatedException, CreateSessionResponse> result;171 try {172 if (data.latch.await(requestTimeout.toMillis(), MILLISECONDS)) {173 result = data.result;174 } else {175 result = Either.left(new SessionNotCreatedException("New session request timed out"));176 }177 } catch (InterruptedException e) {178 Thread.currentThread().interrupt();179 result = Either.left(new SessionNotCreatedException("Interrupted when creating the session", e));180 } catch (RuntimeException e) {181 result = Either.left(new SessionNotCreatedException("An error occurred creating the session", e));182 }183 Lock writeLock = this.lock.writeLock();184 writeLock.lock();185 try {186 requests.remove(request.getRequestId());187 queue.remove(request);188 } finally {189 writeLock.unlock();190 }191 HttpResponse res = new HttpResponse();192 if (result.isRight()) {193 res.setContent(Contents.bytes(result.right().getDownstreamEncodedResponse()));194 } else {195 res.setStatus(HTTP_INTERNAL_ERROR)196 .setContent(Contents.asJson(Collections.singletonMap("value", result.left())));197 }198 return res;199 }200 }201 @VisibleForTesting202 Data injectIntoQueue(SessionRequest request) {203 Require.nonNull("Session request", request);204 Data data = new Data(request.getEnqueued());205 Lock writeLock = lock.writeLock();206 writeLock.lock();207 try {208 requests.put(request.getRequestId(), data);209 queue.addLast(request);210 } finally {211 writeLock.unlock();212 }213 bus.fire(new NewSessionRequestEvent(request.getRequestId()));214 return data;215 }216 @Override217 public boolean retryAddToQueue(SessionRequest request) {218 Require.nonNull("New session request", request);219 boolean added;220 TraceContext context = contexts.getOrDefault(request.getRequestId(), tracer.getCurrentContext());221 try (Span span = context.createSpan("sessionqueue.retry")) {222 Lock writeLock = lock.writeLock();223 writeLock.lock();224 try {225 if (!requests.containsKey(request.getRequestId())) {226 return false;227 }228 if (queue.contains(request)) {229 // No need to re-add this230 return true;231 } else {232 added = queue.offerFirst(request);233 }234 } finally {235 writeLock.unlock();236 }237 if (added) {238 bus.fire(new NewSessionRequestEvent(request.getRequestId()));239 }240 return added;241 }242 }243 @Override244 public Optional<SessionRequest> remove(RequestId reqId) {245 Require.nonNull("Request ID", reqId);246 Lock writeLock = lock.writeLock();247 writeLock.lock();248 try {249 Iterator<SessionRequest> iterator = queue.iterator();250 while (iterator.hasNext()) {251 SessionRequest req = iterator.next();252 if (reqId.equals(req.getRequestId())) {253 iterator.remove();254 return Optional.of(req);255 }256 }257 return Optional.empty();258 } finally {259 writeLock.unlock();260 }261 }262 @Override263 public Optional<SessionRequest> getNextAvailable(Set<Capabilities> stereotypes) {264 Require.nonNull("Stereotypes", stereotypes);265 Predicate<Capabilities> matchesStereotype =266 caps -> stereotypes.stream().anyMatch(stereotype -> slotMatcher.matches(stereotype, caps));267 Lock writeLock = lock.writeLock();268 writeLock.lock();269 try {270 Optional<SessionRequest> maybeRequest =271 queue.stream()272 .filter(req -> req.getDesiredCapabilities().stream().anyMatch(matchesStereotype))273 .findFirst();274 maybeRequest.ifPresent(req -> {275 this.remove(req.getRequestId());276 });277 return maybeRequest;278 } finally {279 writeLock.unlock();280 }281 }282 @Override283 public void complete(RequestId reqId, Either<SessionNotCreatedException, CreateSessionResponse> result) {284 Require.nonNull("New session request", reqId);285 Require.nonNull("Result", result);286 TraceContext context = contexts.getOrDefault(reqId, tracer.getCurrentContext());287 try (Span span = context.createSpan("sessionqueue.completed")) {288 Lock readLock = lock.readLock();289 readLock.lock();290 Data data;291 try {292 data = requests.get(reqId);293 } finally {294 readLock.unlock();295 }296 if (data == null) {297 return;298 }299 Lock writeLock = lock.writeLock();300 writeLock.lock();301 try {302 requests.remove(reqId);303 queue.removeIf(req -> reqId.equals(req.getRequestId()));304 contexts.remove(reqId);305 } finally {306 writeLock.unlock();307 }308 if (result.isLeft()) {309 bus.fire(new NewSessionRejectedEvent(new NewSessionErrorResponse(reqId, result.left().getMessage())));310 }311 data.setResult(result);312 }313 }314 @Override315 public int clearQueue() {316 Lock writeLock = lock.writeLock();317 writeLock.lock();318 try {319 int size = queue.size();320 queue.clear();321 requests.forEach((reqId, data) -> {322 data.setResult(Either.left(new SessionNotCreatedException("Request queue was cleared")));323 bus.fire(new NewSessionRejectedEvent(324 new NewSessionErrorResponse(reqId, "New session queue was forcibly cleared")));325 });326 requests.clear();327 return size;328 } finally {329 writeLock.unlock();330 }331 }332 @Override333 public List<SessionRequestCapability> getQueueContents() {334 Lock readLock = lock.readLock();335 readLock.lock();336 try {337 return queue.stream()338 .map(req ->339 new SessionRequestCapability(req.getRequestId(), req.getDesiredCapabilities()))340 .collect(Collectors.toList());341 } finally {342 readLock.unlock();343 }344 }345 @ManagedAttribute(name = "NewSessionQueueSize")346 public int getQueueSize() {347 return queue.size();348 }349 @Override350 public boolean isReady() {351 return true;352 }353 @Override354 public void close() throws IOException {355 service.shutdownNow();356 }357 private void failDueToTimeout(RequestId reqId) {358 complete(reqId, Either.left(new SessionNotCreatedException("Timed out creating session")));359 }360 private class Data {361 public final Instant endTime;362 public Either<SessionNotCreatedException, CreateSessionResponse> result;363 private boolean complete;364 private CountDownLatch latch = new CountDownLatch(1);365 public Data(Instant enqueued) {366 this.endTime = enqueued.plus(requestTimeout);367 this.result = Either.left(new SessionNotCreatedException("Session not created"));368 }369 public synchronized void setResult(Either<SessionNotCreatedException, CreateSessionResponse> result) {370 if (complete) {371 return;372 }373 this.result = result;374 complete = true;375 latch.countDown();376 }377 }378}...

Full Screen

Full Screen

complete

Using AI Code Generation

copy

Full Screen

1package org.openqa.selenium.grid.sessionqueue.local;2import org.openqa.selenium.grid.config.Config;3import org.openqa.selenium.grid.data.Session;4import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;5import org.openqa.selenium.internal.Require;6import org.openqa.selenium.remote.tracing.Tracer;7import java.net.URI;8import java.util.Objects;9import java.util.Optional;10import java.util.concurrent.ConcurrentLinkedQueue;11import java.util.concurrent.atomic.AtomicInteger;12public class LocalNewSessionQueue implements NewSessionQueue {13 private final Tracer tracer;14 private final ConcurrentLinkedQueue<Session> queue;15 private final AtomicInteger size;16 public LocalNewSessionQueue(Tracer tracer, int size) {17 this.tracer = Require.nonNull("Tracer", tracer);18 this.size = new AtomicInteger(size);19 this.queue = new ConcurrentLinkedQueue<>();20 }21 public static NewSessionQueue create(Config config) {22 return new LocalNewSessionQueue(23 config.getTracer(),24 config.getInt("queue-size").orElse(10));25 }26 public void add(Session session) {27 Require.nonNull("Session", session);28 if (size.decrementAndGet() >= 0) {29 queue.add(session);30 } else {31 size.incrementAndGet();32 }33 }34 public Optional<Session> remove(URI uri) {35 Require.nonNull("URI", uri);36 return Optional.ofNullable(queue.poll());37 }38 public void complete(URI uri) {39 Require.nonNull("URI", uri);40 size.incrementAndGet();41 }42 public boolean equals(Object o) {43 if (!(o instanceof LocalNewSessionQueue)) {44 return false;45 }46 LocalNewSessionQueue that = (LocalNewSessionQueue) o;47 return Objects.equals(this.tracer, that.tracer) &&48 Objects.equals(this.size, that.size) &&49 Objects.equals(this.queue, that.queue);50 }51 public int hashCode() {52 return Objects.hash(tracer, queue, size);53 }54}55package org.openqa.selenium.grid.sessionqueue.local;56import org.openqa.selenium.grid.config.Config;57import org.openqa.selenium.grid.data.Session;58import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;59import org.openqa.selenium.internal.Require;60import org.openqa.selenium.remote.tracing.Tracer;61import java

Full Screen

Full Screen

complete

Using AI Code Generation

copy

Full Screen

1import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;2import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;3import org.openqa.selenium.remote.tracing.Tracer;4import org.openqa.selenium.remote.tracing.DistributedTracer;5public class LocalNewSessionQueueExample {6 public static void main(String[] args) {7 Tracer tracer = new DistributedTracer();8 NewSessionQueue sessionQueue = new LocalNewSessionQueue(tracer);9 sessionQueue.complete(sessionId);10 }11}

Full Screen

Full Screen

complete

Using AI Code Generation

copy

Full Screen

1package com.selenium4beginners.java.webdriver;2import java.net.URI;3import java.net.URISyntaxException;4import java.util.ArrayList;5import java.util.List;6import org.openqa.selenium.Capabilities;7import org.openqa.selenium.ImmutableCapabilities;8import org.openqa.selenium.grid.config.MapConfig;9import org.openqa.selenium.grid.data.Session;10import org.openqa.selenium.grid.data.SessionId;11import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;12import org.openqa.selenium.remote.NewSessionPayload;13import org.openqa.selenium.remote.SessionIdGenerator;14import org.openqa.selenium.remote.SessionIdGenerator.SauceSessionIdGenerator;15import org.openqa.selenium.remote.http.HttpClient;16import org.openqa.selenium.remote.http.HttpMethod;17import org.openqa.selenium.remote.http.HttpResponse;18import org.openqa.selenium.remote.http.HttpResponseCode;19import com.google.common.collect.ImmutableMap;20public class CompleteLocalNewSessionQueue {21 public static void main(String[] args) throws URISyntaxException {22 NewSessionPayload payload = new NewSessionPayload(23 new ImmutableCapabilities("browserName", "chrome"));24 SessionIdGenerator generator = new SauceSessionIdGenerator();25 SessionId id = generator.generateSessionId();26 new ImmutableCapabilities("browserName", "chrome"));27 LocalNewSessionQueue queue = new LocalNewSessionQueue(28 new MapConfig(ImmutableMap.of("session-queue-timeout", "30")));29 queue.add(payload);30 Session nextSession = queue.next();31 int size = queue.size();32 List<Capabilities> capabilities = queue.getCapabilities();33 List<Capabilities> capabilitiesList = queue.getCapabilitiesList();34 String capabilitiesString = queue.getCapabilitiesString();

Full Screen

Full Screen

complete

Using AI Code Generation

copy

Full Screen

1import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;2import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;3import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue.CompleteResponse;4import org.openqa.selenium.internal.Require;5import org.openqa.selenium.remote.http.HttpRequest;6import org.openqa.selenium.remote.http.HttpResponse;7import org.openqa.selenium.remote.tracing.Tracer;8import java.util.Objects;9import java.util.UUID;10import java.util.concurrent.TimeUnit;11public class CompleteResponse extends HttpResponse {12 private final NewSessionQueue queue;13 private final HttpRequest req;14 private final UUID id;15 private final Tracer tracer;16 public CompleteResponse(NewSessionQueue queue, HttpRequest req, UUID id, Tracer tracer) {17 super(200);18 this.queue = Require.nonNull("Queue", queue);19 this.req = Require.nonNull("HTTP request", req);20 this.id = Require.nonNull("Session ID", id);21 this.tracer = Require.nonNull("Tracer", tracer);22 }23 public void writeTo(OutputStream output) throws IOException {24 try (Span span = tracer.getCurrentContext().createSpan("new_session_queue.complete")) {25 span.addTag("session.id", id.toString());26 try {27 queue.complete(id, TimeUnit.SECONDS.toMillis(10));28 } catch (TimeoutException e) {29 span.addTag("error", true);30 span.addTag("message", e.getMessage());31 span.addTag("stacktrace", Throwables.getStackTraceAsString(e));32 }33 }34 }35}36public class LocalNewSessionQueue implements NewSessionQueue {37 public CompleteResponse complete(UUID id, long timeout) {38 Objects.requireNonNull(id, "Session ID to complete must be set.");39 try (Span span = tracer.getCurrentContext().createSpan("new_session_queue.complete")) {40 span.addTag("session.id", id.toString());41 span.addTag("timeout", timeout);42 SessionRequest request = requests.remove(id);43 if (request == null) {44 span.addTag("error", true);45 span.addTag("message", "No such request");46 throw new NoSuchElementException("No such request: " + id);47 }48 request.complete();49 return new CompleteResponse(this, req, id, tracer);50 }51 }52}53public class LocalNewSessionQueue implements NewSessionQueue {54 public static class CompleteResponse extends HttpResponse {55 private final NewSessionQueue queue;56 private final HttpRequest req;

Full Screen

Full Screen

complete

Using AI Code Generation

copy

Full Screen

1import org.openqa.selenium.grid.config.Config;2import org.openqa.selenium.grid.config.MapConfig;3import org.openqa.selenium.grid.data.Session;4import org.openqa.selenium.grid.node.local.LocalNode;5import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;6import org.openqa.selenium.remote.http.HttpClient;7import org.openqa.selenium.remote.tracing.Tracer;8import org.openqa.selenium.remote.tracing.zipkin.ZipkinTracer;9import org.openqa.selenium.remote.tracing.zipkin.ZipkinTracerFactory;10import org.openqa.selenium.remote.tracing.zipkin.ZipkinTracerOptions;11import java.net.URI;12import java.util.concurrent.ExecutionException;13public class LocalNodeTest {14 public static void main(String[] args) throws ExecutionException, InterruptedException {15 Tracer tracer = new ZipkinTracer(new ZipkinTracerFactory(), new ZipkinTracerOptions());16 Config config = new MapConfig();17 LocalNode node = new LocalNode(18 new LocalNewSessionQueue(),19 HttpClient.Factory.createDefault(),20 HttpClient.Factory.createDefault(),21 Session session = node.newSession(null).get();22 node.complete(session.getId());23 }24}252021-02-24 15:59:04.229:INFO:oejs.Server:main: jetty-9.4.33.v20201020; built: 2020-10-20T22:32:19.116Z; git: 6f1b6c8b6d9b6b1e6b7c6e8a0a7f2d2f1d1a1a66; jvm 1.8.0_275-b01

Full Screen

Full Screen

complete

Using AI Code Generation

copy

Full Screen

1package com.selenium.grid;2import java.io.IOException;3import java.net.URI;4import java.net.URISyntaxException;5import java.util.Optional;6import java.util.concurrent.TimeUnit;7import java.util.logging.Level;8import java.util.logging.Logger;9import org.openqa.selenium.Capabilities;10import org.openqa.selenium.ImmutableCapabilities;11import org.openqa.selenium.SessionNotCreatedException;12import org.openqa.selenium.grid.data.NewSessionRequest;13import org.openqa.selenium.grid.data.NewSessionResponse;14import org.openqa.selenium.grid.data.Session;15import org.openqa.selenium.grid.distributor.local.LocalDistributor;16import org.openqa.selenium.grid.node.local.LocalNode;17import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;18import org.openqa.selenium.grid.web.Values;19import org.openqa.selenium.internal.Require;20import org.openqa.selenium.json.Json;21import org.openqa.selenium.remote.http.HttpClient;22import org.openqa.selenium.remote.tracing.DefaultTestTracer;23import org.openqa.selenium.remote.tracing.Tracer;24import com.google.common.collect.ImmutableMap;25public class LocalDistributorSessionQueue {26 private static final Logger LOG = Logger.getLogger(LocalDistributorSessionQueue.class.getName());27 public static void main(String[] args) throws URISyntaxException {28 Tracer tracer = DefaultTestTracer.createTracer();29 HttpClient.Factory clientFactory = HttpClient.Factory.createDefault();30 LocalDistributor distributor = new LocalDistributor(31 new LocalNewSessionQueue(32 TimeUnit.SECONDS));33 LocalNode node = new LocalNode(34 new ImmutableCapabilities("browserName", "chrome"));35 node.start();36 NewSessionRequest request = new NewSessionRequest(37 new ImmutableCapabilities("browserName", "chrome"),38 new ImmutableCapabilities());39 try {40 NewSessionResponse response = distributor.newSession(request);41 Session session = response.getSession();42 System.out.println("Session ID: " + session.getId());43 System.out.println("List of all the sessions waiting in the queue: " + distributor.getNewSessionQueue().complete());44 System.out.println("Session at the top of the

Full Screen

Full Screen

Selenium 4 Tutorial:

LambdaTest’s Selenium 4 tutorial is covering every aspects of Selenium 4 testing with examples and best practices. Here you will learn basics, such as how to upgrade from Selenium 3 to Selenium 4, to some advanced concepts, such as Relative locators and Selenium Grid 4 for Distributed testing. Also will learn new features of Selenium 4, such as capturing screenshots of specific elements, opening a new tab or window on the browser, and new protocol adoptions.

Chapters:

  1. Upgrading From Selenium 3 To Selenium 4?: In this chapter, learn in detail how to update Selenium 3 to Selenium 4 for Java binding. Also, learn how to upgrade while using different build tools such as Maven or Gradle and get comprehensive guidance for upgrading Selenium.

  2. What’s New In Selenium 4 & What’s Being Deprecated? : Get all information about new implementations in Selenium 4, such as W3S protocol adaption, Optimized Selenium Grid, and Enhanced Selenium IDE. Also, learn what is deprecated for Selenium 4, such as DesiredCapabilites and FindsBy methods, etc.

  3. Selenium 4 With Python: Selenium supports all major languages, such as Python, C#, Ruby, and JavaScript. In this chapter, learn how to install Selenium 4 for Python and the features of Python in Selenium 4, such as Relative locators, Browser manipulation, and Chrom DevTool protocol.

  4. Selenium 4 Is Now W3C Compliant: JSON Wireframe protocol is retiring from Selenium 4, and they are adopting W3C protocol to learn in detail about the advantages and impact of these changes.

  5. How To Use Selenium 4 Relative Locator? : Selenium 4 came with new features such as Relative Locators that allow constructing locators with reference and easily located constructors nearby. Get to know its different use cases with examples.

  6. Selenium Grid 4 Tutorial For Distributed Testing: Selenium Grid 4 allows you to perform tests over different browsers, OS, and device combinations. It also enables parallel execution browser testing, reads up on various features of Selenium Grid 4 and how to download it, and runs a test on Selenium Grid 4 with best practices.

  7. Selenium Video Tutorials: Binge on video tutorials on Selenium by industry experts to get step-by-step direction from automating basic to complex test scenarios with Selenium.

Selenium 101 certifications:

LambdaTest also provides certification for Selenium testing to accelerate your career in Selenium automation testing.

Run Selenium automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful