/* * RHQ Management Platform * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.enterprise.server.test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.management.ManagementFactory; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.regex.Pattern; import javax.ejb.EJB; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.naming.Context; import javax.naming.InitialContext; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.PersistenceContext; import javax.transaction.TransactionManager; import org.testng.AssertJUnit; import org.testng.ITestResult; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.arquillian.testng.Arquillian; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ArchivePaths; import org.jboss.shrinkwrap.api.Filters; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.ByteArrayAsset; import org.jboss.shrinkwrap.api.asset.ClassAsset; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.EnterpriseArchive; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.impl.base.exporter.zip.ZipExporterImpl; import org.jboss.shrinkwrap.resolver.api.Resolvers; import org.jboss.shrinkwrap.resolver.api.maven.Maven; import org.jboss.shrinkwrap.resolver.api.maven.MavenResolverSystem; import org.rhq.core.db.DatabaseTypeFactory; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.Server; import org.rhq.core.domain.criteria.ServerCriteria; import org.rhq.core.domain.shared.BuilderException; import org.rhq.core.domain.shared.ResourceBuilder; import org.rhq.core.domain.shared.ResourceTypeBuilder; import org.rhq.core.util.MessageDigestGenerator; import org.rhq.core.util.exception.ThrowableUtil; import org.rhq.core.util.stream.StreamUtil; import org.rhq.enterprise.server.RHQConstants; import org.rhq.enterprise.server.auth.SessionManager; import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean; import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner; import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean; import org.rhq.enterprise.server.plugin.pc.ServerPluginService; import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean; import org.rhq.enterprise.server.resource.metadata.PluginManagerLocal; import org.rhq.enterprise.server.scheduler.SchedulerService; import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean; import org.rhq.enterprise.server.storage.FakeStorageClusterSettingsManagerBean; import org.rhq.enterprise.server.storage.StorageClientManager; import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.test.AssertUtils; import org.rhq.test.MatchResult; import org.rhq.test.PropertyMatchException; import org.rhq.test.PropertyMatcher; public abstract class AbstractEJB3Test extends Arquillian { // this value should correspond with the value passed in the default constructor in // org.rhq.core.domain.criteria.Criteria class public static final int DEFAULT_CRITERIA_PAGE_SIZE = 200; protected static final String JNDI_RHQDS = "java:jboss/datasources/RHQDS"; protected static File tmpdirRoot = new File("./target/test-tmpdir"); private TestServerCommunicationsService agentService; private SchedulerService schedulerService; private ServerPluginService serverPluginService; private PluginDeploymentScannerMBean pluginScannerService; private String originalServerIdentity; @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME) protected EntityManager em; @ArquillianResource protected InitialContext initialContext; @EJB private StorageClientManager storageClientManager; // We originally (in 4.2.3 days) ran these tests as "unit" tests in the server/jar module using // the embedded container. With Arquillian it makes sense to actually deploy an EAR because // we need a way to deploy dependent ears needed to support the server/jar classes. But // building this jar up (as is done in core/domain) was too difficult due to the huge number // of dependencies. It was easier, and made sense, to use the already built rhq.ear // and run as true integration tests. We do thin rhq.ear by removing all of the WAR files, and // deploy only the EJB jars, and the services, which are really the objects under test. @Deployment protected static EnterpriseArchive getBaseDeployment() { // Ensure the test working dir exists tmpdirRoot.mkdirs(); // deploy the test classes in their own jar, under /lib JavaArchive testClassesJar = ShrinkWrap.create(JavaArchive.class, "test-classes.jar"); testClassesJar = addClasses(testClassesJar, new File("target/test-classes/org"), null); // add non itests-2 RHQ classes used by the test classes, as well as needed resources testClassesJar.addClass(ThrowableUtil.class); testClassesJar.addClass(MessageDigestGenerator.class); testClassesJar.addClass(StreamUtil.class); testClassesJar.addClass(AssertUtils.class); testClassesJar.addClass(ResourceBuilder.class); testClassesJar.addClass(ResourceTypeBuilder.class); testClassesJar.addClass(BuilderException.class); testClassesJar.addClasses(PropertyMatcher.class, MatchResult.class, PropertyMatchException.class); testClassesJar.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")); // add CDI injection (needed by arquillian injection); //TOD0 (jshaughn): Once we have identified all of the necessary test resource files, see if we can just add the // entire /resources dir in one statement testClassesJar.addAsResource("binary-blob-sample.jar"); testClassesJar.addAsResource("test-alert-sender-serverplugin.xml"); testClassesJar.addAsResource("test-assist-color-number.txt"); testClassesJar.addAsResource("test-ldap.properties"); testClassesJar.addAsResource("test-scheduler.properties"); testClassesJar.addAsResource("cassandra-test.properties"); testClassesJar .addAsResource("org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/configuration/metadata/configuration_metadata_manager_bean_test_v2.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/discovery/DiscoveryBossBeanTest.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/inventory/InventoryManagerBeanTest.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/resource/metadata/MetadataTest.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/AlertMetadataManagerBeanTest/plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ContentMetadataManagerBeanTest/plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/EventMetadataManagerBeanTest/plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MeasurementMetadataManagerBeanTest/plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child1_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/child2_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionMetadataTest/parent_plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/child_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MultiplePluginExtensionSinglePluginDescriptorMetadataTest/parent_plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/OperationMetadataManagerBeanTest/plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/child_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginExtensionMetadataTest/parent_plugin_v2.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_1.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_3.1.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/resource/metadata/PluginManagerBeanTest/plugin_3.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child1_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/child2_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/PluginScanningExtensionMetadataTest/parent_plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/dup_drift.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/parent_resource_type-plugin.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/plugin_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_bundle_drift_config_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest/remove_types_v2.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MetadataUpdateWithIgnoredTypesTest/remove_types_v1.xml"); testClassesJar .addAsResource("org/rhq/enterprise/server/resource/metadata/MetadataUpdateWithIgnoredTypesTest/remove_types_v2.xml"); testClassesJar.addAsResource("perftest/AvailabilityInsertPurgeTest-testOne-data.xml.zip"); testClassesJar.addAsResource("serverplugins/simple-generic-serverplugin.xml"); testClassesJar.addAsResource("test/deployment/1.0-feb-2.xml"); testClassesJar.addAsResource("test/deployment/1.0-feb.xml"); testClassesJar.addAsResource("test/deployment/1.0-june.xml"); testClassesJar.addAsResource("test/deployment/1.1-feb.xml"); testClassesJar.addAsResource("test/deployment/1.1-june.xml"); testClassesJar.addAsResource("test/metadata/content-source-update-v1.xml"); testClassesJar.addAsResource("test/metadata/content-source-update-v2.xml"); testClassesJar.addAsResource("test/metadata/noTypes.xml"); testClassesJar.addAsResource("test/metadata/alerts/type-with-metric.xml"); testClassesJar.addAsResource("test/metadata/alerts/type-with-trait.xml"); testClassesJar.addAsResource("test/metadata/configuration/addDeleteTemplate1.xml"); testClassesJar.addAsResource("test/metadata/configuration/addDeleteTemplate2.xml"); testClassesJar.addAsResource("test/metadata/configuration/addDeleteTemplate3.xml"); testClassesJar.addAsResource("test/metadata/configuration/constraint.xml"); testClassesJar.addAsResource("test/metadata/configuration/constraintMinMax.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyChanging-v1.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyChanging-v2.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyList-v1.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyList-v2.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyList-simple.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyMap-v1.xml"); testClassesJar.addAsResource("test/metadata/configuration/propertyMap-v2.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupDeleted-v1.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupDeleted-v2.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupPropDeleted-v1.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupPropDeleted-v2.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupPropDeleted-v3.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupPropDeleted-v4.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupPropMoved-v1.xml"); testClassesJar.addAsResource("test/metadata/configuration/groupPropMoved-v2.xml"); testClassesJar.addAsResource("test/metadata/configuration/update5-v1_0.xml"); testClassesJar.addAsResource("test/metadata/configuration/update5-v2_0.xml"); testClassesJar.addAsResource("test/metadata/configuration/updateDefaultTemplate1.xml"); testClassesJar.addAsResource("test/metadata/configuration/updateDefaultTemplate2.xml"); testClassesJar.addAsResource("test/metadata/events/event1-1.xml"); testClassesJar.addAsResource("test/metadata/events/event1-2.xml"); testClassesJar.addAsResource("test/metadata/measurement/measurementDeletion-v1_0.xml"); testClassesJar.addAsResource("test/metadata/measurement/measurementDeletion-v2_0.xml"); testClassesJar.addAsResource("test/metadata/measurement/update-v1_0.xml"); testClassesJar.addAsResource("test/metadata/measurement/update-v2_0.xml"); testClassesJar.addAsResource("test/metadata/measurement/update6-1.xml"); testClassesJar.addAsResource("test/metadata/measurement/update6-2.xml"); testClassesJar.addAsResource("test/metadata/measurement/update7-1.xml"); testClassesJar.addAsResource("test/metadata/measurement/update7-2.xml"); testClassesJar.addAsResource("test/metadata/natives/update5-v1_0.xml"); testClassesJar.addAsResource("test/metadata/natives/update5-v2_0.xml"); testClassesJar.addAsResource("test/metadata/operation/operation1-1.xml"); testClassesJar.addAsResource("test/metadata/operation/operation1-2.xml"); testClassesJar.addAsResource("test/metadata/operation/operation2-1.xml"); testClassesJar.addAsResource("test/metadata/operation/operation2-2.xml"); testClassesJar.addAsResource("test/metadata/operation/operation3-1.xml"); testClassesJar.addAsResource("test/metadata/operation/operation3-2.xml"); testClassesJar.addAsResource("test/metadata/operation/update3-v1_0.xml"); testClassesJar.addAsResource("test/metadata/operation/update3-v2_0.xml"); testClassesJar.addAsResource("test/metadata/resource/nested-subcat-services-v1_0.xml"); testClassesJar.addAsResource("test/metadata/resource/nested-subcat-services-v2_0.xml"); testClassesJar.addAsResource("test/metadata/resource/nested-subcat-services-v3_0.xml"); testClassesJar.addAsResource("test/metadata/resource/no-subcat.xml"); testClassesJar.addAsResource("test/metadata/resource/old-subcat.xml"); testClassesJar.addAsResource("test/metadata/resource/undefined-child-subcat-1.xml"); testClassesJar.addAsResource("test/metadata/resource-type/duplicateResourceType.xml"); testClassesJar.addAsResource("test/metadata/resource-type/update2-v1_0.xml"); testClassesJar.addAsResource("test/metadata/resource-type/update2-v2_0.xml"); testClassesJar.addAsResource("test/metadata/resource-type/update4-v1_0.xml"); testClassesJar.addAsResource("test/metadata/resource-type/update4-v2_0.xml"); testClassesJar.addAsResource("test/metadata/resource-type/updateResourceTypeBundleTarget-v1.xml"); testClassesJar.addAsResource("test/metadata/resource-type/updateResourceTypeBundleTarget-v2.xml"); testClassesJar.addAsResource("org/rhq/enterprise/server/plugins/ant/recipe-no-manageRootDir.xml"); // create test ear by starting with rhq.ear and thinning it String projectVersion = System.getProperty("rhq.version"); String rhqCoreClientApiVersion = System.getProperty("rhq-core-client-api.version"); if ((rhqCoreClientApiVersion == null) || rhqCoreClientApiVersion.trim().isEmpty()) { rhqCoreClientApiVersion = projectVersion; } String rhqPlatformPluginVersion = System.getProperty("rhq-platform-plugin.version"); if ((rhqPlatformPluginVersion == null) || rhqPlatformPluginVersion.trim().isEmpty()) { rhqPlatformPluginVersion = projectVersion; } MavenResolverSystem earResolver = Resolvers.use(MavenResolverSystem.class); // this must be named rhq.ear because the "rhq" portion is used in the jndi names earResolver.offline(); EnterpriseArchive testEar = ShrinkWrap.create(EnterpriseArchive.class, "rhq.ear"); EnterpriseArchive rhqEar = earResolver.resolve("org.rhq:rhq-enterprise-server-ear:ear:" + projectVersion) .withoutTransitivity().asSingle(EnterpriseArchive.class); // merge rhq.ear into testEar but include only the EJB jars and the supporting libraries. Note that we // don't include the services sar because tests are responsible for prepare/unprepare of all required services, // we don't want the production services performing any unexpected work. testEar = testEar.merge(rhqEar, Filters.include("/lib.*|/rhq.*ejb3\\.jar.*|/rhq-server.jar.*")); // remove startup beans and shutdown listeners, we don't want this to be a full server deployment. The tests // start/stop what they need, typically with test services or mocks. testEar.delete(ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/core/StartupBean.class")); testEar.delete(ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/core/StartupBean$1.class")); testEar.delete(ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/core/ShutdownListener.class")); testEar.delete(ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.class")); //replace the above startup beans with stripped down versions testEar.add(new ClassAsset(StrippedDownStartupBean.class), ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/test/StrippedDownStartupBean.class")); testEar.add(new ClassAsset(StrippedDownStartupBeanPreparation.class), ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/test/" + "StrippedDownStartupBeanPreparation.class")); testEar.add(new ClassAsset(FakeStorageClusterSettingsManagerBean.class), ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.class")); testEar.addAsManifestResource(new ByteArrayAsset("<beans/>".getBytes()), ArchivePaths.create("beans.xml")); // add the test classes to the deployment testEar.addAsLibrary(testClassesJar); // add the necessary AS7 dependency modules testEar.addAsManifestResource("jboss-deployment-structure.xml"); // add the application xml declaring the ejb jars testEar.setApplicationXML("application.xml"); // add additional 3rd party dependent jars needed to support test classes Collection<String> thirdPartyDeps = new ArrayList<String>(); thirdPartyDeps.add("joda-time:joda-time"); thirdPartyDeps.add("org.jboss.shrinkwrap:shrinkwrap-impl-base"); thirdPartyDeps.add("org.liquibase:liquibase-core"); thirdPartyDeps.add("org.powermock:powermock-api-mockito"); thirdPartyDeps.add("org.rhq.helpers:perftest-support:" + projectVersion); thirdPartyDeps.add("org.rhq:rhq-core-client-api:jar:tests:" + rhqCoreClientApiVersion); thirdPartyDeps.add("org.rhq:rhq-platform-plugin:jar:" + rhqPlatformPluginVersion); thirdPartyDeps.add("org.codehaus.jackson:jackson-core-asl:1.9.13"); thirdPartyDeps.add("org.codehaus.jackson:jackson-mapper-asl:1.9.13"); thirdPartyDeps.add("org.rhq:test-utils:" + projectVersion); MavenResolverSystem resolver = Maven.resolver(); Collection<JavaArchive> dependencies = new HashSet<JavaArchive>(); dependencies.addAll(Arrays.asList(resolver.loadPomFromFile("pom.xml").resolve(thirdPartyDeps) .withTransitivity().as(JavaArchive.class))); // If we're running oracle we need to include the OJDBC driver because dbunit needs it. Note that we need // add it explicitly even though it is a provided module used by the datasource. if (!Boolean.valueOf(System.getProperty("rhq.skip.oracle"))) { // in proxy situations (like Jenkins) shrinkwrap won't be able to find repositories defined in // settings.xml profiles. We know at this point the driver is in the local repo, try going offline // at this point to force local repo resolution since the oracle driver is not in public repos. // see http://stackoverflow.com/questions/6291146/arquillian-shrinkwrap-mavendependencyresolver-behind-proxy // Last verified this problem using: Arquillian 1.0.3 bom resolver.offline(); dependencies.addAll(Arrays.asList(resolver .resolve("com.oracle:ojdbc6:jar:" + System.getProperty("rhq.ojdbc.version")).withTransitivity() .as(JavaArchive.class))); } // Transitive test dep required by rhq-core-client-api above and for some reason not sucked in. // TODO: pass in version from pom property dependencies.addAll(Arrays.asList(resolver.resolve("commons-jxpath:commons-jxpath:1.3").withTransitivity() .as(JavaArchive.class))); // exclude any transitive deps we don't want String[] excludeFilters = { "testng.*jdk", "rhq-core-domain.*jar" }; dependencies = exclude(dependencies, excludeFilters); testEar.addAsLibraries(dependencies); // Print out the test EAR structure //System.out.println("** The Deployment EAR: " + testEar.toString(true) + "\n"); // Save the test EAR to a zip file for inspection (set file explicitly) //String tmpDir = System.getProperty("java.io.tmpdir"); //exportZip(testEar, new File(tmpDir, "test.ear")); return testEar; } @SuppressWarnings("unused") static private void exportZip(Archive<?> zipArchive, File outFile) { try { ZipExporter exporter = new ZipExporterImpl(zipArchive); exporter.exportTo(outFile, true); } catch (Exception e) { e.printStackTrace(); } } /** * @param dependencies The current set of deps - THIS IS FILTERED, not copied * @param filters regex filters * @return the filtered set of deps */ public static Collection<JavaArchive> exclude(Collection<JavaArchive> dependencies, String... filters) { for (String filter : filters) { Pattern p = Pattern.compile(filter); for (Iterator<JavaArchive> i = dependencies.iterator(); i.hasNext();) { JavaArchive dependency = i.next(); if (p.matcher(dependency.getName()).find()) { i.remove(); } } } return dependencies; } /** * @param dependencies The current set of deps - this is not changed * @param filters regex filters * @return set set of JavaArchives in dependencies that matched an include filter */ public static Collection<JavaArchive> include(Collection<JavaArchive> dependencies, String... filters) { Collection<JavaArchive> result = new HashSet<JavaArchive>(); for (String filter : filters) { Pattern p = Pattern.compile(filter); for (Iterator<JavaArchive> i = dependencies.iterator(); i.hasNext();) { JavaArchive dependency = i.next(); if (p.matcher(dependency.getName()).find()) { result.add(dependency); } } } return result; } public static JavaArchive addClasses(JavaArchive archive, File dir, String packageName) { packageName = (null == packageName) ? "" + dir.getName() : packageName + "." + dir.getName(); for (File file : dir.listFiles()) { String fileName = file.getName(); if (file.isDirectory()) { archive = addClasses(archive, file, packageName); } else if (fileName.endsWith(".class")) { int dot = fileName.indexOf('.'); try { archive.addClass(packageName + "." + fileName.substring(0, dot)); } catch (Exception e) { System.out.println("WARN: Could not add class:" + e); } } } return archive; } /** * <p>DO NOT OVERRIDE.</p> * <p>DO NOT DEFINE AN @BeforeMethod</p> * * Instead, override {@link #beforeMethod()}. If you must override, for example, if you * need to use special attributes on your annotation, then ensure you protect the code with * and {@link #inContainer()} call. */ @BeforeMethod protected void __beforeMethod(Method method) throws Throwable { // Note that Arquillian calls the testng BeforeMethod twice (as of 1.0.2.Final, once // out of container and once in container. In general the expectation is to execute it // one time, and doing it in container allows for the expected injections and context. if (inContainer()) { try { // Make sure we set the db type for tests that may need it (normally done in StartupBean) if (null == DatabaseTypeFactory.getDefaultDatabaseType()) { Connection conn = null; try { conn = getConnection(); DatabaseTypeFactory.setDefaultDatabaseType(DatabaseTypeFactory.getDatabaseType(conn)); } catch (Exception e) { System.err.println("!!! WARNING !!! cannot set default database type, some tests may fail"); e.printStackTrace(); } finally { if (null != conn) { conn.close(); } } } originalServerIdentity = System.getProperty(TestConstants.RHQ_SERVER_NAME_PROPERTY); storageClientManager.init(); beforeMethod(); beforeMethod(method); } catch (Throwable t) { // Arquillian is eating these, make sure they show up in some way System.out.println("BEFORE METHOD FAILURE, TEST DID NOT RUN!!! [" + method.getName() + "]"); t.printStackTrace(); throw t; } } } /** * <p>DO NOT OVERRIDE.</p> * <p>DO NOT DEFINE AN @AfterMethod</p> * * Instead, override {@link #afterMethod()}. */ @AfterMethod(alwaysRun = true) protected void __afterMethod(ITestResult result, Method method) throws Throwable { try { if (inContainer()) { if (originalServerIdentity != null) { System.setProperty(TestConstants.RHQ_SERVER_NAME_PROPERTY, originalServerIdentity); } afterMethod(); afterMethod(result, method); } } catch (Throwable t) { System.out .println("AFTER METHOD FAILURE, TEST CLEAN UP FAILED!!! MAY NEED TO CLEAN DB BEFORE RUNNING MORE TESTS! [" + method.getName() + "]"); t.printStackTrace(); throw t; } } protected boolean inContainer() { // If the injection is done we're running in the container. return (null != initialContext); } /** * Override Point! Do not implement a @BeforeMethod, instead override this method. */ protected void beforeMethod() throws Exception { // do nothing if we're not overridden } /** * Override Point! Do not implement a @BeforeMethod, instead override this method. */ protected void beforeMethod(Method method) throws Exception { // do nothing if we're not overridden } /** * Override Point! Do not implement an @AfterMethod, instead override this method. note: alwaysRun=true */ protected void afterMethod() throws Exception { // do nothing if we're not overridden } /** * Override Point! Do not implement an @AfterMethod, instead override this method. note: alwaysRun=true */ protected void afterMethod(ITestResult result, Method meth) throws Exception { // do nothing if we're not overridden } /** * Safe to be used inside {@link #beforeMethod()}, {@link #afterMethod()} and tests. * Sets the HA identity of the current server. Does <b>NOT</b> define the server in the database, merely sets * its identity as a system property. * <p/> * The value is reset after each test, so tests don't influence each other. */ protected void setServerIdentity(String name) { System.setProperty(TestConstants.RHQ_SERVER_NAME_PROPERTY, name); } /** * Gets the current server identity. This is just a value of the system property, no DB row may exist for the server. */ protected String getServerIdentity() { return System.getProperty(TestConstants.RHQ_SERVER_NAME_PROPERTY); } protected void startTransaction() throws Exception { getTransactionManager().begin(); } protected void commitTransaction() throws Exception { getTransactionManager().commit(); } protected void rollbackTransaction() throws Exception { getTransactionManager().rollback(); } protected InitialContext getInitialContext() { // may be null if not yet injected if (null != initialContext) { return initialContext; } InitialContext result = null; try { Properties jndiProperties = new Properties(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.as.naming.InitialContextFactory"); result = new InitialContext(jndiProperties); } catch (Exception e) { throw new RuntimeException("Failed to get InitialContext", e); } return result; } public TransactionManager getTransactionManager() { TransactionManager result = null; try { result = (TransactionManager) getInitialContext().lookup("java:jboss/TransactionManager"); if (null == result) { result = (TransactionManager) getInitialContext().lookup("TransactionManager"); } } catch (Exception e) { throw new RuntimeException("Failed to get TransactionManager", e); } return result; } protected EntityManager getEntityManager() { // may be null if not yet injected (as of 1.0.1.Final, only injected inside @Test) if (null != em) { return em; } EntityManager result = null; try { EntityManagerFactory emf = (EntityManagerFactory) getInitialContext().lookup( "java:jboss/RHQEntityManagerFactory"); result = emf.createEntityManager(); } catch (Exception e) { throw new RuntimeException("Failed to get EntityManagerFactory", e); } return result; } /** * Equivalent to <pre>executeInTransaction(true, callback)</pre>. * @param callback */ protected void executeInTransaction(TransactionCallback callback) { executeInTransaction(true, callback); } protected void executeInTransaction(boolean rollback, final TransactionCallback callback) { executeInTransaction(rollback, new TransactionCallbackReturnable<Void>() { public Void execute() throws Exception { callback.execute(); return null; } }); } protected <T> T executeInTransaction(TransactionCallbackReturnable<T> callback) { return executeInTransaction(true, callback); } protected <T> T executeInTransaction(boolean rollback, TransactionCallbackReturnable<T> callback) { try { startTransaction(); T result = callback.execute(); return result; } catch (Throwable t) { rollback = true; RuntimeException re = new RuntimeException(ThrowableUtil.getAllMessages(t), t); throw re; } finally { try { if (!rollback) { commitTransaction(); } else { rollbackTransaction(); } } catch (Exception e) { throw new RuntimeException("Failed to " + (rollback ? "rollback" : "commit") + " transaction", e); } } } /* The old AbstractEJB3Test impl extended AssertJUnit. Continue to support the used methods * with various call-thru methods. */ protected void assertNotNull(Object o) { AssertJUnit.assertNotNull(o); } protected void assertNotNull(String msg, Object o) { AssertJUnit.assertNotNull(msg, o); } protected void assertNull(Object o) { AssertJUnit.assertNull(o); } protected void assertNull(String msg, Object o) { AssertJUnit.assertNull(msg, o); } protected void assertFalse(boolean b) { AssertJUnit.assertFalse(b); } protected void assertFalse(String msg, boolean b) { AssertJUnit.assertFalse(msg, b); } protected void assertTrue(boolean b) { AssertJUnit.assertTrue(b); } protected void assertTrue(String msg, boolean b) { AssertJUnit.assertTrue(msg, b); } protected void assertEquals(int expected, int actual) { AssertJUnit.assertEquals(expected, actual); } protected void assertEquals(String msg, int expected, int actual) { AssertJUnit.assertEquals(msg, expected, actual); } protected void assertEquals(long expected, long actual) { AssertJUnit.assertEquals(expected, actual); } protected void assertEquals(String msg, long expected, long actual) { AssertJUnit.assertEquals(msg, expected, actual); } protected void assertEquals(String expected, String actual) { AssertJUnit.assertEquals(expected, actual); } protected void assertEquals(String msg, String expected, String actual) { AssertJUnit.assertEquals(msg, expected, actual); } protected void assertEquals(boolean expected, boolean actual) { AssertJUnit.assertEquals(expected, actual); } protected void assertEquals(String msg, boolean expected, boolean actual) { AssertJUnit.assertEquals(msg, expected, actual); } protected void assertEquals(Object expected, Object actual) { AssertJUnit.assertEquals(expected, actual); } protected void assertEquals(String msg, Object expected, Object actual) { AssertJUnit.assertEquals(msg, expected, actual); } protected void fail() { AssertJUnit.fail(); } protected void fail(String message) { AssertJUnit.fail(message); } /** * This will register any custom service, replacing any service with the same objectName. * <br/> * It does nothing more than registration, any calls to the service (e.g. start) are up to the caller. * * @param testServiceMBean the test service MBean to register * @param objectNameStr the name of the service, which will be converted to an ObjectName * * @throws RuntimeException */ public void prepareCustomServerService(Object testServiceMBean, String objectNameStr) { try { ObjectName objectName = new ObjectName(objectNameStr); prepareCustomServerService(testServiceMBean, objectName); } catch (MalformedObjectNameException e) { throw new RuntimeException(e); } } /** * This will register any custom service, replacing any service with the same objectName. * <br/> * It does nothing more than registration, any calls to the service (e.g. start) are up to the caller. * * @param testServiceMBean the test service MBean to register * @param objectName the name of the service * * @throws RuntimeException */ public void prepareCustomServerService(Object testServiceMBean, ObjectName objectName) { try { // first, unregister the real service... MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(objectName)) { mbs.unregisterMBean(objectName); } // Now replace with the test service... mbs.registerMBean(testServiceMBean, objectName); return; } catch (Exception e) { throw new RuntimeException(e); } } public void unprepareCustomServerService(String objectNameStr) throws Exception { ObjectName objectName = new ObjectName(objectNameStr); unprepareCustomServerService(objectName); } public void unprepareCustomServerService(ObjectName objectName) throws Exception { MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(objectName)) { mbs.unregisterMBean(objectName); } } /** * If you need to test server plugins, you must first prepare the server plugin service. * After this returns, the caller must explicitly start the PC by using the appropriate API * on the given mbean; this method will only start the service, it will NOT start the master PC. * * @param testServiceMBean the object that will house your test server plugins * * @throws RuntimeException */ public void prepareCustomServerPluginService(ServerPluginService testServiceMBean) { try { // first, unregister the real service... MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) { mbs.unregisterMBean(ServerPluginService.OBJECT_NAME); } // Now replace with the test service... testServiceMBean.start(); mbs.registerMBean(testServiceMBean, ServerPluginServiceMBean.OBJECT_NAME); serverPluginService = testServiceMBean; } catch (Exception e) { throw new RuntimeException(e); } } public void unprepareServerPluginService() throws Exception { if (serverPluginService != null) { serverPluginService.stopMasterPluginContainer(); serverPluginService.stop(); serverPluginService = null; } MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(ServerPluginService.OBJECT_NAME)) { mbs.unregisterMBean(ServerPluginService.OBJECT_NAME); } } public SchedulerService getSchedulerService() { return schedulerService; } public void prepareScheduler() { try { if (schedulerService != null) { return; } // first, unregister the real service... MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(SchedulerService.SCHEDULER_MBEAN_NAME)) { mbs.unregisterMBean(SchedulerService.SCHEDULER_MBEAN_NAME); } // Now replace with the test service... Properties quartzProps = new Properties(); quartzProps.load(this.getClass().getClassLoader().getResourceAsStream("test-scheduler.properties")); schedulerService = new SchedulerService(); schedulerService.setQuartzProperties(quartzProps); schedulerService.start(); mbs.registerMBean(schedulerService, SchedulerServiceMBean.SCHEDULER_MBEAN_NAME); schedulerService.startQuartzScheduler(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } public void unprepareScheduler() throws Exception { if (schedulerService != null) { schedulerService.stop(); schedulerService = null; } MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(SchedulerService.SCHEDULER_MBEAN_NAME)) { mbs.unregisterMBean(SchedulerService.SCHEDULER_MBEAN_NAME); } } /** * If you need to test round trips from server to agent and back, you first must install the server communications * service that houses all the agent clients. Call this method and add your test agent services to the public fields * in the returned object. * * @return the object that will house your test agent service impls and the agent clients. * * @throws RuntimeException */ public TestServerCommunicationsService prepareForTestAgents() { if (agentService != null) { return agentService; } return prepareForTestAgents(new TestServerCommunicationsService()); } /** * If you need to test round trips from server to agent and back, you first must install the server communications * service that houses all the agent clients. Call this method and add your test agent services to the public fields * in the returned object. * * @return the object that will house your test agent service impls and the agent clients. * * @throws RuntimeException */ public TestServerCommunicationsService prepareForTestAgents(TestServerCommunicationsServiceMBean customAgentService) { try { if (agentService != null) { return agentService; } // first, unregister the real service... MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) { mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME); } // Now replace with the test service... agentService = (TestServerCommunicationsService) customAgentService; mbs.registerMBean(agentService, ServerCommunicationsServiceMBean.OBJECT_NAME); return agentService; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Call this after your tests have finished. You only need to call this if your test previously called * {@link #prepareForTestAgents()}. */ public void unprepareForTestAgents() { try { if (agentService != null) { agentService.stop(); agentService = null; } MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(ServerCommunicationsServiceMBean.OBJECT_NAME)) { mbs.unregisterMBean(ServerCommunicationsServiceMBean.OBJECT_NAME); } } catch (Exception e) { throw new RuntimeException(e); } } public PluginDeploymentScannerMBean getPluginScannerService() { return pluginScannerService; } /** * Prepares a test deployment scanner with the following characteristics<br/>. * - start() is called but startDeployment() is not called.<br/> * - agentPluginDir is set to getTempDir() + "/plugins"<br/> * - serverPluginDir is set to null (no scanning for server plugins)<br/> * - scanPeriod is set to 9999999 (basically prevent autoscan)<br/> */ protected PluginDeploymentScannerMBean preparePluginScannerService() { if (null != pluginScannerService) { return pluginScannerService; } PluginDeploymentScanner scanner = new PluginDeploymentScanner(); String pluginDirPath = getTempDir() + "/plugins"; scanner.setAgentPluginDir(pluginDirPath); // we don't want to scan for these scanner.setServerPluginDir("ignore no plugins here"); // we don't want to scan for these scanner.setUserPluginDir("ignore no plugins here"); // we don't want to scan for these scanner.setScanPeriod("9999999"); // we want to manually scan - don't allow for auto-scan to happen return preparePluginScannerService(scanner); } /** * Note that the standard plugin scanner service is deployed automatically with the test rhq ear, * this is only necessary if you want a custom service. * * @param scannerService */ public PluginDeploymentScannerMBean preparePluginScannerService(PluginDeploymentScannerMBean scannerService) { try { MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(PluginDeploymentScannerMBean.OBJECT_NAME)) { mbs.unregisterMBean(PluginDeploymentScannerMBean.OBJECT_NAME); } // Now replace with the test service... mbs.registerMBean(scannerService, PluginDeploymentScannerMBean.OBJECT_NAME); pluginScannerService = scannerService; pluginScannerService.start(); return pluginScannerService; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } public void unpreparePluginScannerService() throws Exception { if (pluginScannerService != null) { pluginScannerService.stop(); pluginScannerService = null; } MBeanServer mbs = getPlatformMBeanServer(); if (mbs.isRegistered(PluginDeploymentScannerMBean.OBJECT_NAME)) { mbs.unregisterMBean(PluginDeploymentScannerMBean.OBJECT_NAME); } } public MBeanServer getPlatformMBeanServer() { return ManagementFactory.getPlatformMBeanServer(); } /** * This creates a session for the given user and associates that session with the subject. You can test the security * annotations by creating sessions for different users with different permissions. * * @param subject a JON subject * @return the session activated subject, a copy of the subject passed in. */ public Subject createSession(Subject subject) { return SessionManager.getInstance().put(subject); } public static Connection getConnection() throws SQLException { return LookupUtil.getDataSource().getConnection(); } /** * A utility for writing out various objects that need to be persisted for use between * tests. Arquillian (1.0.2) basically "new"s the testng test class on each test, so instance * variables can not be used between tests. Instead, the db or this mechanism needs to be used. * * The file will be placed in the standard temp dir. If it already exists it will be replaced. * * @param filename Do not include the directory. The value will be prepended with the class name. * @param objects * @throws Exception */ protected void writeObjects(String filename, Object... objects) throws Exception { File file = new File(getTempDir(), filename); file.delete(); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); for (Object o : objects) { oos.writeObject(o); } oos.close(); } /** * A utility for reading in objects written with {@link #writeObjects(String, Object...). They are * placed in the result List in the same order they were written. * * @param filename The same filename used in the write. Do not include the directory. * @param numObjects the number of objects to read out. Can be less than total written, not greater. * @throws Exception */ protected List<Object> readObjects(String filename, int numObjects) throws Exception { List<Object> result = new ArrayList<Object>(); ObjectInputStream ois = null; try { File file = new File(getTempDir(), filename); ois = new ObjectInputStream(new FileInputStream(file)); for (int i = 0; i < numObjects; ++i) { result.add(ois.readObject()); } } finally { ois.close(); } return result; } /** * A utility for cleaning up files created with {@link #writeObjects(String, Object...). * * @param filename The same filename used in the write. Do not include the directory. * @return true if deleted, false otherwise. */ protected boolean deleteObjects(String filename) { File file = new File(getTempDir(), filename); return file.delete(); } /** * @return a temp directory for testing that is specific to this test class. Specifically tmpdirRoot/this.getClass().getSimpleName(). */ public File getTempDir() { return new File(tmpdirRoot, this.getClass().getSimpleName()); } protected void ackDeletedPlugins() { Subject overlord = LookupUtil.getSubjectManager().getOverlord(); PluginManagerLocal pluginMgr = LookupUtil.getPluginManager(); for(Server server : LookupUtil.getTopologyManager().findServersByCriteria(overlord, new ServerCriteria())) { pluginMgr.acknowledgeDeletedPluginsBy(server.getId()); } } }