blob: baf174da12ada51ab7c47ad7e271db687031173e [file]
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package amxtest;
import org.testng.annotations.*;
import org.testng.Assert;
import javax.management.ObjectName;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collection;
import org.glassfish.admin.amx.core.*;
import org.glassfish.admin.amx.base.*;
import org.glassfish.admin.amx.config.*;
//import org.glassfish.admin.amx.j2ee.*;
import org.glassfish.admin.amx.monitoring.*;
import org.glassfish.admin.amx.util.CollectionUtil;
import org.glassfish.admin.amx.util.ExceptionUtil;
import org.glassfish.admin.amx.util.jmx.JMXUtil;
import org.glassfish.admin.amx.logging.Logging;
import org.glassfish.admin.amx.annotation.*;
/**
These tests are designed to exercise the AMXProxyHandler code.
*/
//@Test(groups={"amx"}, description="AMXProxy tests", sequential=false, threadPoolSize=5)
@Test(
sequential=false, threadPoolSize=10,
groups =
{
"amx"
},
description = "test the functionality of AMX dymamic proxy eg AMXProxy"
)
public final class AMXProxyTests extends AMXTestBase
{
public AMXProxyTests()
{
}
private String attrName( final Method m )
{
if ( ! JMXUtil.isIsOrGetter(m) ) return null;
return JMXUtil.getAttributeName(m);
}
private <T extends AMXProxy> void testProxyInterface(final AMXProxy amx, Class<T> clazz)
{
final List<String> problems = _testProxyInterface(amx, clazz);
assert problems.size() == 0 : CollectionUtil.toString( problems, "\n" );
}
private <T extends AMXProxy> List<String> _testProxyInterface(final AMXProxy amxIn, Class<T> clazz)
{
assert amxIn != null : "_testProxyInterface(): null proxy for class " + clazz.getName();
final List<String> problems = new ArrayList<String>();
final T amx = amxIn.as(clazz);
final String nameProp = amx.nameProp();
assert Util.getNameProp(amx.objectName()) == nameProp;
assert amx.parentPath() != null;
assert amx.type() != null;
assert amx.valid();
assert amx.childrenSet() != null;
assert amx.childrenMaps() != null;
assert amx.attributesMap() != null;
final Set<String> attrNames = amx.attributeNames();
assert attrNames != null;
final ObjectName objectName = amx.objectName();
assert objectName != null;
assert amx.extra() != null;
final Extra extra = amx.extra();
//assert extra.mbeanServerConnection() == getMBeanServerConnection();
assert extra.proxyFactory() == getProxyFactory();
assert extra.java().length() >= 100;
assert extra.mbeanInfo() != null;
assert extra.interfaceName() != null;
assert extra.genericInterface() != null;
assert extra.group() != null;
assert extra.descriptor() != null;
extra.isInvariantMBeanInfo(); // just call it
extra.subTypes(); // just call it
extra.supportsAdoption(); // just call it
if ( extra.globalSingleton() )
{
assert extra.singleton();
}
final Method[] methods = clazz.getMethods();
final Set<String> attrNamesFromMethods = new HashSet<String>();
for( final Method m : methods )
{
if ( JMXUtil.isIsOrGetter(m) )
{
final String attrName = attrName(m);
final ChildGetter childGetter = m.getAnnotation(ChildGetter.class);
if ( attrNames.contains(attrName) && childGetter != null )
{
println( "Warning: Attribute " + attrName +
" exists in " + objectName + ", but has superfluous @ChildGetter annotation" );
}
try
{
final Object result = m.invoke( amx, (Object[])null);
attrNamesFromMethods.add( attrName(m) );
}
catch( final Exception e )
{
e.printStackTrace();
problems.add( "Error invoking " + m.getName() + "() on " + objectName + " = " + e );
}
}
}
if ( clazz != AMXProxy.class && clazz != AMXConfigProxy.class )
{
// see whether the interface is missing any getters
final Set<String> missing = new HashSet<String>(attrNames);
missing.removeAll(attrNamesFromMethods);
if ( missing.size() != 0 )
{
//println( clazz.getName() + " missing getters attributes: " + missing );
}
}
return problems;
}
@Test
public void testDomainRoot()
{
final DomainRoot dr = getDomainRootProxy();
testProxyInterface( dr, DomainRoot.class );
// sanity check: see that the various attributes are reachable through its proxy
assert dr.getAMXReady();
assert dr.getDebugPort() != null;
assert dr.getApplicationServerFullVersion() != null;
assert dr.getInstanceRoot() != null;
assert dr.getDomainDir() != null;
assert dr.getConfigDir() != null;
assert dr.getInstallDir() != null;
assert dr.getUptimeMillis() != null;
}
@Test
public void testExt()
{
testProxyInterface( getExt(), Ext.class );
}
@Test
public void testQuery()
{
testProxyInterface( getQueryMgr(), Query.class );
}
@Test
public void testBulkAccess()
{
testProxyInterface( getDomainRootProxy().getBulkAccess(), BulkAccess.class );
}
@Test
public void testTools()
{
testProxyInterface( getDomainRootProxy().getTools(), Tools.class );
}
@Test
public void testMonitoringRoot()
{
testProxyInterface( getDomainRootProxy().getMonitoringRoot(), MonitoringRoot.class );
}
@Test
public void testRuntimeRoot()
{
testProxyInterface( getDomainRootProxy().getRuntime(), RuntimeRoot.class );
}
@Test
public void testServerRuntime()
{
final RuntimeRoot runtime = getDomainRootProxy().getRuntime();
final Map<String,ServerRuntime> serverRuntimes = runtime.getServerRuntime();
assert serverRuntimes.keySet().size() != 0;
for( final ServerRuntime sr : serverRuntimes.values() )
{
testProxyInterface( sr, ServerRuntime.class );
}
}
@Test
public void testSystemInfo()
{
testProxyInterface( getDomainRootProxy().getSystemInfo(), SystemInfo.class );
}
@Test
public void testLogging()
{
testProxyInterface( getDomainRootProxy().getLogging(), Logging.class );
}
@Test
public void testPathnames()
{
testProxyInterface( getDomainRootProxy().getPathnames(), Pathnames.class );
}
/** test all MBeans generically */
@Test
public void testForBogusAnnotations()
{
final List<Class<? extends AMXProxy>> interfaces = getInterfaces().all();
for( final Class<? extends AMXProxy> intf : interfaces )
{
final Method[] methods = intf.getMethods();
for( final Method m : methods )
{
final ChildGetter cg = m.getAnnotation(ChildGetter.class);
final ManagedAttribute ma = m.getAnnotation(ManagedAttribute.class);
final ManagedOperation mo = m.getAnnotation(ManagedOperation.class);
final String desc = intf.getName() + "." + m.getName() + "()";
final int numArgs = m.getParameterTypes().length;
assert ma == null || mo == null :
"Can't have both @ManagedAttribute and @ManagedOperation: " + desc;
if ( cg != null )
{
assert numArgs == 0 :
"@ChildGetter cannot be applied to method with arguments: " + desc;
assert ma == null && mo == null :
"@ManagedAttribute/@ManagedOperation not applicable with @ChildGetter: " + desc;
}
if ( mo != null )
{
// operations that mimic getters are bad. We can't prevent all such things
// but we can object to such oddball usage in an AMX interface
if ( numArgs == 0 && m.getName().startsWith("get") )
{
assert false : "testForBogusAnnotations: @ManagedOperation should be @ManagedAttribute: " + desc;
}
}
}
}
}
/** test all MBeans generically */
@Test(/* GLASSFISH-21214 */enabled=false)
public void testAllGenerically()
{
final Interfaces interfaces = getInterfaces();
final List<String> problems = new ArrayList<String>();
for( final AMXProxy amx : getQueryMgr().queryAll() )
{
assert amx != null : "testAllGenerically(): null proxy in query list";
try
{
final List<String> p = _testProxyInterface( amx, interfaces.get(amx.type()) );
problems.addAll(p);
}
catch( final Throwable t )
{
final Throwable rootCause = ExceptionUtil.getRootCause(t);
problems.add( rootCause.getMessage() );
}
}
if ( problems.size() != 0 )
{
System.out.println( "\nPROBLEMS:\n" + CollectionUtil.toString(problems, "\n\n") );
assert false : "" + problems;
}
}
@Test
public void testJ2EEDomain() throws ClassNotFoundException
{
if ( haveJSR77() )
{
testProxyInterface( getDomainRootProxy().getJ2EEDomain(), getJ2EEDomainClass() );
}
}
}