diff --git a/java/server/src/org/openqa/selenium/grid/node/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/node/BUILD.bazel index 20af4ac4b8cb5..0e96e57d5ec14 100644 --- a/java/server/src/org/openqa/selenium/grid/node/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/node/BUILD.bazel @@ -21,6 +21,7 @@ java_library( "//java/server/src/org/openqa/selenium/grid/security", "//java/server/src/org/openqa/selenium/grid/web", "//java/server/src/org/openqa/selenium/status", + "//java/server/src/org/openqa/selenium/remote/server/jmx", artifact("com.google.guava:guava"), ], ) diff --git a/java/server/src/org/openqa/selenium/grid/node/local/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/node/local/BUILD.bazel index b974f9e37a08f..68b3944270c13 100644 --- a/java/server/src/org/openqa/selenium/grid/node/local/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/node/local/BUILD.bazel @@ -25,6 +25,7 @@ java_library( "//java/server/src/org/openqa/selenium/grid/node/config", "//java/server/src/org/openqa/selenium/grid/security", "//java/server/src/org/openqa/selenium/grid/server", + "//java/server/src/org/openqa/selenium/remote/server/jmx", artifact("com.google.guava:guava"), ], ) diff --git a/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java b/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java index bdf5fab09ce3f..9f3f6c5a23d5c 100644 --- a/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java +++ b/java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java @@ -31,6 +31,7 @@ import org.openqa.selenium.WebDriverException; import org.openqa.selenium.concurrent.Regularly; import org.openqa.selenium.events.EventBus; +import org.openqa.selenium.grid.data.Availability; import org.openqa.selenium.grid.data.CreateSessionRequest; import org.openqa.selenium.grid.data.CreateSessionResponse; import org.openqa.selenium.grid.data.NodeDrainComplete; @@ -53,6 +54,9 @@ import org.openqa.selenium.remote.SessionId; import org.openqa.selenium.remote.http.HttpRequest; import org.openqa.selenium.remote.http.HttpResponse; +import org.openqa.selenium.remote.server.jmx.JMXHelper; +import org.openqa.selenium.remote.server.jmx.ManagedAttribute; +import org.openqa.selenium.remote.server.jmx.ManagedService; import org.openqa.selenium.remote.tracing.AttributeKey; import org.openqa.selenium.remote.tracing.EventAttribute; import org.openqa.selenium.remote.tracing.EventAttributeValue; @@ -91,6 +95,8 @@ import static org.openqa.selenium.remote.http.Contents.string; import static org.openqa.selenium.remote.http.HttpMethod.DELETE; +@ManagedService(objectName = "org.seleniumhq.grid:type=Node,name=LocalNode", + description = "Node running the webdriver sessions.") public class LocalNode extends Node { private static final Json JSON = new Json(); @@ -173,6 +179,8 @@ private LocalNode( } } })); + + new JMXHelper().register(this); } @Override @@ -181,11 +189,53 @@ public boolean isReady() { } @VisibleForTesting + @ManagedAttribute(name = "CurrentSessions") public int getCurrentSessionCount() { // It seems wildly unlikely we'll overflow an int return Math.toIntExact(currentSessions.size()); } + @ManagedAttribute(name = "MaxSessions") + public int getMaxSessionCount() { + return maxSessionCount; + } + + @ManagedAttribute(name = "Status") + public Availability getAvailability() { + return isDraining() ? DRAINING : UP; + } + + @ManagedAttribute(name = "TotalSlots") + public int getTotalSlots() { + return factories.size(); + } + + @ManagedAttribute(name = "UsedSlots") + public long getUsedSlots() { + return factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count(); + } + + @ManagedAttribute(name = "Load") + public float getLoad() { + long inUse = factories.stream().filter(sessionSlot -> !sessionSlot.isAvailable()).count(); + return inUse / (float) maxSessionCount * 100f; + } + + @ManagedAttribute(name = "RemoteNodeUri") + public URI getExternalUri() { + return this.getUri(); + } + + @ManagedAttribute(name = "GridUri") + public URI getGridUri() { + return this.gridUri; + } + + @ManagedAttribute(name = "NodeId") + public String getNodeId() { + return getId().toString(); + } + @Override public boolean isSupporting(Capabilities capabilities) { return factories.parallelStream().anyMatch(factory -> factory.test(capabilities)); diff --git a/java/server/src/org/openqa/selenium/grid/server/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/server/BUILD.bazel index 08ad4b6f100c6..d7e265ee401d5 100644 --- a/java/server/src/org/openqa/selenium/grid/server/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/server/BUILD.bazel @@ -20,6 +20,7 @@ java_library( "//java/server/src/org/openqa/selenium/grid/component", "//java/server/src/org/openqa/selenium/grid/config", "//java/server/src/org/openqa/selenium/grid/web", + "//java/server/src/org/openqa/selenium/remote/server/jmx", artifact("com.beust:jcommander"), artifact("com.google.guava:guava"), artifact("javax.servlet:javax.servlet-api"), diff --git a/java/server/src/org/openqa/selenium/grid/server/BaseServerOptions.java b/java/server/src/org/openqa/selenium/grid/server/BaseServerOptions.java index 597f51befde57..2dc48213aa4c0 100644 --- a/java/server/src/org/openqa/selenium/grid/server/BaseServerOptions.java +++ b/java/server/src/org/openqa/selenium/grid/server/BaseServerOptions.java @@ -23,6 +23,9 @@ import org.openqa.selenium.net.HostIdentifier; import org.openqa.selenium.net.NetworkUtils; import org.openqa.selenium.net.PortProber; +import org.openqa.selenium.remote.server.jmx.JMXHelper; +import org.openqa.selenium.remote.server.jmx.ManagedAttribute; +import org.openqa.selenium.remote.server.jmx.ManagedService; import java.io.File; import java.net.URI; @@ -30,6 +33,8 @@ import java.util.Optional; import java.util.logging.Logger; +@ManagedService(objectName = "org.seleniumhq.grid:type=Config,name=BaseServerConfig", + description = "Server config") public class BaseServerOptions { private static final String SERVER_SECTION = "server"; @@ -40,12 +45,14 @@ public class BaseServerOptions { public BaseServerOptions(Config config) { this.config = config; + new JMXHelper().register(this); } public Optional getHostname() { return config.get(SERVER_SECTION, "hostname"); } + @ManagedAttribute(name = "Port") public int getPort() { if (port == -1) { int newPort = config.getInt(SERVER_SECTION, "port") @@ -61,6 +68,7 @@ public int getPort() { return port; } + @ManagedAttribute(name = "MaxServerThreads") public int getMaxServerThreads() { int count = config.getInt(SERVER_SECTION, "max-threads") .orElse(200); @@ -72,6 +80,7 @@ public int getMaxServerThreads() { return count; } + @ManagedAttribute(name = "Uri") public URI getExternalUri() { // Assume the host given is addressable if it's been set String host = getHostname() diff --git a/java/server/src/org/openqa/selenium/grid/sessionqueue/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/sessionqueue/BUILD.bazel index bd1fae1bee621..350697a95a7ac 100644 --- a/java/server/src/org/openqa/selenium/grid/sessionqueue/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/sessionqueue/BUILD.bazel @@ -20,6 +20,7 @@ java_library( "//java/server/src/org/openqa/selenium/grid/data", "//java/server/src/org/openqa/selenium/grid/log", "//java/server/src/org/openqa/selenium/status", + "//java/server/src/org/openqa/selenium/remote/server/jmx", artifact("com.google.guava:guava"), ], ) diff --git a/java/server/src/org/openqa/selenium/grid/sessionqueue/config/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/sessionqueue/config/BUILD.bazel index 56149b0d209d2..248569a185c7f 100644 --- a/java/server/src/org/openqa/selenium/grid/sessionqueue/config/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/sessionqueue/config/BUILD.bazel @@ -6,11 +6,13 @@ java_library( srcs = glob(["*.java"]), visibility = [ "//java/server/src/org/openqa/selenium/grid:__subpackages__", + "//java/server/test/org/openqa/selenium/grid:__subpackages__", ], deps = [ "//java:auto-service", "//java/server/src/org/openqa/selenium/grid/config", "//java/server/src/org/openqa/selenium/grid/sessionqueue", + "//java/server/src/org/openqa/selenium/remote/server/jmx", artifact("com.beust:jcommander"), artifact("io.opentelemetry:opentelemetry-api"), ], diff --git a/java/server/src/org/openqa/selenium/grid/sessionqueue/config/NewSessionQueueOptions.java b/java/server/src/org/openqa/selenium/grid/sessionqueue/config/NewSessionQueueOptions.java index 1a43773940881..52b4434996166 100644 --- a/java/server/src/org/openqa/selenium/grid/sessionqueue/config/NewSessionQueueOptions.java +++ b/java/server/src/org/openqa/selenium/grid/sessionqueue/config/NewSessionQueueOptions.java @@ -19,9 +19,14 @@ import org.openqa.selenium.grid.config.Config; import org.openqa.selenium.grid.sessionqueue.NewSessionQueue; +import org.openqa.selenium.remote.server.jmx.JMXHelper; +import org.openqa.selenium.remote.server.jmx.ManagedAttribute; +import org.openqa.selenium.remote.server.jmx.ManagedService; import java.time.Duration; +@ManagedService(objectName = "org.seleniumhq.grid:type=Config,name=NewSessionQueueConfig", + description = "New session queue config") public class NewSessionQueueOptions { private static final String SESSIONS_QUEUE_SECTION = "sessionqueue"; @@ -35,10 +40,11 @@ public class NewSessionQueueOptions { public NewSessionQueueOptions(Config config) { this.config = config; + new JMXHelper().register(this); } public Duration getSessionRequestTimeout() { - int timeout = config.getInt(SESSIONS_QUEUE_SECTION, "session-request-timeout") + long timeout = config.getInt(SESSIONS_QUEUE_SECTION, "session-request-timeout") .orElse(DEFAULT_REQUEST_TIMEOUT); if (timeout <= 0) { @@ -48,7 +54,7 @@ public Duration getSessionRequestTimeout() { } public Duration getSessionRequestRetryInterval() { - int interval = config.getInt(SESSIONS_QUEUE_SECTION, "session-retry-interval") + long interval = config.getInt(SESSIONS_QUEUE_SECTION, "session-retry-interval") .orElse(DEFAULT_RETRY_INTERVAL); if (interval <= 0) { @@ -57,6 +63,16 @@ public Duration getSessionRequestRetryInterval() { return Duration.ofSeconds(interval); } + @ManagedAttribute(name = "RequestTimeoutSeconds") + public long getRequestTimeoutSeconds() { + return getSessionRequestTimeout().getSeconds(); + } + + @ManagedAttribute(name = "RetryIntervalSeconds") + public long getRetryIntervalSeconds() { + return getSessionRequestRetryInterval().getSeconds(); + } + public NewSessionQueue getSessionQueue() { return config .getClass(SESSIONS_QUEUE_SECTION, "implementation", NewSessionQueue.class, diff --git a/java/server/src/org/openqa/selenium/grid/sessionqueue/local/BUILD.bazel b/java/server/src/org/openqa/selenium/grid/sessionqueue/local/BUILD.bazel index 10585de4ee546..54c8b8b39c272 100644 --- a/java/server/src/org/openqa/selenium/grid/sessionqueue/local/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/grid/sessionqueue/local/BUILD.bazel @@ -18,6 +18,7 @@ java_library( "//java/server/src/org/openqa/selenium/grid/server", "//java/server/src/org/openqa/selenium/grid/sessionqueue", "//java/server/src/org/openqa/selenium/grid/sessionqueue/config", + "//java/server/src/org/openqa/selenium/remote/server/jmx", artifact("com.google.guava:guava"), ], ) diff --git a/java/server/src/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueue.java b/java/server/src/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueue.java index 3218f4b90ffb1..ef11d3a4d2500 100644 --- a/java/server/src/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueue.java +++ b/java/server/src/org/openqa/selenium/grid/sessionqueue/local/LocalNewSessionQueue.java @@ -29,6 +29,11 @@ import org.openqa.selenium.grid.sessionqueue.config.NewSessionQueueOptions; import org.openqa.selenium.internal.Require; import org.openqa.selenium.remote.http.HttpRequest; + +import org.openqa.selenium.remote.server.jmx.JMXHelper; +import org.openqa.selenium.remote.server.jmx.ManagedAttribute; +import org.openqa.selenium.remote.server.jmx.ManagedService; + import org.openqa.selenium.remote.tracing.AttributeKey; import org.openqa.selenium.remote.tracing.EventAttribute; import org.openqa.selenium.remote.tracing.EventAttributeValue; @@ -50,6 +55,8 @@ import java.util.logging.Level; import java.util.logging.Logger; +@ManagedService(objectName = "org.seleniumhq.grid:type=SessionQueue,name=LocalSessionQueue", + description = "New session queue") public class LocalNewSessionQueue extends NewSessionQueue { private static final Logger LOG = Logger.getLogger(LocalNewSessionQueue.class.getName()); @@ -65,6 +72,7 @@ public LocalNewSessionQueue(Tracer tracer, EventBus bus, Duration retryInterval, super(tracer, retryInterval, requestTimeout); this.bus = Require.nonNull("Event bus", bus); Runtime.getRuntime().addShutdownHook(shutdownHook); + new JMXHelper().register(this); } public static NewSessionQueue create(Config config) { @@ -80,6 +88,17 @@ public boolean isReady() { return bus.isReady(); } + @ManagedAttribute(name = "NewSessionQueueSize") + public int getQueueSize() { + Lock readLock = lock.readLock(); + readLock.lock(); + try { + return sessionRequests.size(); + } finally { + readLock.unlock(); + } + } + @Override public boolean offerLast(HttpRequest request, RequestId requestId) { Require.nonNull("New Session request", request); diff --git a/java/server/src/org/openqa/selenium/remote/server/jmx/BUILD.bazel b/java/server/src/org/openqa/selenium/remote/server/jmx/BUILD.bazel index 5e6f9cd1e8d38..13009f6bb90d3 100644 --- a/java/server/src/org/openqa/selenium/remote/server/jmx/BUILD.bazel +++ b/java/server/src/org/openqa/selenium/remote/server/jmx/BUILD.bazel @@ -5,5 +5,7 @@ java_library( srcs = glob(["*.java"]), visibility = [ "//java/server/src/org/openqa/selenium/grid/session:__pkg__", + "//java/server/src/org/openqa/selenium/grid:__subpackages__", + "//java/server/test/org/openqa/selenium/grid:__subpackages__", ], ) diff --git a/java/server/test/org/openqa/selenium/grid/router/BUILD.bazel b/java/server/test/org/openqa/selenium/grid/router/BUILD.bazel index 2170a09b847a3..6c46226f50dee 100644 --- a/java/server/test/org/openqa/selenium/grid/router/BUILD.bazel +++ b/java/server/test/org/openqa/selenium/grid/router/BUILD.bazel @@ -70,12 +70,14 @@ java_test_suite( "//java/server/src/org/openqa/selenium/grid/sessionmap/httpd", "//java/server/src/org/openqa/selenium/grid/sessionmap/local", "//java/server/src/org/openqa/selenium/grid/sessionmap/remote", + "//java/server/src/org/openqa/selenium/grid/sessionqueue/config", "//java/server/src/org/openqa/selenium/grid/sessionqueue", "//java/server/src/org/openqa/selenium/grid/sessionqueue/httpd", "//java/server/src/org/openqa/selenium/grid/sessionqueue/local", "//java/server/src/org/openqa/selenium/grid/sessionqueue/remote", "//java/server/src/org/openqa/selenium/grid/web", "//java/server/src/org/openqa/selenium/netty/server", + "//java/server/src/org/openqa/selenium/remote/server/jmx", "//java/server/test/org/openqa/selenium/grid/testing", artifact("com.google.guava:guava"), artifact("io.opentelemetry:opentelemetry-api"), diff --git a/java/server/test/org/openqa/selenium/grid/router/JmxTest.java b/java/server/test/org/openqa/selenium/grid/router/JmxTest.java new file mode 100644 index 0000000000000..0ee79754ba5f5 --- /dev/null +++ b/java/server/test/org/openqa/selenium/grid/router/JmxTest.java @@ -0,0 +1,222 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.openqa.selenium.grid.router; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; + +import com.google.common.collect.ImmutableMap; + +import java.lang.management.ManagementFactory; +import java.net.URI; +import java.net.URISyntaxException; +import java.time.Duration; +import java.time.Instant; +import javax.management.AttributeNotFoundException; +import javax.management.InstanceNotFoundException; +import javax.management.IntrospectionException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.management.ReflectionException; + +import org.junit.Test; +import org.openqa.selenium.Capabilities; +import org.openqa.selenium.ImmutableCapabilities; +import org.openqa.selenium.events.EventBus; +import org.openqa.selenium.events.local.GuavaEventBus; +import org.openqa.selenium.grid.config.MapConfig; +import org.openqa.selenium.grid.data.Session; +import org.openqa.selenium.grid.node.local.LocalNode; +import org.openqa.selenium.grid.security.Secret; +import org.openqa.selenium.grid.server.BaseServerOptions; +import org.openqa.selenium.grid.sessionqueue.config.NewSessionQueueOptions; +import org.openqa.selenium.grid.sessionqueue.local.LocalNewSessionQueue; +import org.openqa.selenium.grid.testing.TestSessionFactory; +import org.openqa.selenium.net.PortProber; +import org.openqa.selenium.remote.server.jmx.JMXHelper; +import org.openqa.selenium.remote.tracing.DefaultTestTracer; +import org.openqa.selenium.remote.tracing.Tracer; + +public class JmxTest { + + private final Capabilities CAPS = new ImmutableCapabilities("browserName", "cheese"); + private final MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); + + @Test + public void shouldBeAbleToRegisterBaseServerConfig() { + try { + ObjectName name = new ObjectName("org.seleniumhq.grid:type=Config,name=BaseServerConfig"); + new JMXHelper().unregister(name); + + BaseServerOptions baseServerOptions = new BaseServerOptions( + new MapConfig( + ImmutableMap.of("server", ImmutableMap.of("port", PortProber.findFreePort())))); + + MBeanInfo info = beanServer.getMBeanInfo(name); + assertThat(info).isNotNull(); + + MBeanAttributeInfo[] attributeInfoArray = info.getAttributes(); + assertThat(attributeInfoArray).hasSize(3); + + String uriValue = (String) beanServer.getAttribute(name, "Uri"); + assertThat(uriValue).isEqualTo(baseServerOptions.getExternalUri().toString()); + + } catch (InstanceNotFoundException | IntrospectionException | ReflectionException + | MalformedObjectNameException e) { + fail("Could not find the registered MBean"); + } catch (MBeanException e) { + fail("MBeanServer exception"); + } catch (AttributeNotFoundException e) { + fail("Could not find the registered MBean's attribute"); + } + } + + @Test + public void shouldBeAbleToRegisterNode() throws URISyntaxException { + try { + URI nodeUri = new URI("http://example.com:1234"); + ObjectName name = new ObjectName("org.seleniumhq.grid:type=Node,name=LocalNode"); + new JMXHelper().unregister(name); + + Tracer tracer = DefaultTestTracer.createTracer(); + EventBus bus = new GuavaEventBus(); + + Secret secret = new Secret("cheese"); + + LocalNode localNode = LocalNode.builder(tracer, bus, nodeUri, nodeUri, secret) + .add(CAPS, new TestSessionFactory((id, caps) -> new Session( + id, + nodeUri, + new ImmutableCapabilities(), + caps, + Instant.now()))).build(); + + assertThat(localNode).isNotNull(); + + MBeanInfo info = beanServer.getMBeanInfo(name); + assertThat(info).isNotNull(); + + MBeanAttributeInfo[] attributeInfo = info.getAttributes(); + assertThat(attributeInfo).hasSize(9); + + String currentSessions = (String) beanServer.getAttribute(name, "CurrentSessions"); + assertThat(Integer.parseInt(currentSessions)).isZero(); + + String maxSessions = (String) beanServer.getAttribute(name, "MaxSessions"); + assertThat(Integer.parseInt(maxSessions)).isEqualTo(1); + + String status = (String) beanServer.getAttribute(name, "Status"); + assertThat(status).isEqualTo("UP"); + + String totalSlots = (String) beanServer.getAttribute(name, "TotalSlots"); + assertThat(Integer.parseInt(totalSlots)).isEqualTo(1); + + String usedSlots = (String) beanServer.getAttribute(name, "UsedSlots"); + assertThat(Integer.parseInt(usedSlots)).isZero(); + + String load = (String) beanServer.getAttribute(name, "Load"); + assertThat(Float.parseFloat(load)).isEqualTo(0.0f); + + String remoteNodeUri = (String) beanServer.getAttribute(name, "RemoteNodeUri"); + assertThat(remoteNodeUri).isEqualTo(nodeUri.toString()); + + String gridUri = (String) beanServer.getAttribute(name, "GridUri"); + assertThat(gridUri).isEqualTo(nodeUri.toString()); + + } catch (InstanceNotFoundException | IntrospectionException | ReflectionException + | MalformedObjectNameException e) { + fail("Could not find the registered MBean"); + } catch (MBeanException e) { + fail("MBeanServer exception"); + } catch (AttributeNotFoundException e) { + fail("Could not find the registered MBean's attribute"); + } + } + + @Test + public void shouldBeAbleToRegisterSessionQueuerServerConfig() { + try { + ObjectName name = new ObjectName( + "org.seleniumhq.grid:type=Config,name=NewSessionQueueConfig"); + + new JMXHelper().unregister(name); + + NewSessionQueueOptions queueOptions = + new NewSessionQueueOptions(new MapConfig(ImmutableMap.of())); + MBeanInfo info = beanServer.getMBeanInfo(name); + assertThat(info).isNotNull(); + + MBeanAttributeInfo[] attributeInfoArray = info.getAttributes(); + assertThat(attributeInfoArray).hasSize(2); + + String requestTimeout = (String) beanServer.getAttribute(name, "RequestTimeoutSeconds"); + assertThat(Long.parseLong(requestTimeout)).isEqualTo(queueOptions.getRequestTimeoutSeconds()); + + String retryInterval = (String) beanServer.getAttribute(name, "RetryIntervalSeconds"); + assertThat(Long.parseLong(retryInterval)).isEqualTo(queueOptions.getRetryIntervalSeconds()); + } catch (InstanceNotFoundException | IntrospectionException | ReflectionException + | MalformedObjectNameException e) { + fail("Could not find the registered MBean"); + } catch (MBeanException e) { + fail("MBeanServer exception"); + } catch (AttributeNotFoundException e) { + fail("Could not find the registered MBean's attribute"); + } + } + + @Test + public void shouldBeAbleToRegisterSessionQueue() { + try { + ObjectName name = new ObjectName("org.seleniumhq.grid:type=SessionQueue," + + "name=LocalSessionQueue"); + + new JMXHelper().unregister(name); + + Tracer tracer = DefaultTestTracer.createTracer(); + EventBus bus = new GuavaEventBus(); + + LocalNewSessionQueue localNewSessionQueue = new LocalNewSessionQueue( + tracer, + bus, + Duration.ofSeconds(2), + Duration.ofSeconds(2)); + + assertThat(localNewSessionQueue).isNotNull(); + MBeanInfo info = beanServer.getMBeanInfo(name); + assertThat(info).isNotNull(); + + MBeanAttributeInfo[] attributeInfoArray = info.getAttributes(); + assertThat(attributeInfoArray).hasSize(1); + + String size = (String) beanServer.getAttribute(name, "NewSessionQueueSize"); + assertThat(Integer.parseInt(size)).isZero(); + } catch (InstanceNotFoundException | IntrospectionException | ReflectionException + | MalformedObjectNameException e) { + fail("Could not find the registered MBean"); + } catch (MBeanException e) { + fail("MBeanServer exception"); + } catch (AttributeNotFoundException e) { + fail("Could not find the registered MBean's attribute"); + } + } +} +