How to use Slot class of org.openqa.selenium.grid.data package

Best Selenium code snippet using org.openqa.selenium.grid.data.Slot

Source:GraphqlHandlerTest.java Github

copy

Full Screen

...25import org.openqa.selenium.events.EventBus;26import org.openqa.selenium.events.local.GuavaEventBus;27import org.openqa.selenium.grid.data.CreateSessionRequest;28import org.openqa.selenium.grid.data.CreateSessionResponse;29import org.openqa.selenium.grid.data.DefaultSlotMatcher;30import org.openqa.selenium.grid.data.NewSessionRequestEvent;31import org.openqa.selenium.grid.data.RequestId;32import org.openqa.selenium.grid.data.Session;33import org.openqa.selenium.grid.data.Slot;34import org.openqa.selenium.grid.distributor.Distributor;35import org.openqa.selenium.grid.distributor.local.LocalDistributor;36import org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector;37import org.openqa.selenium.grid.node.ActiveSession;38import org.openqa.selenium.grid.node.Node;39import org.openqa.selenium.grid.node.SessionFactory;40import org.openqa.selenium.grid.node.local.LocalNode;41import org.openqa.selenium.grid.security.Secret;42import org.openqa.selenium.grid.sessionmap.SessionMap;43import org.openqa.selenium.grid.sessionmap.local.LocalSessionMap;44import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;45import org.openqa.selenium.grid.data.SessionRequest;46import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;47import org.openqa.selenium.grid.testing.TestSessionFactory;48import org.openqa.selenium.internal.Either;49import org.openqa.selenium.json.Json;50import org.openqa.selenium.remote.http.Contents;51import org.openqa.selenium.remote.http.HttpClient;52import org.openqa.selenium.remote.http.HttpHandler;53import org.openqa.selenium.remote.http.HttpRequest;54import org.openqa.selenium.remote.http.HttpResponse;55import org.openqa.selenium.remote.tracing.DefaultTestTracer;56import org.openqa.selenium.remote.tracing.Tracer;57import org.openqa.selenium.support.ui.FluentWait;58import org.openqa.selenium.support.ui.Wait;59import java.net.URI;60import java.net.URISyntaxException;61import java.time.Duration;62import java.time.Instant;63import java.util.Collections;64import java.util.Map;65import java.util.Set;66import java.util.UUID;67import java.util.concurrent.CountDownLatch;68import java.util.concurrent.atomic.AtomicInteger;69import static java.util.Collections.singletonList;70import static java.util.Collections.singletonMap;71import static java.util.concurrent.TimeUnit.SECONDS;72import static org.assertj.core.api.Assertions.assertThat;73import static org.assertj.core.api.Assertions.fail;74import static org.assertj.core.api.InstanceOfAssertFactories.LIST;75import static org.assertj.core.api.InstanceOfAssertFactories.MAP;76import static org.openqa.selenium.json.Json.MAP_TYPE;77import static org.openqa.selenium.remote.Dialect.OSS;78import static org.openqa.selenium.remote.Dialect.W3C;79import static org.openqa.selenium.remote.http.HttpMethod.GET;80public class GraphqlHandlerTest {81 private static final Json JSON = new Json();82 private final Secret registrationSecret = new Secret("stilton");83 private final URI publicUri = new URI("http://example.com/grid-o-matic");84 private final String version = "4.0.0";85 private final Wait<Object> wait = new FluentWait<>(new Object()).withTimeout(Duration.ofSeconds(5));86 private Distributor distributor;87 private NewSessionQueue queue;88 private Tracer tracer;89 private EventBus events;90 private ImmutableCapabilities caps;91 private ImmutableCapabilities stereotype;92 private SessionRequest sessionRequest;93 public GraphqlHandlerTest() throws URISyntaxException {94 }95 @Before96 public void setupGrid() {97 tracer = DefaultTestTracer.createTracer();98 events = new GuavaEventBus();99 HttpClient.Factory clientFactory = HttpClient.Factory.createDefault();100 SessionMap sessions = new LocalSessionMap(tracer, events);101 stereotype = new ImmutableCapabilities("browserName", "cheese");102 caps = new ImmutableCapabilities("browserName", "cheese");103 sessionRequest = new SessionRequest(104 new RequestId(UUID.randomUUID()),105 Instant.now(),106 Set.of(OSS, W3C),107 Set.of(caps),108 Map.of(),109 Map.of());110 queue = new LocalNewSessionQueue(111 tracer,112 events,113 new DefaultSlotMatcher(),114 Duration.ofSeconds(2),115 Duration.ofSeconds(2),116 registrationSecret);117 distributor = new LocalDistributor(118 tracer,119 events,120 clientFactory,121 sessions,122 queue,123 new DefaultSlotSelector(),124 registrationSecret,125 Duration.ofMinutes(5),126 false);127 }128 @Test129 public void shouldBeAbleToGetGridUri() {130 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);131 Map<String, Object> topLevel = executeQuery(handler, "{ grid { uri } }");132 assertThat(topLevel).isEqualTo(133 singletonMap(134 "data", singletonMap(135 "grid", singletonMap(136 "uri", publicUri.toString()))));137 }138 @Test139 public void shouldBeAbleToGetGridVersion() {140 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);141 Map<String, Object> topLevel = executeQuery(handler, "{ grid { version } }");142 assertThat(topLevel).isEqualTo(143 singletonMap(144 "data", singletonMap(145 "grid", singletonMap(146 "version", version))));147 }148 private void continueOnceAddedToQueue(SessionRequest request) {149 // Add to the queue in the background150 CountDownLatch latch = new CountDownLatch(1);151 events.addListener(NewSessionRequestEvent.listener(id -> latch.countDown()));152 new Thread(() -> {153 queue.addToQueue(request);154 }).start();155 try {156 assertThat(latch.await(5, SECONDS)).isTrue();157 } catch (InterruptedException e) {158 Thread.currentThread().interrupt();159 throw new RuntimeException(e);160 }161 }162 @Test163 public void shouldBeAbleToGetSessionQueueSize() throws URISyntaxException {164 SessionRequest request = new SessionRequest(165 new RequestId(UUID.randomUUID()),166 Instant.now(),167 Set.of(W3C),168 Set.of(caps),169 Map.of(),170 Map.of());171 continueOnceAddedToQueue(request);172 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);173 Map<String, Object> topLevel = executeQuery(handler, "{ grid { sessionQueueSize } }");174 assertThat(topLevel).isEqualTo(175 singletonMap(176 "data", singletonMap(177 "grid", singletonMap(178 "sessionQueueSize", 1L))));179 }180 @Test181 public void shouldBeAbleToGetSessionQueueRequests() throws URISyntaxException {182 SessionRequest request = new SessionRequest(183 new RequestId(UUID.randomUUID()),184 Instant.now(),185 Set.of(W3C),186 Set.of(caps),187 Map.of(),188 Map.of());189 continueOnceAddedToQueue(request);190 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);191 Map<String, Object> topLevel = executeQuery(handler,192 "{ sessionsInfo { sessionQueueRequests } }");193 assertThat(topLevel).isEqualTo(194 singletonMap(195 "data", singletonMap(196 "sessionsInfo", singletonMap(197 "sessionQueueRequests", singletonList(JSON.toJson(caps))))));198 }199 @Test200 public void shouldBeReturnAnEmptyListIfQueueIsEmpty() {201 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);202 Map<String, Object> topLevel = executeQuery(handler,203 "{ sessionsInfo { sessionQueueRequests } }");204 assertThat(topLevel).isEqualTo(205 singletonMap(206 "data", singletonMap(207 "sessionsInfo", singletonMap(208 "sessionQueueRequests", Collections.emptyList()))));209 }210 @Test211 public void shouldReturnAnEmptyListForNodesIfNoneAreRegistered() {212 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);213 Map<String, Object> topLevel = executeQuery(handler, "{ nodesInfo { nodes { uri } } }");214 assertThat(topLevel).describedAs(topLevel.toString()).isEqualTo(215 singletonMap(216 "data", singletonMap(217 "nodesInfo", singletonMap(218 "nodes", Collections.emptyList()))));219 }220 @Test221 public void shouldBeAbleToGetUrlsOfAllNodes() throws URISyntaxException {222 Capabilities stereotype = new ImmutableCapabilities("cheese", "stilton");223 String nodeUri = "http://localhost:5556";224 Node node = LocalNode.builder(tracer, events, new URI(nodeUri), publicUri, registrationSecret)225 .add(stereotype, new SessionFactory() {226 @Override227 public Either<WebDriverException, ActiveSession> apply(228 CreateSessionRequest createSessionRequest) {229 return Either.left(new SessionNotCreatedException("Factory for testing"));230 }231 @Override232 public boolean test(Capabilities capabilities) {233 return false;234 }235 })236 .build();237 distributor.add(node);238 wait.until(obj -> distributor.getStatus().hasCapacity());239 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);240 Map<String, Object> topLevel = executeQuery(handler, "{ nodesInfo { nodes { uri } } }");241 assertThat(topLevel).describedAs(topLevel.toString()).isEqualTo(242 singletonMap(243 "data", singletonMap(244 "nodesInfo", singletonMap(245 "nodes", singletonList(singletonMap("uri", nodeUri))))));246 }247 @Test248 public void shouldBeAbleToGetSessionCount() throws URISyntaxException {249 String nodeUrl = "http://localhost:5556";250 URI nodeUri = new URI(nodeUrl);251 Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)252 .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(253 id,254 nodeUri,255 stereotype,256 caps,257 Instant.now()))).build();258 distributor.add(node);259 wait.until(obj -> distributor.getStatus().hasCapacity());260 Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);261 if (response.isRight()) {262 Session session = response.right().getSession();263 assertThat(session).isNotNull();264 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);265 Map<String, Object> topLevel = executeQuery(handler,266 "{ grid { sessionCount } }");267 assertThat(topLevel).isEqualTo(268 singletonMap(269 "data", singletonMap(270 "grid", singletonMap(271 "sessionCount", 1L ))));272 } else {273 fail("Session creation failed", response.left());274 }275 }276 @Test277 public void shouldBeAbleToGetSessionInfo() throws URISyntaxException {278 String nodeUrl = "http://localhost:5556";279 URI nodeUri = new URI(nodeUrl);280 Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)281 .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(282 id,283 nodeUri,284 stereotype,285 caps,286 Instant.now()))).build();287 distributor.add(node);288 wait.until(obj -> distributor.getStatus().hasCapacity());289 Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);290 if (response.isRight()) {291 Session session = response.right().getSession();292 assertThat(session).isNotNull();293 String sessionId = session.getId().toString();294 Set<Slot> slots = distributor.getStatus().getNodes().stream().findFirst().get().getSlots();295 Slot slot = slots.stream().findFirst().get();296 org.openqa.selenium.grid.graphql.Session graphqlSession =297 new org.openqa.selenium.grid.graphql.Session(298 sessionId,299 session.getCapabilities(),300 session.getStartTime(),301 session.getUri(),302 node.getId().toString(),303 node.getUri(),304 slot);305 String query = String.format(306 "{ session (id: \"%s\") { id, capabilities, startTime, uri } }", sessionId);307 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);308 Map<String, Object> result = executeQuery(handler, query);309 assertThat(result).describedAs(result.toString()).isEqualTo(310 singletonMap(311 "data", singletonMap(312 "session", ImmutableMap.of(313 "id", sessionId,314 "capabilities", graphqlSession.getCapabilities(),315 "startTime", graphqlSession.getStartTime(),316 "uri", graphqlSession.getUri().toString()))));317 } else {318 fail("Session creation failed", response.left());319 }320 }321 @Test322 public void shouldBeAbleToGetNodeInfoForSession() throws URISyntaxException {323 String nodeUrl = "http://localhost:5556";324 URI nodeUri = new URI(nodeUrl);325 Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)326 .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(327 id,328 nodeUri,329 stereotype,330 caps,331 Instant.now()))).build();332 distributor.add(node);333 wait.until(obj -> distributor.getStatus().hasCapacity());334 Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);335 if (response.isRight()) {336 Session session = response.right().getSession();337 assertThat(session).isNotNull();338 String sessionId = session.getId().toString();339 Set<Slot> slots = distributor.getStatus().getNodes().stream().findFirst().get().getSlots();340 Slot slot = slots.stream().findFirst().get();341 org.openqa.selenium.grid.graphql.Session graphqlSession =342 new org.openqa.selenium.grid.graphql.Session(343 sessionId,344 session.getCapabilities(),345 session.getStartTime(),346 session.getUri(),347 node.getId().toString(),348 node.getUri(),349 slot);350 String query = String.format("{ session (id: \"%s\") { nodeId, nodeUri } }", sessionId);351 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);352 Map<String, Object> result = executeQuery(handler, query);353 assertThat(result).describedAs(result.toString()).isEqualTo(354 singletonMap(355 "data", singletonMap(356 "session", ImmutableMap.of(357 "nodeId", graphqlSession.getNodeId(),358 "nodeUri", graphqlSession.getNodeUri().toString()))));359 } else {360 fail("Session creation failed", response.left());361 }362 }363 @Test364 public void shouldBeAbleToGetSlotInfoForSession() throws URISyntaxException {365 String nodeUrl = "http://localhost:5556";366 URI nodeUri = new URI(nodeUrl);367 Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)368 .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(369 id,370 nodeUri,371 stereotype,372 caps,373 Instant.now()))).build();374 distributor.add(node);375 wait.until(obj -> distributor.getStatus().hasCapacity());376 Either<SessionNotCreatedException, CreateSessionResponse> response = distributor.newSession(sessionRequest);377 if (response.isRight()) {378 Session session = response.right().getSession();379 assertThat(session).isNotNull();380 String sessionId = session.getId().toString();381 Set<Slot> slots = distributor.getStatus().getNodes().stream().findFirst().get().getSlots();382 Slot slot = slots.stream().findFirst().get();383 org.openqa.selenium.grid.graphql.Session graphqlSession =384 new org.openqa.selenium.grid.graphql.Session(385 sessionId,386 session.getCapabilities(),387 session.getStartTime(),388 session.getUri(),389 node.getId().toString(),390 node.getUri(),391 slot);392 org.openqa.selenium.grid.graphql.Slot graphqlSlot = graphqlSession.getSlot();393 String query = String.format(394 "{ session (id: \"%s\") { slot { id, stereotype, lastStarted } } }", sessionId);395 GraphqlHandler handler = new GraphqlHandler(tracer, distributor, queue, publicUri, version);396 Map<String, Object> result = executeQuery(handler, query);397 assertThat(result).describedAs(result.toString()).isEqualTo(398 singletonMap(399 "data", singletonMap(400 "session", singletonMap(401 "slot", ImmutableMap.of(402 "id", graphqlSlot.getId(),403 "stereotype", graphqlSlot.getStereotype(),404 "lastStarted", graphqlSlot.getLastStarted())))));405 } else {406 fail("Session creation failed", response.left());407 }408 }409 @Test410 public void shouldBeAbleToGetSessionDuration() throws URISyntaxException {411 String nodeUrl = "http://localhost:5556";412 URI nodeUri = new URI(nodeUrl);413 Node node = LocalNode.builder(tracer, events, nodeUri, publicUri, registrationSecret)414 .add(caps, new TestSessionFactory((id, caps) -> new org.openqa.selenium.grid.data.Session(415 id,416 nodeUri,417 stereotype,418 caps,...

Full Screen

Full Screen

Source:AddingNodesTest.java Github

copy

Full Screen

...27import org.openqa.selenium.events.EventBus;28import org.openqa.selenium.events.local.GuavaEventBus;29import org.openqa.selenium.grid.data.CreateSessionRequest;30import org.openqa.selenium.grid.data.CreateSessionResponse;31import org.openqa.selenium.grid.data.DefaultSlotMatcher;32import org.openqa.selenium.grid.data.NodeId;33import org.openqa.selenium.grid.data.NodeStatus;34import org.openqa.selenium.grid.data.NodeStatusEvent;35import org.openqa.selenium.grid.data.Session;36import org.openqa.selenium.grid.data.SessionClosedEvent;37import org.openqa.selenium.grid.data.Slot;38import org.openqa.selenium.grid.data.SlotId;39import org.openqa.selenium.grid.distributor.local.LocalDistributor;40import org.openqa.selenium.grid.distributor.remote.RemoteDistributor;41import org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector;42import org.openqa.selenium.grid.node.CapabilityResponseEncoder;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.local.LocalSessionMap;48import org.openqa.selenium.grid.sessionqueue.NewSessionQueue;49import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue;50import org.openqa.selenium.grid.testing.TestSessionFactory;51import org.openqa.selenium.grid.web.CombinedHandler;52import org.openqa.selenium.grid.web.RoutableHttpClientFactory;53import org.openqa.selenium.internal.Either;54import org.openqa.selenium.remote.SessionId;55import org.openqa.selenium.remote.http.HttpClient;56import org.openqa.selenium.remote.http.HttpRequest;57import org.openqa.selenium.remote.http.HttpResponse;58import org.openqa.selenium.remote.tracing.DefaultTestTracer;59import org.openqa.selenium.remote.tracing.Tracer;60import org.openqa.selenium.support.ui.FluentWait;61import org.openqa.selenium.support.ui.Wait;62import java.net.MalformedURLException;63import java.net.URI;64import java.net.URISyntaxException;65import java.net.URL;66import java.time.Duration;67import java.time.Instant;68import java.util.HashMap;69import java.util.Map;70import java.util.Objects;71import java.util.Optional;72import java.util.Set;73import java.util.UUID;74import java.util.function.Function;75import static com.google.common.collect.Iterables.getOnlyElement;76import static org.junit.Assert.assertEquals;77import static org.openqa.selenium.grid.data.Availability.UP;78import static org.openqa.selenium.remote.Dialect.W3C;79public class AddingNodesTest {80 private static final Capabilities CAPS = new ImmutableCapabilities("cheese", "gouda");81 private static final Secret registrationSecret = new Secret("caerphilly");82 private Distributor distributor;83 private Tracer tracer;84 private EventBus bus;85 private Wait<Object> wait;86 private URL externalUrl;87 private CombinedHandler handler;88 private Capabilities stereotype;89 @Before90 public void setUpDistributor() throws MalformedURLException {91 tracer = DefaultTestTracer.createTracer();92 bus = new GuavaEventBus();93 handler = new CombinedHandler();94 externalUrl = new URL("http://example.com");95 HttpClient.Factory clientFactory = new RoutableHttpClientFactory(96 externalUrl,97 handler,98 HttpClient.Factory.createDefault());99 LocalSessionMap sessions = new LocalSessionMap(tracer, bus);100 NewSessionQueue queue = new LocalNewSessionQueue(101 tracer,102 bus,103 new DefaultSlotMatcher(),104 Duration.ofSeconds(2),105 Duration.ofSeconds(2),106 registrationSecret);107 Distributor local = new LocalDistributor(108 tracer,109 bus,110 clientFactory,111 sessions,112 queue,113 new DefaultSlotSelector(),114 registrationSecret,115 Duration.ofMinutes(5),116 false);117 handler.addHandler(local);118 distributor = new RemoteDistributor(tracer, clientFactory, externalUrl, registrationSecret);119 stereotype = new ImmutableCapabilities("browserName", "gouda");120 wait = new FluentWait<>(121 new Object()).ignoring(Throwable.class).withTimeout(Duration.ofSeconds(2));122 }123 @Test124 public void shouldBeAbleToRegisterALocalNode() throws URISyntaxException {125 URI sessionUri = new URI("http://example:1234");126 Node node = LocalNode127 .builder(tracer, bus, externalUrl.toURI(), externalUrl.toURI(), registrationSecret)128 .add(129 CAPS,130 new TestSessionFactory(131 (id, caps) -> new Session(id, sessionUri, stereotype, caps, Instant.now())))132 .build();133 handler.addHandler(node);134 distributor.add(node);135 wait.until(obj -> distributor.getStatus().hasCapacity());136 NodeStatus status = getOnlyElement(distributor.getStatus().getNodes());137 assertEquals(1, getStereotypes(status).get(CAPS).intValue());138 }139 @Test140 public void shouldBeAbleToRegisterACustomNode() throws URISyntaxException {141 URI sessionUri = new URI("http://example:1234");142 Node node = new CustomNode(143 bus,144 new NodeId(UUID.randomUUID()),145 externalUrl.toURI(),146 c -> new Session(147 new SessionId(UUID.randomUUID()), sessionUri, stereotype, c, Instant.now()));148 handler.addHandler(node);149 distributor.add(node);150 wait.until(obj -> distributor.getStatus().hasCapacity());151 NodeStatus status = getOnlyElement(distributor.getStatus().getNodes());152 assertEquals(1, getStereotypes(status).get(CAPS).intValue());153 }154 @Test155 public void shouldBeAbleToRegisterNodesByListeningForEvents() throws URISyntaxException {156 URI sessionUri = new URI("http://example:1234");157 Node node = LocalNode158 .builder(tracer, bus, externalUrl.toURI(), externalUrl.toURI(), registrationSecret)159 .add(160 CAPS,161 new TestSessionFactory(162 (id, caps) -> new Session(id, sessionUri, stereotype, caps, Instant.now())))163 .build();164 handler.addHandler(node);165 bus.fire(new NodeStatusEvent(node.getStatus()));166 wait.until(obj -> distributor.getStatus().hasCapacity());167 NodeStatus status = getOnlyElement(distributor.getStatus().getNodes());168 assertEquals(1, getStereotypes(status).get(CAPS).intValue());169 }170 @Test171 public void shouldKeepOnlyOneNodeWhenTwoRegistrationsHaveTheSameUriByListeningForEvents()172 throws URISyntaxException {173 URI sessionUri = new URI("http://example:1234");174 Node firstNode = LocalNode175 .builder(tracer, bus, externalUrl.toURI(), externalUrl.toURI(), registrationSecret)176 .add(177 CAPS,178 new TestSessionFactory(179 (id, caps) -> new Session(id, sessionUri, stereotype, caps, Instant.now())))180 .build();181 Node secondNode = LocalNode182 .builder(tracer, bus, externalUrl.toURI(), externalUrl.toURI(), registrationSecret)183 .add(184 CAPS,185 new TestSessionFactory(186 (id, caps) -> new Session(id, sessionUri, stereotype, caps, Instant.now())))187 .build();188 handler.addHandler(firstNode);189 handler.addHandler(secondNode);190 bus.fire(new NodeStatusEvent(firstNode.getStatus()));191 bus.fire(new NodeStatusEvent(secondNode.getStatus()));192 wait.until(obj -> distributor.getStatus());193 Set<NodeStatus> nodes = distributor.getStatus().getNodes();194 assertEquals(1, nodes.size());195 }196 @Test197 public void distributorShouldUpdateStateOfExistingNodeWhenNodePublishesStateChange()198 throws URISyntaxException {199 URI sessionUri = new URI("http://example:1234");200 Node node = LocalNode201 .builder(tracer, bus, externalUrl.toURI(), externalUrl.toURI(), registrationSecret)202 .add(203 CAPS,204 new TestSessionFactory(205 (id, caps) -> new Session(id, sessionUri, stereotype, caps, Instant.now())))206 .build();207 handler.addHandler(node);208 bus.fire(new NodeStatusEvent(node.getStatus()));209 // Start empty210 wait.until(obj -> distributor.getStatus().hasCapacity());211 NodeStatus nodeStatus = getOnlyElement(distributor.getStatus().getNodes());212 assertEquals(1, getStereotypes(nodeStatus).get(CAPS).intValue());213 // Craft a status that makes it look like the node is busy, and post it on the bus.214 NodeStatus status = node.getStatus();215 NodeStatus crafted = new NodeStatus(216 status.getId(),217 status.getUri(),218 status.getMaxSessionCount(),219 ImmutableSet.of(220 new Slot(221 new SlotId(status.getId(), UUID.randomUUID()),222 CAPS,223 Instant.now(),224 Optional.of(new Session(225 new SessionId(UUID.randomUUID()), sessionUri, CAPS, CAPS, Instant.now())))),226 UP,227 Duration.ofSeconds(10),228 status.getVersion(),229 status.getOsInfo());230 bus.fire(new NodeStatusEvent(crafted));231 // We claimed the only slot is filled. Life is good.232 wait.until(obj -> !distributor.getStatus().hasCapacity());233 }234 private Map<Capabilities, Integer> getStereotypes(NodeStatus status) {235 Map<Capabilities, Integer> stereotypes = new HashMap<>();236 for (Slot slot : status.getSlots()) {237 int count = stereotypes.getOrDefault(slot.getStereotype(), 0);238 count++;239 stereotypes.put(slot.getStereotype(), count);240 }241 return ImmutableMap.copyOf(stereotypes);242 }243 static class CustomNode extends Node {244 private final EventBus bus;245 private final Function<Capabilities, Session> factory;246 private Session running;247 protected CustomNode(248 EventBus bus,249 NodeId nodeId,250 URI uri,251 Function<Capabilities, Session> factory) {252 super(DefaultTestTracer.createTracer(), nodeId, uri, registrationSecret);253 this.bus = bus;254 this.factory = Objects.requireNonNull(factory);255 }256 @Override257 public boolean isReady() {258 return true;259 }260 @Override261 public Either<WebDriverException, CreateSessionResponse> newSession(CreateSessionRequest sessionRequest) {262 Objects.requireNonNull(sessionRequest);263 if (running != null) {264 return Either.left(new SessionNotCreatedException("Session already exists"));265 }266 Session session = factory.apply(sessionRequest.getDesiredCapabilities());267 running = session;268 return Either.right(269 new CreateSessionResponse(270 session,271 CapabilityResponseEncoder.getEncoder(W3C).apply(session)));272 }273 @Override274 public HttpResponse executeWebDriverCommand(HttpRequest req) {275 throw new UnsupportedOperationException("executeWebDriverCommand");276 }277 @Override278 public HttpResponse uploadFile(HttpRequest req, SessionId id) {279 throw new UnsupportedOperationException("uploadFile");280 }281 @Override282 public Session getSession(SessionId id) throws NoSuchSessionException {283 if (running == null || !running.getId().equals(id)) {284 throw new NoSuchSessionException();285 }286 return running;287 }288 @Override289 public void stop(SessionId id) throws NoSuchSessionException {290 getSession(id);291 running = null;292 bus.fire(new SessionClosedEvent(id));293 }294 @Override295 public boolean isSessionOwner(SessionId id) {296 return running != null && running.getId().equals(id);297 }298 @Override299 public boolean isSupporting(Capabilities capabilities) {300 return Objects.equals("cake", capabilities.getCapability("cheese"));301 }302 @Override303 public NodeStatus getStatus() {304 Session sess = null;305 if (running != null) {306 try {307 sess = new Session(308 running.getId(),309 new URI("http://localhost:14568"),310 CAPS,311 running.getCapabilities(),312 Instant.now());313 } catch (URISyntaxException e) {314 throw new RuntimeException(e);315 }316 }317 return new NodeStatus(318 getId(),319 getUri(),320 1,321 ImmutableSet.of(322 new Slot(323 new SlotId(getId(), UUID.randomUUID()),324 CAPS,325 Instant.now(),326 Optional.ofNullable(sess))),327 UP,328 Duration.ofSeconds(10),329 getNodeVersion(),330 getOsInfo());331 }332 @Override333 public HealthCheck getHealthCheck() {334 return () -> new HealthCheck.Result(UP, "tl;dr");335 }336 @Override337 public void drain() {...

Full Screen

Full Screen

Source:OneShotNode.java Github

copy

Full Screen

...33import org.openqa.selenium.grid.data.NodeId;34import org.openqa.selenium.grid.data.NodeStatus;35import org.openqa.selenium.grid.data.Session;36import org.openqa.selenium.grid.data.SessionClosedEvent;37import org.openqa.selenium.grid.data.Slot;38import org.openqa.selenium.grid.data.SlotId;39import org.openqa.selenium.grid.log.LoggingOptions;40import org.openqa.selenium.grid.node.HealthCheck;41import org.openqa.selenium.grid.node.Node;42import org.openqa.selenium.grid.node.config.NodeOptions;43import org.openqa.selenium.grid.security.Secret;44import org.openqa.selenium.grid.server.BaseServerOptions;45import org.openqa.selenium.grid.server.EventBusOptions;46import org.openqa.selenium.internal.Require;47import org.openqa.selenium.json.Json;48import org.openqa.selenium.remote.CommandExecutor;49import org.openqa.selenium.remote.RemoteWebDriver;50import org.openqa.selenium.remote.SessionId;51import org.openqa.selenium.remote.http.HttpClient;52import org.openqa.selenium.remote.http.HttpRequest;53import org.openqa.selenium.remote.http.HttpResponse;54import org.openqa.selenium.remote.tracing.Tracer;55import java.lang.reflect.Field;56import java.net.URI;57import java.net.URISyntaxException;58import java.time.Instant;59import java.util.HashMap;60import java.util.Map;61import java.util.Optional;62import java.util.ServiceLoader;63import java.util.TreeMap;64import java.util.UUID;65import java.util.logging.Logger;66import java.util.stream.StreamSupport;67import static java.nio.charset.StandardCharsets.UTF_8;68import static org.openqa.selenium.grid.data.Availability.DRAINING;69import static org.openqa.selenium.grid.data.Availability.UP;70import static org.openqa.selenium.json.Json.MAP_TYPE;71import static org.openqa.selenium.remote.http.HttpMethod.DELETE;72/**73 * An implementation of {@link Node} that marks itself as draining immediately74 * after starting, and which then shuts down after usage. This will allow an75 * appropriately configured Kubernetes cluster to start a new node once the76 * session is finished.77 */78public class OneShotNode extends Node {79 private static final Logger LOG = Logger.getLogger(OneShotNode.class.getName());80 private static final Json JSON = new Json();81 private final EventBus events;82 private final WebDriverInfo driverInfo;83 private final Capabilities stereotype;84 private final URI gridUri;85 private final UUID slotId = UUID.randomUUID();86 private RemoteWebDriver driver;87 private SessionId sessionId;88 private HttpClient client;89 private Capabilities capabilities;90 private Instant sessionStart = Instant.EPOCH;91 private OneShotNode(92 Tracer tracer,93 EventBus events,94 Secret registrationSecret,95 NodeId id,96 URI uri,97 URI gridUri,98 Capabilities stereotype,99 WebDriverInfo driverInfo) {100 super(tracer, id, uri, registrationSecret);101 this.events = Require.nonNull("Event bus", events);102 this.gridUri = Require.nonNull("Public Grid URI", gridUri);103 this.stereotype = ImmutableCapabilities.copyOf(Require.nonNull("Stereotype", stereotype));104 this.driverInfo = Require.nonNull("Driver info", driverInfo);105 }106 public static Node create(Config config) {107 LoggingOptions loggingOptions = new LoggingOptions(config);108 EventBusOptions eventOptions = new EventBusOptions(config);109 BaseServerOptions serverOptions = new BaseServerOptions(config);110 NodeOptions nodeOptions = new NodeOptions(config);111 Map<String, Object> raw = new Json().toType(112 config.get("k8s", "stereotype")113 .orElseThrow(() -> new ConfigException("Unable to find node stereotype")),114 MAP_TYPE);115 Capabilities stereotype = new ImmutableCapabilities(raw);116 Optional<String> driverName = config.get("k8s", "driver_name").map(String::toLowerCase);117 // Find the webdriver info corresponding to the driver name118 WebDriverInfo driverInfo = StreamSupport.stream(ServiceLoader.load(WebDriverInfo.class).spliterator(), false)119 .filter(info -> info.isSupporting(stereotype))120 .filter(info -> driverName.map(name -> name.equals(info.getDisplayName().toLowerCase())).orElse(true))121 .findFirst()122 .orElseThrow(() -> new ConfigException(123 "Unable to find matching driver for %s and %s", stereotype, driverName.orElse("any driver")));124 LOG.info(String.format("Creating one-shot node for %s with stereotype %s", driverInfo, stereotype));125 LOG.info("Grid URI is: " + nodeOptions.getPublicGridUri());126 return new OneShotNode(127 loggingOptions.getTracer(),128 eventOptions.getEventBus(),129 serverOptions.getRegistrationSecret(),130 new NodeId(UUID.randomUUID()),131 serverOptions.getExternalUri(),132 nodeOptions.getPublicGridUri().orElseThrow(() -> new ConfigException("Unable to determine public grid address")),133 stereotype,134 driverInfo);135 }136 @Override137 public Optional<CreateSessionResponse> newSession(CreateSessionRequest sessionRequest) {138 if (driver != null) {139 throw new IllegalStateException("Only expected one session at a time");140 }141 Optional<WebDriver> driver = driverInfo.createDriver(sessionRequest.getCapabilities());142 if (!driver.isPresent()) {143 return Optional.empty();144 }145 if (!(driver.get() instanceof RemoteWebDriver)) {146 driver.get().quit();147 return Optional.empty();148 }149 this.driver = (RemoteWebDriver) driver.get();150 this.sessionId = this.driver.getSessionId();151 this.client = extractHttpClient(this.driver);152 this.capabilities = rewriteCapabilities(this.driver);153 this.sessionStart = Instant.now();154 LOG.info("Encoded response: " + JSON.toJson(ImmutableMap.of(155 "value", ImmutableMap.of(156 "sessionId", sessionId,157 "capabilities", capabilities))));158 events.fire(new NodeDrainStarted(getId()));159 return Optional.of(160 new CreateSessionResponse(161 getSession(sessionId),162 JSON.toJson(ImmutableMap.of(163 "value", ImmutableMap.of(164 "sessionId", sessionId,165 "capabilities", capabilities))).getBytes(UTF_8)));166 }167 private HttpClient extractHttpClient(RemoteWebDriver driver) {168 CommandExecutor executor = driver.getCommandExecutor();169 try {170 Field client = null;171 Class<?> current = executor.getClass();172 while (client == null && (current != null || Object.class.equals(current))) {173 client = findClientField(current);174 current = current.getSuperclass();175 }176 if (client == null) {177 throw new IllegalStateException("Unable to find client field in " + executor.getClass());178 }179 if (!HttpClient.class.isAssignableFrom(client.getType())) {180 throw new IllegalStateException("Client field is not assignable to http client");181 }182 client.setAccessible(true);183 return (HttpClient) client.get(executor);184 } catch (ReflectiveOperationException e) {185 throw new IllegalStateException(e);186 }187 }188 private Field findClientField(Class<?> clazz) {189 try {190 return clazz.getDeclaredField("client");191 } catch (NoSuchFieldException e) {192 return null;193 }194 }195 private Capabilities rewriteCapabilities(RemoteWebDriver driver) {196 // Rewrite the se:options if necessary197 Object rawSeleniumOptions = driver.getCapabilities().getCapability("se:options");198 if (rawSeleniumOptions == null || rawSeleniumOptions instanceof Map) {199 @SuppressWarnings("unchecked") Map<String, Object> original = (Map<String, Object>) rawSeleniumOptions;200 Map<String, Object> updated = new TreeMap<>(original == null ? new HashMap<>() : original);201 String cdpPath = String.format("/session/%s/se/cdp", driver.getSessionId());202 updated.put("cdp", rewrite(cdpPath));203 return new PersistentCapabilities(driver.getCapabilities()).setCapability("se:options", updated);204 }205 return ImmutableCapabilities.copyOf(driver.getCapabilities());206 }207 private URI rewrite(String path) {208 try {209 return new URI(210 gridUri.getScheme(),211 gridUri.getUserInfo(),212 gridUri.getHost(),213 gridUri.getPort(),214 path,215 null,216 null);217 } catch (URISyntaxException e) {218 throw new RuntimeException(e);219 }220 }221 @Override222 public HttpResponse executeWebDriverCommand(HttpRequest req) {223 LOG.info("Executing " + req);224 HttpResponse res = client.execute(req);225 if (DELETE.equals(req.getMethod()) && req.getUri().equals("/session/" + sessionId)) {226 // Ensure the response is sent before we viciously kill the node227 new Thread(228 () -> {229 try {230 Thread.sleep(500);231 } catch (InterruptedException e) {232 Thread.currentThread().interrupt();233 throw new RuntimeException(e);234 }235 LOG.info("Stopping session: " + sessionId);236 stop(sessionId);237 },238 "Node clean up: " + getId())239 .start();240 }241 return res;242 }243 @Override244 public Session getSession(SessionId id) throws NoSuchSessionException {245 if (!isSessionOwner(id)) {246 throw new NoSuchSessionException("Unable to find session with id: " + id);247 }248 return new Session(249 sessionId,250 getUri(),251 stereotype,252 capabilities,253 sessionStart); }254 @Override255 public HttpResponse uploadFile(HttpRequest req, SessionId id) {256 return null;257 }258 @Override259 public void stop(SessionId id) throws NoSuchSessionException {260 LOG.info("Stop has been called: " + id);261 Require.nonNull("Session ID", id);262 if (!isSessionOwner(id)) {263 throw new NoSuchSessionException("Unable to find session " + id);264 }265 LOG.info("Quitting session " + id);266 try {267 driver.quit();268 } catch (Exception e) {269 // It's possible that the driver has already quit.270 }271 events.fire(new SessionClosedEvent(id));272 LOG.info("Firing node drain complete message");273 events.fire(new NodeDrainComplete(getId()));274 }275 @Override276 public boolean isSessionOwner(SessionId id) {277 return driver != null && sessionId.equals(id);278 }279 @Override280 public boolean isSupporting(Capabilities capabilities) {281 return driverInfo.isSupporting(capabilities);282 }283 @Override284 public NodeStatus getStatus() {285 return new NodeStatus(286 getId(),287 getUri(),288 1,289 ImmutableSet.of(290 new Slot(291 new SlotId(getId(), slotId),292 stereotype,293 Instant.EPOCH,294 driver == null ?295 Optional.empty() :296 Optional.of(new Session(sessionId, getUri(), stereotype, capabilities, Instant.now())))),297 isDraining() ? DRAINING : UP);298 }299 @Override300 public void drain() {301 events.fire(new NodeDrainStarted(getId()));302 draining = true;303 }304 @Override305 public HealthCheck getHealthCheck() {...

Full Screen

Full Screen

Source:GridModel.java Github

copy

Full Screen

...25import org.openqa.selenium.grid.data.NodeStatus;26import org.openqa.selenium.grid.data.NodeStatusEvent;27import org.openqa.selenium.grid.data.Session;28import org.openqa.selenium.grid.data.SessionClosedEvent;29import org.openqa.selenium.grid.data.Slot;30import org.openqa.selenium.grid.data.SlotId;31import org.openqa.selenium.grid.security.Secret;32import org.openqa.selenium.internal.Require;33import org.openqa.selenium.remote.SessionId;34import java.time.Instant;35import java.util.HashSet;36import java.util.Iterator;37import java.util.Map;38import java.util.Optional;39import java.util.Set;40import java.util.concurrent.ConcurrentHashMap;41import java.util.concurrent.locks.Lock;42import java.util.concurrent.locks.ReadWriteLock;43import java.util.concurrent.locks.ReentrantReadWriteLock;44import java.util.logging.Logger;45import static org.openqa.selenium.grid.data.Availability.DOWN;46import static org.openqa.selenium.grid.data.Availability.DRAINING;47import static org.openqa.selenium.grid.data.Availability.UP;48public class GridModel {49 private static final Logger LOG = Logger.getLogger(GridModel.class.getName());50 private static final SessionId RESERVED = new SessionId("reserved");51 private final ReadWriteLock lock = new ReentrantReadWriteLock(/* fair */ true);52 private final Map<Availability, Set<NodeStatus>> nodes = new ConcurrentHashMap<>();53 private final EventBus events;54 public GridModel(EventBus events, Secret registrationSecret) {55 this.events = Require.nonNull("Event bus", events);56 Require.nonNull("Registration secret", registrationSecret);57 events.addListener(NodeDrainStarted.listener(nodeId -> setAvailability(nodeId, DRAINING)));58 events.addListener(NodeDrainComplete.listener(this::remove));59 events.addListener(NodeRemovedEvent.listener(this::remove));60 events.addListener(NodeStatusEvent.listener(status -> refresh(status)));61 events.addListener(SessionClosedEvent.listener(this::release));62 }63 public GridModel add(NodeStatus node) {64 Require.nonNull("Node", node);65 Lock writeLock = lock.writeLock();66 writeLock.lock();67 try {68 // If we've already added the node, remove it.69 for (Set<NodeStatus> nodes : nodes.values()) {70 Iterator<NodeStatus> iterator = nodes.iterator();71 while (iterator.hasNext()) {72 NodeStatus next = iterator.next();73 // If the ID is the same, we're re-adding a node. If the URI is the same a node probably restarted74 if (next.getId().equals(node.getId()) || next.getUri().equals(node.getUri())) {75 LOG.info(String.format("Re-adding node with id %s and URI %s.", node.getId(), node.getUri()));76 iterator.remove();77 }78 }79 }80 // Nodes are initially added in the "down" state until something changes their availability81 nodes(DOWN).add(node);82 } finally {83 writeLock.unlock();84 }85 return this;86 }87 public GridModel refresh(NodeStatus status) {88 Require.nonNull("Node status", status);89 Lock writeLock = lock.writeLock();90 writeLock.lock();91 try {92 AvailabilityAndNode availabilityAndNode = findNode(status.getId());93 if (availabilityAndNode == null) {94 return this;95 }96 // if the node was marked as "down", keep it down until a healthcheck passes:97 // just because the node can hit the event bus doesn't mean it's reachable98 if (DOWN.equals(availabilityAndNode.availability)) {99 nodes(DOWN).remove(availabilityAndNode.status);100 nodes(DOWN).add(status);101 return this;102 }103 // But do trust the node if it tells us it's draining104 nodes(availabilityAndNode.availability).remove(availabilityAndNode.status);105 nodes(status.getAvailability()).add(status);106 return this;107 } finally {108 writeLock.unlock();109 }110 }111 public GridModel remove(NodeId id) {112 Require.nonNull("Node ID", id);113 Lock writeLock = lock.writeLock();114 writeLock.lock();115 try {116 AvailabilityAndNode availabilityAndNode = findNode(id);117 if (availabilityAndNode == null) {118 return this;119 }120 nodes(availabilityAndNode.availability).remove(availabilityAndNode.status);121 return this;122 } finally {123 writeLock.unlock();124 }125 }126 public Availability setAvailability(NodeId id, Availability availability) {127 Require.nonNull("Node ID", id);128 Require.nonNull("Availability", availability);129 Lock writeLock = lock.writeLock();130 writeLock.lock();131 try {132 AvailabilityAndNode availabilityAndNode = findNode(id);133 if (availabilityAndNode == null) {134 return DOWN;135 }136 if (availability.equals(availabilityAndNode.availability)) {137 return availability;138 }139 nodes(availabilityAndNode.availability).remove(availabilityAndNode.status);140 nodes(availability).add(availabilityAndNode.status);141 LOG.info(String.format(142 "Switching node %s (uri: %s) from %s to %s",143 id,144 availabilityAndNode.status.getUri(),145 availabilityAndNode.availability,146 availability));147 return availabilityAndNode.availability;148 } finally {149 writeLock.unlock();150 }151 }152 public boolean reserve(SlotId slotId) {153 Lock writeLock = lock.writeLock();154 writeLock.lock();155 try {156 AvailabilityAndNode node = findNode(slotId.getOwningNodeId());157 if (node == null) {158 LOG.warning(String.format("Asked to reserve slot on node %s, but unable to find node", slotId.getOwningNodeId()));159 return false;160 }161 if (!UP.equals(node.availability)) {162 LOG.warning(String.format(163 "Asked to reserve a slot on node %s, but not is %s",164 slotId.getOwningNodeId(),165 node.availability));166 return false;167 }168 Optional<Slot> maybeSlot = node.status.getSlots().stream()169 .filter(slot -> slotId.equals(slot.getId()))170 .findFirst();171 if (!maybeSlot.isPresent()) {172 LOG.warning(String.format(173 "Asked to reserve slot on node %s, but no slot with id %s found",174 node.status.getId(),175 slotId));176 return false;177 }178 reserve(node.status, maybeSlot.get());179 return true;180 } finally {181 writeLock.unlock();182 }183 }184 public Set<NodeStatus> getSnapshot() {185 Lock readLock = this.lock.readLock();186 readLock.lock();187 try {188 ImmutableSet.Builder<NodeStatus> snapshot = ImmutableSet.builder();189 for (Map.Entry<Availability, Set<NodeStatus>> entry : nodes.entrySet()) {190 entry.getValue().stream()191 .map(status -> rewrite(status, entry.getKey()))192 .forEach(snapshot::add);193 }194 return snapshot.build();195 } finally {196 readLock.unlock();197 }198 }199 private Set<NodeStatus> nodes(Availability availability) {200 return nodes.computeIfAbsent(availability, ignored -> new HashSet<>());201 }202 private AvailabilityAndNode findNode(NodeId id) {203 for (Map.Entry<Availability, Set<NodeStatus>> entry : nodes.entrySet()) {204 for (NodeStatus nodeStatus : entry.getValue()) {205 if (id.equals(nodeStatus.getId())) {206 return new AvailabilityAndNode(entry.getKey(), nodeStatus);207 }208 }209 }210 return null;211 }212 private NodeStatus rewrite(NodeStatus status, Availability availability) {213 return new NodeStatus(214 status.getId(),215 status.getUri(),216 status.getMaxSessionCount(),217 status.getSlots(),218 availability);219 }220 private void release(SessionId id) {221 if (id == null) {222 return;223 }224 Lock writeLock = lock.writeLock();225 writeLock.lock();226 try {227 for (Map.Entry<Availability, Set<NodeStatus>> entry : nodes.entrySet()) {228 for (NodeStatus node : entry.getValue()) {229 for (Slot slot : node.getSlots()) {230 if (!slot.getSession().isPresent()) {231 continue;232 }233 if (id.equals(slot.getSession().get().getId())) {234 Slot released = new Slot(235 slot.getId(),236 slot.getStereotype(),237 slot.getLastStarted(),238 Optional.empty());239 amend(entry.getKey(), node, released);240 return;241 }242 }243 }244 }245 } finally {246 writeLock.unlock();247 }248 }249 private void reserve(NodeStatus status, Slot slot) {250 Instant now = Instant.now();251 Slot reserved = new Slot(252 slot.getId(),253 slot.getStereotype(),254 now,255 Optional.of(new Session(256 RESERVED,257 status.getUri(),258 slot.getStereotype(),259 slot.getStereotype(),260 now)));261 amend(UP, status, reserved);262 }263 public void setSession(SlotId slotId, Session session) {264 Require.nonNull("Slot ID", slotId);265 AvailabilityAndNode node = findNode(slotId.getOwningNodeId());266 if (node == null) {267 LOG.warning("Grid model and reality have diverged. Unable to find node " + slotId.getOwningNodeId());268 return;269 }270 Optional<Slot> maybeSlot = node.status.getSlots().stream()271 .filter(slot -> slotId.equals(slot.getId()))272 .findFirst();273 if (!maybeSlot.isPresent()) {274 LOG.warning("Grid model and reality have diverged. Unable to find slot " + slotId);275 return;276 }277 Slot slot = maybeSlot.get();278 Optional<Session> maybeSession = slot.getSession();279 if (!maybeSession.isPresent()) {280 LOG.warning("Grid model and reality have diverged. Slot is not reserved. " + slotId);281 return;282 }283 Session current = maybeSession.get();284 if (!RESERVED.equals(current.getId())) {285 LOG.warning("Gid model and reality have diverged. Slot has session and is not reserved. " + slotId);286 return;287 }288 Slot updated = new Slot(289 slot.getId(),290 slot.getStereotype(),291 session == null ? slot.getLastStarted() : session.getStartTime(),292 Optional.ofNullable(session));293 amend(node.availability, node.status, updated);294 }295 private void amend(Availability availability, NodeStatus status, Slot slot) {296 Set<Slot> newSlots = new HashSet<>(status.getSlots());297 newSlots.removeIf(s -> s.getId().equals(slot.getId()));298 newSlots.add(slot);299 nodes(availability).remove(status);300 nodes(availability).add(new NodeStatus(301 status.getId(),302 status.getUri(),303 status.getMaxSessionCount(),304 newSlots,305 status.getAvailability()));306 }307 private static class AvailabilityAndNode {308 public final Availability availability;309 public final NodeStatus status;310 public AvailabilityAndNode(Availability availability, NodeStatus status) {311 this.availability = availability;312 this.status = status;313 }314 }315}...

Full Screen

Full Screen

Source:LocalDistributor.java Github

copy

Full Screen

...31import org.openqa.selenium.grid.data.NodeId;32import org.openqa.selenium.grid.data.NodeRemovedEvent;33import org.openqa.selenium.grid.data.NodeStatus;34import org.openqa.selenium.grid.data.NodeStatusEvent;35import org.openqa.selenium.grid.data.Slot;36import org.openqa.selenium.grid.data.SlotId;37import org.openqa.selenium.grid.distributor.Distributor;38import org.openqa.selenium.grid.distributor.selector.DefaultSlotSelector;39import org.openqa.selenium.grid.log.LoggingOptions;40import org.openqa.selenium.grid.node.HealthCheck;41import org.openqa.selenium.grid.node.Node;42import org.openqa.selenium.grid.node.remote.RemoteNode;43import org.openqa.selenium.grid.security.Secret;44import org.openqa.selenium.grid.server.BaseServerOptions;45import org.openqa.selenium.grid.server.EventBusOptions;46import org.openqa.selenium.grid.server.NetworkOptions;47import org.openqa.selenium.grid.sessionmap.SessionMap;48import org.openqa.selenium.grid.sessionmap.config.SessionMapOptions;49import org.openqa.selenium.internal.Require;50import org.openqa.selenium.remote.http.HttpClient;51import org.openqa.selenium.remote.tracing.Tracer;52import org.openqa.selenium.status.HasReadyState;53import java.time.Duration;54import java.util.ArrayList;55import java.util.HashMap;56import java.util.List;57import java.util.Map;58import java.util.Optional;59import java.util.Set;60import java.util.concurrent.locks.Lock;61import java.util.concurrent.locks.ReadWriteLock;62import java.util.concurrent.locks.ReentrantReadWriteLock;63import java.util.function.Supplier;64import java.util.logging.Level;65import java.util.logging.Logger;66import static com.google.common.collect.ImmutableSet.toImmutableSet;67import static org.openqa.selenium.grid.data.Availability.DOWN;68import static org.openqa.selenium.grid.data.Availability.DRAINING;69public class LocalDistributor extends Distributor {70 private static final Logger LOG = Logger.getLogger(LocalDistributor.class.getName());71 private final Tracer tracer;72 private final EventBus bus;73 private final HttpClient.Factory clientFactory;74 private final SessionMap sessions;75 private final Secret registrationSecret;76 private final Regularly hostChecker = new Regularly("distributor host checker");77 private final Map<NodeId, Runnable> allChecks = new HashMap<>();78 private final ReadWriteLock lock = new ReentrantReadWriteLock(/* fair */ true);79 private final GridModel model;80 private final Map<NodeId, Node> nodes;81 public LocalDistributor(82 Tracer tracer,83 EventBus bus,84 HttpClient.Factory clientFactory,85 SessionMap sessions,86 Secret registrationSecret) {87 super(tracer, clientFactory, new DefaultSlotSelector(), sessions, registrationSecret);88 this.tracer = Require.nonNull("Tracer", tracer);89 this.bus = Require.nonNull("Event bus", bus);90 this.clientFactory = Require.nonNull("HTTP client factory", clientFactory);91 this.sessions = Require.nonNull("Session map", sessions);92 this.model = new GridModel(bus, registrationSecret);93 this.nodes = new HashMap<>();94 this.registrationSecret = Require.nonNull("Registration secret", registrationSecret);95 bus.addListener(NodeStatusEvent.listener(this::register));96 bus.addListener(NodeStatusEvent.listener(model::refresh));97 bus.addListener(NodeDrainComplete.listener(this::remove));98 }99 public static Distributor create(Config config) {100 Tracer tracer = new LoggingOptions(config).getTracer();101 EventBus bus = new EventBusOptions(config).getEventBus();102 HttpClient.Factory clientFactory = new NetworkOptions(config).getHttpClientFactory(tracer);103 SessionMap sessions = new SessionMapOptions(config).getSessionMap();104 BaseServerOptions serverOptions = new BaseServerOptions(config);105 return new LocalDistributor(tracer, bus, clientFactory, sessions, serverOptions.getRegistrationSecret());106 }107 @Override108 public boolean isReady() {109 try {110 return ImmutableSet.of(bus, sessions).parallelStream()111 .map(HasReadyState::isReady)112 .reduce(true, Boolean::logicalAnd);113 } catch (RuntimeException e) {114 return false;115 }116 }117 private void register(NodeStatus status) {118 Require.nonNull("Node", status);119 Lock writeLock = lock.writeLock();120 writeLock.lock();121 try {122 if (nodes.containsKey(status.getId())) {123 return;124 }125 Set<Capabilities> capabilities = status.getSlots().stream()126 .map(Slot::getStereotype)127 .map(ImmutableCapabilities::copyOf)128 .collect(toImmutableSet());129 // A new node! Add this as a remote node, since we've not called add130 RemoteNode remoteNode = new RemoteNode(131 tracer,132 clientFactory,133 status.getId(),134 status.getUri(),135 registrationSecret,136 capabilities);137 add(remoteNode);138 } finally {139 writeLock.unlock();140 }141 }142 @Override143 public LocalDistributor add(Node node) {144 Require.nonNull("Node", node);145 LOG.info(String.format("Added node %s at %s.", node.getId(), node.getUri()));146 nodes.put(node.getId(), node);147 model.add(node.getStatus());148 // Extract the health check149 Runnable runnableHealthCheck = asRunnableHealthCheck(node);150 allChecks.put(node.getId(), runnableHealthCheck);151 hostChecker.submit(runnableHealthCheck, Duration.ofMinutes(5), Duration.ofSeconds(30));152 bus.fire(new NodeAddedEvent(node.getId()));153 return this;154 }155 private Runnable asRunnableHealthCheck(Node node) {156 HealthCheck healthCheck = node.getHealthCheck();157 NodeId id = node.getId();158 return () -> {159 HealthCheck.Result result;160 try {161 result = healthCheck.check();162 } catch (Exception e) {163 LOG.log(Level.WARNING, "Unable to process node " + id, e);164 result = new HealthCheck.Result(DOWN, "Unable to run healthcheck. Assuming down");165 }166 Lock writeLock = lock.writeLock();167 writeLock.lock();168 try {169 model.setAvailability(id, result.getAvailability());170 } finally {171 writeLock.unlock();172 }173 };174 }175 @Override176 public boolean drain(NodeId nodeId) {177 Node node = nodes.get(nodeId);178 if (node == null) {179 LOG.info("Asked to drain unregistered node " + nodeId);180 return false;181 }182 Lock writeLock = lock.writeLock();183 writeLock.lock();184 try {185 node.drain();186 model.setAvailability(nodeId, DRAINING);187 } finally {188 writeLock.unlock();189 }190 return node.isDraining();191 }192 public void remove(NodeId nodeId) {193 Lock writeLock = lock.writeLock();194 writeLock.lock();195 try {196 model.remove(nodeId);197 Runnable runnable = allChecks.remove(nodeId);198 if (runnable != null) {199 hostChecker.remove(runnable);200 }201 } finally {202 writeLock.unlock();203 bus.fire(new NodeRemovedEvent(nodeId));204 }205 }206 @Override207 public DistributorStatus getStatus() {208 Lock readLock = this.lock.readLock();209 readLock.lock();210 try {211 return new DistributorStatus(model.getSnapshot());212 } finally {213 readLock.unlock();214 }215 }216 @Beta217 public void refresh() {218 List<Runnable> allHealthChecks = new ArrayList<>();219 Lock readLock = this.lock.readLock();220 readLock.lock();221 try {222 allHealthChecks.addAll(allChecks.values());223 } finally {224 readLock.unlock();225 }226 allHealthChecks.parallelStream().forEach(Runnable::run);227 }228 @Override229 protected Set<NodeStatus> getAvailableNodes() {230 Lock readLock = this.lock.readLock();231 readLock.lock();232 try {233 return model.getSnapshot().stream()234 .filter(node -> !DOWN.equals(node.getAvailability()))235 .collect(toImmutableSet());236 } finally {237 readLock.unlock();238 }239 }240 @Override241 protected Supplier<CreateSessionResponse> reserve(SlotId slotId, CreateSessionRequest request) {242 Require.nonNull("Slot ID", slotId);243 Require.nonNull("New Session request", request);244 Lock writeLock = this.lock.writeLock();245 writeLock.lock();246 try {247 Node node = nodes.get(slotId.getOwningNodeId());248 if (node == null) {249 return () -> {250 throw new SessionNotCreatedException("Unable to find node");251 };252 }253 model.reserve(slotId);254 return () -> {255 Optional<CreateSessionResponse> response = node.newSession(request);256 if (!response.isPresent()) {...

Full Screen

Full Screen

Source:Host.java Github

copy

Full Screen

...45import static org.openqa.selenium.grid.data.Availability.DOWN;46import static org.openqa.selenium.grid.data.Availability.DRAINING;47import static org.openqa.selenium.grid.data.Availability.UP;48import static org.openqa.selenium.grid.data.SessionClosedEvent.SESSION_CLOSED;49import static org.openqa.selenium.grid.distributor.model.Slot.Status.ACTIVE;50import static org.openqa.selenium.grid.distributor.model.Slot.Status.AVAILABLE;51public class Host {52 private static final Logger LOG = Logger.getLogger("Selenium Host");53 private final Node node;54 private final NodeId nodeId;55 private final URI uri;56 private final Runnable performHealthCheck;57 // Used any time we need to read or modify the mutable state of this host58 private final ReadWriteLock lock = new ReentrantReadWriteLock(/* fair */ true);59 private Availability status;60 private Set<Slot> slots;61 private int maxSessionCount;62 public Host(EventBus bus, Node node) {63 this.node = Require.nonNull("Node", node);64 this.nodeId = node.getId();65 this.uri = node.getUri();66 this.status = DOWN;67 this.slots = ImmutableSet.of();68 HealthCheck healthCheck = node.getHealthCheck();69 this.performHealthCheck = () -> {70 HealthCheck.Result result = healthCheck.check();71 Availability current = result.isAlive() ? UP : DOWN;72 Availability previous = setHostStatus(current);73 //If the node has been set to maintenance mode, set the status here as draining74 if (node.isDraining() || previous == DRAINING) {75 // We want to continue to allow the node to drain.76 setHostStatus(DRAINING);77 return;78 }79 if (current != previous) {80 LOG.info(String.format(81 "Changing status of node %s from %s to %s. Reason: %s",82 node.getId(),83 previous,84 current,85 result.getMessage()));86 }87 };88 bus.addListener(SESSION_CLOSED, event -> {89 SessionId id = event.getData(SessionId.class);90 this.slots.forEach(slot -> slot.onEnd(id));91 });92 update(node.getStatus());93 }94 public void update(NodeStatus status) {95 Require.nonNull("Node status", status);96 Lock writeLock = lock.writeLock();97 writeLock.lock();98 try {99 this.slots = status.getSlots().stream()100 .map(slot -> new Slot(node, slot.getStereotype(), slot.getSession().isPresent() ? ACTIVE : AVAILABLE))101 .collect(toImmutableSet());102 // By definition, we can never have more sessions than we have slots available103 this.maxSessionCount = Math.min(this.slots.size(), status.getMaxSessionCount());104 } finally {105 writeLock.unlock();106 }107 }108 public NodeId getId() {109 return nodeId;110 }111 public DistributorStatus.NodeSummary asSummary() {112 Map<Capabilities, Integer> stereotypes = new HashMap<>();113 Map<Capabilities, Integer> used = new HashMap<>();114 Set<Session> activeSessions = new HashSet<>();115 slots.forEach(slot -> {116 stereotypes.compute(slot.getStereotype(), (key, curr) -> curr == null ? 1 : curr + 1);117 if (slot.getStatus() != AVAILABLE) {118 used.compute(slot.getStereotype(), (key, curr) -> curr == null ? 1 : curr + 1);119 activeSessions.add(slot.getCurrentSession());120 }121 });122 return new DistributorStatus.NodeSummary(123 nodeId,124 uri,125 getHostStatus(),126 maxSessionCount,127 stereotypes,128 used,129 activeSessions);130 }131 public Availability getHostStatus() {132 return status;133 }134 /**135 * @return The previous status of the node.136 */137 private Availability setHostStatus(Availability status) {138 Availability toReturn = this.status;139 this.status = Require.nonNull("Status", status);140 return toReturn;141 }142 /**143 * @return The previous status of the node if it not able to drain else returning draining status.144 */145 public Availability drainHost() {146 Availability prev = this.status;147 // Drain the node148 if (!node.isDraining()) {149 node.drain();150 }151 // For some reason, it is still not draining then do not update the host status152 if (!node.isDraining()) {153 return prev;154 } else {155 this.status = DRAINING;156 return DRAINING;157 }158 }159 /**160 * @return Whether or not the host has slots available for the requested capabilities.161 */162 public boolean hasCapacity(Capabilities caps) {163 Lock read = lock.readLock();164 read.lock();165 try {166 long count = slots.stream()167 .filter(slot -> slot.isSupporting(caps))168 .filter(slot -> slot.getStatus() == AVAILABLE)169 .count();170 return count > 0;171 } finally {172 read.unlock();173 }174 }175 public float getLoad() {176 Lock read = lock.readLock();177 read.lock();178 try {179 float inUse = slots.parallelStream()180 .filter(slot -> slot.getStatus() != AVAILABLE)181 .count();182 return (inUse / (float) maxSessionCount) * 100f;183 } finally {184 read.unlock();185 }186 }187 public long getLastSessionCreated() {188 Lock read = lock.readLock();189 read.lock();190 try {191 return slots.parallelStream()192 .mapToLong(Slot::getLastSessionCreated)193 .max()194 .orElse(0);195 } finally {196 read.unlock();197 }198 }199 public Supplier<CreateSessionResponse> reserve(CreateSessionRequest sessionRequest) {200 Require.nonNull("Session creation request", sessionRequest);201 Lock write = lock.writeLock();202 write.lock();203 try {204 Slot toReturn = slots.stream()205 .filter(slot -> slot.isSupporting(sessionRequest.getCapabilities()))206 .filter(slot -> slot.getStatus() == AVAILABLE)207 .findFirst()208 .orElseThrow(() -> new SessionNotCreatedException("Unable to reserve an instance"));209 return toReturn.onReserve(sessionRequest);210 } finally {211 write.unlock();212 }213 }214 public void runHealthCheck() {215 performHealthCheck.run();216 }217 @Override218 public int hashCode() {...

Full Screen

Full Screen

Source:SessionData.java Github

copy

Full Screen

...19import graphql.schema.DataFetcher;20import graphql.schema.DataFetchingEnvironment;21import org.openqa.selenium.grid.data.DistributorStatus;22import org.openqa.selenium.grid.data.NodeStatus;23import org.openqa.selenium.grid.data.Slot;24import org.openqa.selenium.grid.distributor.Distributor;25import org.openqa.selenium.internal.Require;26import java.util.Optional;27import java.util.Set;28import java.util.function.Supplier;29public class SessionData implements DataFetcher {30 private final Supplier<DistributorStatus> distributorStatus;31 public SessionData(Distributor distributor) {32 distributorStatus = Suppliers.memoize(Require.nonNull("Distributor", distributor)::getStatus);33 }34 @Override35 public Object get(DataFetchingEnvironment environment) {36 String sessionId = environment.getArgument("id");37 if (sessionId.isEmpty()) {38 throw new SessionNotFoundException("Session id is empty. A valid session id is required.");39 }40 Set<NodeStatus> nodeStatuses = distributorStatus.get().getNodes();41 SessionInSlot currentSession = findSession(sessionId, nodeStatuses);42 if (currentSession != null) {43 org.openqa.selenium.grid.data.Session session = currentSession.session;44 return new org.openqa.selenium.grid.graphql.Session(45 session.getId().toString(),46 session.getCapabilities(),47 session.getStartTime(),48 session.getUri(),49 currentSession.node.getId().toString(),50 currentSession.node.getUri(),51 currentSession.slot);52 } else {53 throw new SessionNotFoundException("No ongoing session found with the requested session id.",54 sessionId);55 }56 }57 private SessionInSlot findSession(String sessionId, Set<NodeStatus> nodeStatuses) {58 for (NodeStatus status : nodeStatuses) {59 for (Slot slot : status.getSlots()) {60 Optional<org.openqa.selenium.grid.data.Session> session = slot.getSession();61 if (session.isPresent() && sessionId.equals(session.get().getId().toString())) {62 return new SessionInSlot(session.get(), status, slot);63 }64 }65 }66 return null;67 }68 private static class SessionInSlot {69 private final org.openqa.selenium.grid.data.Session session;70 private final NodeStatus node;71 private final Slot slot;72 SessionInSlot(org.openqa.selenium.grid.data.Session session, NodeStatus node, Slot slot) {73 this.session = session;74 this.node = node;75 this.slot = slot;76 }77 }78}...

Full Screen

Full Screen

Source:Grid.java Github

copy

Full Screen

...19import com.google.common.collect.ImmutableList;20import org.openqa.selenium.Capabilities;21import org.openqa.selenium.grid.data.DistributorStatus;22import org.openqa.selenium.grid.data.NodeStatus;23import org.openqa.selenium.grid.data.Slot;24import org.openqa.selenium.grid.distributor.Distributor;25import org.openqa.selenium.internal.Require;26import java.net.URI;27import java.util.Collection;28import java.util.HashMap;29import java.util.HashSet;30import java.util.List;31import java.util.Map;32import java.util.Set;33import java.util.function.Supplier;34public class Grid {35 private final URI uri;36 private final Supplier<DistributorStatus> distributorStatus;37 public Grid(Distributor distributor, URI uri) {38 Require.nonNull("Distributor", distributor);39 this.uri = Require.nonNull("Grid's public URI", uri);40 this.distributorStatus = Suppliers.memoize(distributor::getStatus);41 }42 public URI getUri() {43 return uri;44 }45 public List<Node> getNodes() {46 ImmutableList.Builder<Node> toReturn = ImmutableList.builder();47 for (NodeStatus status : distributorStatus.get().getNodes()) {48 Map<Capabilities, Integer> capabilities = new HashMap<>();49 Set<org.openqa.selenium.grid.data.Session> sessions = new HashSet<>();50 for (Slot slot : status.getSlots()) {51 slot.getSession().ifPresent(sessions::add);52 int count = capabilities.getOrDefault(slot.getStereotype(), 0);53 count++;54 capabilities.put(slot.getStereotype(), count);55 }56 toReturn.add(new Node(57 status.getId(),58 status.getUri(),59 status.getAvailability(),60 status.getMaxSessionCount(),61 capabilities,62 sessions));63 }64 return toReturn.build();65 }66 public int getSessionCount() {67 return distributorStatus.get().getNodes().stream()68 .map(NodeStatus::getSlots)69 .flatMap(Collection::stream)70 .filter(slot -> slot.getSession().isPresent())71 .mapToInt(slot -> 1)72 .sum();73 }74 public int getTotalSlots() {75 return distributorStatus.get().getNodes().stream()76 .mapToInt(status -> {77 int slotCount = status.getSlots().size();78 return Math.min(status.getMaxSessionCount(), slotCount);79 })80 .sum();81 }82 public int getUsedSlots() {83 return getSessionCount();84 }85}...

Full Screen

Full Screen

Slot

Using AI Code Generation

copy

Full Screen

1System.out.println(slot);2System.out.println(slot);3System.out.println(slot);4System.out.println(slot);5System.out.println(slot);6System.out.println(slot);7System.out.println(slot);8System.out.println(slot);9System.out.println(slot);10System.out.println(slot);

Full Screen

Full Screen
copy
1OkHttpClient client = new OkHttpClient();2
Full Screen
copy
1String html = new JdkRequest("http://www.google.com").fetch().body();2
Full Screen
copy
1if(object == null){2 //you called my method badly!3
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.

Test Your Web Or Mobile Apps On 3000+ Browsers

Signup for free

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful