Skip to content

Commit

Permalink
GG-25038 Extend test coverage [GG-25026] Jconsole does not show metri…
Browse files Browse the repository at this point in the history
…cs implemented in GG-21273
  • Loading branch information
vmalin committed Nov 25, 2019
1 parent 3dd983f commit 94347f6
Show file tree
Hide file tree
Showing 8 changed files with 329 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
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;

/**
Expand Down Expand Up @@ -300,6 +301,19 @@ public void testProjectionPredicateDifferentClassLoaders() throws Exception {
ret.get(ignite3.cluster().localNode().id());
}

/**
* @throws Exception If fatiled.
*/
@Ignore("https://ggsystems.atlassian.net/browse/GG-25507")
@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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,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;

/**
Expand Down Expand Up @@ -85,4 +85,35 @@ private void checkBean(String grp, String name, String attributeName, Object exp

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.cluster.IgniteClusterMXBeanImpl",
"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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright 2019 GridGain Systems, Inc. and Contributors.
*
* Licensed under the GridGain Community Edition License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.gridgain.com/products/software/community-edition/gridgain-community-edition-license
*
* 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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ public void testReduce() throws Exception {
grid(1).compute().execute(ReduceTestTask.class, null);
}

/**
* @throws Exception If failed.
*/
@Test
public void testCacheCheckpointSpiMbeanValidity() throws Exception {
validateMbeans(grid(1), "org.apache.ignite.spi.checkpoint.cache.CacheCheckpointSpi$CacheCheckpointSpiMBeanImpl");
}

/**
* Failover test task.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,23 @@ public void testPartitionedNearEnabledMultiThreaded() throws Exception {
checkPartitionedMultiThreaded();
}

/**
* @throws Exception if failed.
*/
@Test
public void testEvictionPolicyMbeanValidity() throws Exception {
try {
Ignite ignite = startGrids(2);

//Instanate policy object to know exact class.
EvictionPolicy plc = createPolicy(0);

validateMbeans(ignite, plc.getClass().getName());
} finally {
stopAllGrids();
}
}

/**
* @throws Exception If failed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,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;
Expand All @@ -40,6 +41,7 @@
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;
Expand Down Expand Up @@ -119,6 +121,7 @@
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;
Expand Down Expand Up @@ -2492,4 +2495,126 @@ protected <T, I> T getMxBean(

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<>();

for (ObjectInstance instance: srv.queryMBeans(null, null)) {
final String clsName = instance.getClassName();

if (sysMetricsPackages.stream().anyMatch(clsName::startsWith))
continue;

Class c = Class.forName(clsName);

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://ggsystems.atlassian.net/browse/GG-25507.
*
* @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;
}
}
Loading

0 comments on commit 94347f6

Please sign in to comment.