This is an automated email from the ASF dual-hosted git repository. irakov pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new d45458b IGNITE-12628 Add tests for jmx metrics return types - Fixes #7369. d45458b is described below commit d45458b51a7ef7fa6fc211d4127877ab17e9a8a1 Author: vmalin <vmalinovs...@gridgain.com> AuthorDate: Tue Feb 18 18:33:37 2020 +0300 IGNITE-12628 Add tests for jmx metrics return types - Fixes #7369. Signed-off-by: Ivan Rakov <ira...@apache.org> --- .../ignite/internal/GridJobStealingSelfTest.java | 14 +++ .../org/apache/ignite/internal/GridMBeansTest.java | 34 ++++- .../apache/ignite/internal/GridMbeansMiscTest.java | 117 ++++++++++++++++++ .../checkpoint/GridCheckpointTaskSelfTest.java | 8 ++ .../cache/eviction/EvictionAbstractTest.java | 18 +++ .../junits/common/GridCommonAbstractTest.java | 137 +++++++++++++++++++++ .../ignite/testsuites/IgniteBasicTestSuite.java | 2 + .../zk/internal/ZookeeperDiscoveryMiscTest.java | 15 +++ 8 files changed, 343 insertions(+), 2 deletions(-) diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridJobStealingSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridJobStealingSelfTest.java index 1d01282..26dcfa6 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/GridJobStealingSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/GridJobStealingSelfTest.java @@ -51,6 +51,7 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.testframework.junits.common.GridCommonTest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.junit.Ignore; import org.junit.Test; /** @@ -301,6 +302,19 @@ public class GridJobStealingSelfTest extends GridCommonAbstractTest { ret.get(ignite3.cluster().localNode().id()); } + /** + * @throws Exception If fatiled. + */ + @Ignore("https://issues.apache.org/jira/browse/IGNITE-12629") + @Test + public void testJobStealingMbeanValidity() throws Exception { + String[] beansToValidate = new String[] { + "org.apache.ignite.spi.collision.jobstealing.JobStealingCollisionSpi$JobStealingCollisionSpiMBeanImpl", + "org.apache.ignite.spi.failover.jobstealing.JobStealingFailoverSpi$JobStealingFailoverSpiMBeanImpl"}; + + validateMbeans(ignite1, beansToValidate); + } + /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridMBeansTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridMBeansTest.java index db82643..5bbbbe3 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/GridMBeansTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/GridMBeansTest.java @@ -17,12 +17,12 @@ package org.apache.ignite.internal; +import javax.management.ObjectName; import org.apache.ignite.configuration.ExecutorConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.internal.util.typedef.G; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; - -import javax.management.ObjectName; import org.junit.Test; /** @@ -86,4 +86,34 @@ public class GridMBeansTest extends GridCommonAbstractTest { assertEquals(expAttributeVal, attributeVal); } + + /** + * @throws Exception If failed to validate methods. + */ + @Test + public void testBeansClasses() throws Exception { + String[] clsNames = new String[]{"org.apache.ignite.internal.ClusterLocalNodeMetricsMXBeanImpl", + "org.apache.ignite.internal.ClusterMetricsMXBeanImpl", + "org.apache.ignite.internal.IgniteKernal", + "org.apache.ignite.internal.IgnitionMXBeanAdapter", + "org.apache.ignite.internal.StripedExecutorMXBeanAdapter", + "org.apache.ignite.internal.ThreadPoolMXBeanAdapter", + "org.apache.ignite.internal.TransactionMetricsMxBeanImpl", + "org.apache.ignite.internal.TransactionsMXBeanImpl", + "org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsMXBeanImpl", + "org.apache.ignite.internal.processors.cache.persistence.DataStorageMXBeanImpl", + "org.apache.ignite.internal.processors.cache.persistence.diagnostic.pagelocktracker.PageLockTrackerMXBeanImpl", + "org.apache.ignite.internal.processors.cluster.BaselineAutoAdjustMXBeanImpl", + "org.apache.ignite.internal.processors.odbc.ClientListenerProcessor$ClientProcessorMXBeanImpl", + "org.apache.ignite.internal.worker.FailureHandlingMxBeanImpl", + "org.apache.ignite.spi.checkpoint.sharedfs.SharedFsCheckpointSpi$SharedFsCheckpointSpiMBeanImpl", + "org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi$TcpCommunicationSpiMBeanImpl", + "org.apache.ignite.spi.deployment.local.LocalDeploymentSpi$LocalDeploymentSpiMBeanImpl", + "org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi$TcpDiscoverySpiMBeanImpl", + "org.apache.ignite.spi.eventstorage.memory.MemoryEventStorageSpi$MemoryEventStorageSpiMBeanImpl", + "org.apache.ignite.spi.failover.always.AlwaysFailoverSpi$AlwaysFailoverSpiMBeanImpl", + "org.apache.ignite.spi.loadbalancing.roundrobin.RoundRobinLoadBalancingSpi$RoundRobinLoadBalancingSpiMBeanImpl"}; + + validateMbeans(G.allGrids().get(0), clsNames); + } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridMbeansMiscTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridMbeansMiscTest.java new file mode 100644 index 0000000..d4b20c7 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/GridMbeansMiscTest.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.ignite.internal; + +import org.apache.ignite.Ignite; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.spi.checkpoint.CheckpointSpi; +import org.apache.ignite.spi.checkpoint.sharedfs.SharedFsCheckpointSpi; +import org.apache.ignite.spi.collision.CollisionSpi; +import org.apache.ignite.spi.collision.fifoqueue.FifoQueueCollisionSpi; +import org.apache.ignite.spi.collision.priorityqueue.PriorityQueueCollisionSpi; +import org.apache.ignite.spi.deployment.DeploymentSpi; +import org.apache.ignite.spi.deployment.local.LocalDeploymentSpi; +import org.apache.ignite.spi.loadbalancing.LoadBalancingSpi; +import org.apache.ignite.spi.loadbalancing.adaptive.AdaptiveLoadBalancingSpi; +import org.apache.ignite.spi.loadbalancing.weightedrandom.WeightedRandomLoadBalancingSpi; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +/** + * Checks mbeans validity for miscelenious spis. + */ +public class GridMbeansMiscTest extends GridCommonAbstractTest { + /** */ + private CollisionSpi collisionSpi; + + /** */ + private LoadBalancingSpi loadBalancingSpi; + + /** */ + private DeploymentSpi deploymentSpi; + + /** */ + private CheckpointSpi checkpointSpi; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + if (collisionSpi != null) + cfg.setCollisionSpi(collisionSpi); + + if (loadBalancingSpi != null) + cfg.setLoadBalancingSpi(loadBalancingSpi); + + if (deploymentSpi != null) + cfg.setDeploymentSpi(deploymentSpi); + + if (checkpointSpi != null) + cfg.setCheckpointSpi(checkpointSpi); + + return cfg; + } + + /** + * @throws Exception If failed. + */ + @Test + public void testMbeansSet1() throws Exception { + collisionSpi = new FifoQueueCollisionSpi(); + loadBalancingSpi = new WeightedRandomLoadBalancingSpi(); + deploymentSpi = new LocalDeploymentSpi(); + checkpointSpi = new SharedFsCheckpointSpi(); + + String[] beansToValidate = new String[] { + "org.apache.ignite.spi.collision.fifoqueue.FifoQueueCollisionSpi$FifoQueueCollisionSpiMBeanImpl", + "org.apache.ignite.spi.loadbalancing.weightedrandom.WeightedRandomLoadBalancingSpi$WeightedRandomLoadBalancingSpiMBeanImpl", + "org.apache.ignite.spi.deployment.local.LocalDeploymentSpi$LocalDeploymentSpiMBeanImpl", + "org.apache.ignite.spi.checkpoint.sharedfs.SharedFsCheckpointSpi$SharedFsCheckpointSpiMBeanImpl" + }; + + doTest(beansToValidate); + } + + /** + * @throws Exception If failed. + */ + @Test + public void testMbeansSet2() throws Exception { + collisionSpi = new PriorityQueueCollisionSpi(); + loadBalancingSpi = new AdaptiveLoadBalancingSpi(); + + String[] beansToValidate = new String[] { + "org.apache.ignite.spi.collision.priorityqueue.PriorityQueueCollisionSpi$PriorityQueueCollisionSpiMBeanImpl", + "org.apache.ignite.spi.loadbalancing.adaptive.AdaptiveLoadBalancingSpi$AdaptiveLoadBalancingSpiMBeanImpl" + }; + + doTest(beansToValidate); + } + + /** */ + private void doTest(String[] beansToValidate) throws Exception { + try { + Ignite ignite = startGrid(); + + validateMbeans(ignite, beansToValidate); + } + finally { + stopAllGrids(); + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointTaskSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointTaskSelfTest.java index a9db0ae..2fe7683 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointTaskSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/managers/checkpoint/GridCheckpointTaskSelfTest.java @@ -119,6 +119,14 @@ public class GridCheckpointTaskSelfTest extends GridCommonAbstractTest { } /** + * @throws Exception If failed. + */ + @Test + public void testCacheCheckpointSpiMbeanValidity() throws Exception { + validateMbeans(grid(1), "org.apache.ignite.spi.checkpoint.cache.CacheCheckpointSpi$CacheCheckpointSpiMBeanImpl"); + } + + /** * Failover test task. */ @ComputeTaskSessionFullSupport diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/EvictionAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/EvictionAbstractTest.java index bcc0799..6191f4d 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/EvictionAbstractTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/eviction/EvictionAbstractTest.java @@ -736,6 +736,24 @@ public abstract class EvictionAbstractTest<T extends EvictionPolicy<?, ?>> } /** + * @throws Exception if failed. + */ + @Test + public void testEvictionPolicyMbeanValidity() throws Exception { + try { + Ignite ignite = startGrids(2); + + //Instantiate policy object to know exact class. + EvictionPolicy plc = createPolicy(0); + + validateMbeans(ignite, plc.getClass().getName()); + } + finally { + stopAllGrids(); + } + } + + /** * @throws Exception If failed. */ protected void checkPartitioned() throws Exception { diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java index 593d1c3..d86cfd4 100755 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java @@ -18,6 +18,7 @@ package org.apache.ignite.testframework.junits.common; import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; @@ -41,6 +42,7 @@ import javax.cache.CacheException; import javax.cache.integration.CompletionListener; import javax.management.MBeanServer; import javax.management.MBeanServerInvocationHandler; +import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -118,6 +120,7 @@ import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.lang.IgniteInClosure; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.lang.IgniteRunnable; +import org.apache.ignite.mxbean.MXBeanDescription; import org.apache.ignite.resources.IgniteInstanceResource; import org.apache.ignite.resources.LoggerResource; import org.apache.ignite.testframework.GridTestNode; @@ -131,6 +134,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; import static org.apache.ignite.IgniteSystemProperties.IGNITE_EVENT_DRIVEN_SERVICE_PROCESSOR_ENABLED; import static org.apache.ignite.IgniteSystemProperties.getBoolean; import static org.apache.ignite.cache.CacheMode.LOCAL; @@ -2375,4 +2379,137 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest { return MBeanServerInvocationHandler.newProxyInstance(mbeanSrv, mbeanName, cls, true); } + + /** + * Checks that return types of all registered ignite metrics methods are correct. + * Also checks that all classes from {@code namesToCheck} are registered as mbeans. + * + * @param ignite Ignite instance to collect metrics from. + * @param namesToCheck Mbean classes names that must be registered in {@code MBeanServer}. + * @throws Exception If failed to obtain mbeans. + */ + protected void validateMbeans(Ignite ignite, String... namesToCheck) throws Exception { + logMbeansValidation(getNotRegisteredMbeans(ignite, namesToCheck), "Not registered mbeans"); + logMbeansValidation(getInvalidMbeansMethods(ignite), "Invalid metrics methods"); + } + + /** + * @param ignite Ignite instance to collect metrics from. + * @param namesToCheck Mbean classes names that must be registered in {@code MBeanServer}. + * @return {@code Set} of class names that are contained in {@code namesToCheck} + * but not registered in {@code MBeanServer}. + */ + protected Set<String> getNotRegisteredMbeans(Ignite ignite, String... namesToCheck) { + MBeanServer srv = ignite.configuration().getMBeanServer(); + + Set<String> beancClsNames = srv.queryMBeans(null, null).stream() + .map(ObjectInstance::getClassName) + .collect(toSet()); + + return Arrays.stream(namesToCheck) + .filter(nameToCheck -> beancClsNames.stream().noneMatch(clsName -> clsName.contains(nameToCheck))) + .collect(toSet()); + } + + /** + * @param ignite Ignite instance to collect metrics from. + * @return {@code Set} of metrics methods that have forbidden return types. + * @throws Exception If failed to obtain metrics. + */ + protected Set<String> getInvalidMbeansMethods(Ignite ignite) throws Exception { + Set<String> sysMetricsPackages = new HashSet<>(); + sysMetricsPackages.add("sun.management"); + sysMetricsPackages.add("javax.management"); + + MBeanServer srv = ignite.configuration().getMBeanServer(); + + Set<String> invalidMethods = new HashSet<>(); + + final Set<ObjectInstance> instances = srv.queryMBeans(null, null); + + for (ObjectInstance instance: instances) { + final String clsName = instance.getClassName(); + + if (sysMetricsPackages.stream().anyMatch(clsName::startsWith)) + continue; + + Class c; + + try { + c = Class.forName(clsName); + } + catch (ClassNotFoundException e) { + log.warning("Failed to load class: " + clsName); + + continue; + } + + for (Class interf : c.getInterfaces()) { + for (Method m : interf.getMethods()) { + if (!m.isAnnotationPresent(MXBeanDescription.class)) + continue; + + if (!validateMetricsMethod(m)) + invalidMethods.add(m.toString()); + } + } + } + + return invalidMethods; + } + + /** */ + private void logMbeansValidation(Set<String> invalidSet, String errorMsgPrefix) { + if (!invalidSet.isEmpty()) { + log.info("****************************************"); + log.info(errorMsgPrefix + ":"); + + invalidSet.stream() + .sorted() + .forEach(log::info); + + log.info("****************************************"); + + fail(errorMsgPrefix + " detected^"); + } + } + + /** + * Validates return type for metrics method. + * Validity rules are not carved in stone and can be changed in future. + * See https://issues.apache.org/jira/browse/IGNITE-12629. + * + * @param m Metric method to check. + * @return {@code True} if method return type is allowed. + */ + private boolean validateMetricsMethod(Method m) { + Set<String> primitives = new HashSet<>(); + primitives.add("char"); + primitives.add("short"); + primitives.add("int"); + primitives.add("long"); + primitives.add("double"); + primitives.add("float"); + primitives.add("byte"); + primitives.add("boolean"); + primitives.add("void"); + + Set<String> allowedPackages = new HashSet<>(); + allowedPackages.add("java.lang"); + allowedPackages.add("java.util"); + + final String returnTypeName = m.getGenericReturnType().getTypeName(); + + if (primitives.stream().anyMatch(type -> type.equals(returnTypeName) || (type + "[]").equals(returnTypeName))) + return true; + + String[] parts = returnTypeName.split("[<>,]"); + + for (String part: parts) { + if (allowedPackages.stream().noneMatch(pack -> part.trim().startsWith(pack))) + return false; + } + + return true; + } } diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java index aeead5f..711048e 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java @@ -33,6 +33,7 @@ import org.apache.ignite.internal.GridFailFastNodeFailureDetectionSelfTest; import org.apache.ignite.internal.GridLifecycleAwareSelfTest; import org.apache.ignite.internal.GridLifecycleBeanSelfTest; import org.apache.ignite.internal.GridMBeansTest; +import org.apache.ignite.internal.GridMbeansMiscTest; import org.apache.ignite.internal.GridNodeMetricsLogSelfTest; import org.apache.ignite.internal.GridPeerDeploymentRetryModifiedTest; import org.apache.ignite.internal.GridPeerDeploymentRetryTest; @@ -183,6 +184,7 @@ import org.junit.runners.Suite; GridNodeMetricsLogSelfTest.class, GridLocalIgniteSerializationTest.class, GridMBeansTest.class, + GridMbeansMiscTest.class, TransactionsMXBeanImplTest.class, SetTxTimeoutOnPartitionMapExchangeTest.class, DiscoveryDataDeserializationFailureHanderTest.class, diff --git a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java index f51da78..18493c9 100644 --- a/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java +++ b/modules/zookeeper/src/test/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryMiscTest.java @@ -462,6 +462,21 @@ public class ZookeeperDiscoveryMiscTest extends ZookeeperDiscoverySpiTestBase { } /** + * @throws Exception If failed. + */ + @Test + public void testZkMbeansValidity() throws Exception { + try { + Ignite ignite = startGrid(); + + validateMbeans(ignite, "org.apache.ignite.spi.discovery.zk.ZookeeperDiscoverySpi$ZookeeperDiscoverySpiMBeanImpl"); + } + finally { + stopAllGrids(); + } + } + + /** * */ private static class ValidationTestAffinity extends RendezvousAffinityFunction {