/*
* RHQ Management Platform
* Copyright (C) 2005-2008 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, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser 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.core.clientapi.agent.metadata.test;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.util.ValidationEventCollector;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.clientapi.descriptor.DescriptorPackages;
import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration;
import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory;
import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory.Context;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.configuration.definition.PropertySimpleType;
import org.rhq.core.domain.configuration.definition.constraint.RegexConstraint;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
/**
* Test the management and loading of Agent plugin metadata.
*
* @author Greg Hinkle
*/
public class MetadataManagerTest {
private static final String DESCRIPTOR_FILENAME_TEST1 = "metadata-manager-test-1.xml";
private static final String DESCRIPTOR_FILENAME_TEST2 = "metadata-manager-test-2.xml";
private static final String DESCRIPTOR_FILENAME_TEST3 = "metadata-manager-test-3.xml";
private PluginMetadataManager metadataManager;
@BeforeClass
public void beforeClass() {
try {
this.metadataManager = new PluginMetadataManager();
} catch (Throwable t) {
// Catch RuntimeExceptions and Errors and dump their stack trace, because Surefire will completely swallow them
// and throw a cryptic NPE (see http://jira.codehaus.org/browse/SUREFIRE-157)!
t.printStackTrace();
throw new RuntimeException(t);
}
}
@Test
public void loadPluginDescriptorTest1() throws Exception {
PluginDescriptor pluginDescriptor;
URL descriptorUrl = this.getClass().getClassLoader().getResource(DESCRIPTOR_FILENAME_TEST1);
System.out.println("Loading plugin descriptor at: " + descriptorUrl);
JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
ValidationEventCollector vec = new ValidationEventCollector();
unmarshaller.setEventHandler(vec);
pluginDescriptor = (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream());
this.metadataManager.loadPlugin(pluginDescriptor);
System.out.println("\n~~~~~~~~~~~~DESCRIPTOR TEST 1");
outputTypes();
}
@Test(dependsOnMethods = "loadPluginDescriptorTest1")
public void testDefinitionParsing1() {
ResourceType serverAType = this.metadataManager.getType("Server A", "Test1");
assert serverAType.getName().equals("Server A");
assert serverAType.getPlugin().equals("Test1");
assertServerTypeIsOK(serverAType);
}
@Test(dependsOnMethods = "loadPluginDescriptorTest1")
public void loadPluginDescriptorTest2() throws Exception {
PluginDescriptor pluginDescriptor;
URL descriptorUrl = this.getClass().getClassLoader().getResource(DESCRIPTOR_FILENAME_TEST2);
System.out.println("Loading plugin descriptor at: " + descriptorUrl);
JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
ValidationEventCollector vec = new ValidationEventCollector();
unmarshaller.setEventHandler(vec);
pluginDescriptor = (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream());
this.metadataManager.loadPlugin(pluginDescriptor);
System.out.println("\n~~~~~~~~~~~~DESCRIPTOR TEST 2");
outputTypes();
}
@Test(dependsOnMethods = "loadPluginDescriptorTest2")
public void testDefinitionParsing2() {
ResourceType serverBType = this.metadataManager.getType("Extension Server B", "Test2");
assert serverBType.getName().equals("Extension Server B");
assert serverBType.getPlugin().equals("Test2");
assertServerTypeIsOK(serverBType);
}
@Test(dependsOnMethods = "loadPluginDescriptorTest2")
public void loadPluginDescriptorTest3() throws Exception {
PluginDescriptor pluginDescriptor;
URL descriptorUrl = this.getClass().getClassLoader().getResource(DESCRIPTOR_FILENAME_TEST3);
System.out.println("Loading plugin descriptor at: " + descriptorUrl);
JAXBContext jaxbContext = JAXBContext.newInstance(DescriptorPackages.PC_PLUGIN);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
ValidationEventCollector vec = new ValidationEventCollector();
unmarshaller.setEventHandler(vec);
pluginDescriptor = (PluginDescriptor) unmarshaller.unmarshal(descriptorUrl.openStream());
this.metadataManager.loadPlugin(pluginDescriptor);
System.out.println("\n~~~~~~~~~~~~DESCRIPTOR TEST 3");
outputTypes();
ResourceType parentA = getResourceType(new ResourceType("Server A", "Test1", ResourceCategory.SERVER, null));
ResourceType parentB = getResourceType(new ResourceType("Extension Server B", "Test2", ResourceCategory.SERVER,
null));
assert parentA != null;
assert parentB != null;
ResourceType testC = getResourceType(new ResourceType("Injection C To Server A", "Test3",
ResourceCategory.SERVER, null));
assert testC != null;
assert parentA.getChildResourceTypes().contains(testC);
assert parentB.getChildResourceTypes().contains(testC); // shows that a type can have more than one parent
ResourceType testD = getResourceType(new ResourceType("Injection D To Server A", "Test3",
ResourceCategory.SERVICE, null));
assert testD != null;
assert parentA.getChildResourceTypes().contains(testD);
assert !parentB.getChildResourceTypes().contains(testD);
// now check the many-to-many relationship - child can have more than one parent
assert testC.getParentResourceTypes().contains(parentA);
assert testC.getParentResourceTypes().contains(parentB);
assert testD.getParentResourceTypes().contains(parentA);
assert !testD.getParentResourceTypes().contains(parentB);
// ensure the bundle metadata is correct
assert testD.getBundleType() != null : "missing the bundle for 'Injection D To Server A'";
assert testD.getBundleType().getName().equals("test-bundle-name");
assert testD.getBundleType().getResourceType().equals(testD);
}
@Test(dependsOnMethods = "loadPluginDescriptorTest3")
public void testDiscoveryCallbackDefinitions() {
ResourceType serverAType = this.metadataManager.getType("Server A", "Test1");
ResourceType serverBType = this.metadataManager.getType("Extension Server B", "Test2");
assert serverAType != null : "Where's Server A?";
assert serverBType != null : "Where's Extension Server B?";
Map<String, List<String>> serverACallbacks = this.metadataManager.getDiscoveryCallbacks(serverAType);
assert serverACallbacks.size() == 1 : serverACallbacks;
assert serverACallbacks.get("Test3").size() == 2 : serverACallbacks;
assert serverACallbacks.get("Test3").get(0).equals("org.rhq.plugins.test3.DiscoveryCallback1") : serverACallbacks;
assert serverACallbacks.get("Test3").get(1).equals("org.rhq.plugins.test3.DiscoveryCallbackAnother1") : serverACallbacks;
Map<String, List<String>> serverBCallbacks = this.metadataManager.getDiscoveryCallbacks(serverBType);
assert serverBCallbacks.size() == 2 : serverBCallbacks;
assert serverBCallbacks.get("Test3").size() == 1 : serverBCallbacks;
assert serverBCallbacks.get("Test2").size() == 1 : serverBCallbacks;
assert serverBCallbacks.get("Test3").get(0).equals("org.rhq.plugins.test3.DiscoveryCallback2") : serverBCallbacks;
assert serverBCallbacks.get("Test2").get(0).equals("org.rhq.plugins.test2.DiscoveryCallbackTest2") : serverBCallbacks;
}
private ResourceType getResourceType(ResourceType typeToGet) {
for (ResourceType type : metadataManager.getAllTypes()) {
if (type.equals(typeToGet)) {
return type;
}
}
return null;
}
/**
* @param serverType
*/
private void assertServerTypeIsOK(ResourceType serverType) {
assert serverType != null : "Expected type not found";
ConfigurationDefinition def = serverType.getPluginConfigurationDefinition();
PropertyDefinitionSimple alpha = def.getPropertyDefinitionSimple("alpha");
assert alpha.getType() == PropertySimpleType.STRING;
assert alpha.isRequired();
assert alpha.getConstraints().size() == 1;
RegexConstraint regexConstraint = (RegexConstraint) alpha.getConstraints().iterator().next();
assert regexConstraint.getDetails().equals("^\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$");
PropertyDefinitionSimple bravo = def.getPropertyDefinitionSimple("bravo");
assert bravo.getType() == PropertySimpleType.STRING;
assert bravo.getEnumeratedValues().size() == 4;
assert bravo.getEnumeratedValues().get(0).getName().equals("First Option Name");
assert bravo.getEnumeratedValues().get(0).getValue().equals("FirstOptionValue");
assert bravo.getEnumeratedValues().get(0).getValue().equals(
def.getDefaultTemplate().getConfiguration().getSimpleValue("bravo", null));
assert def.getPropertyDefinitionSimple("charlie").getType() == PropertySimpleType.BOOLEAN;
assert def.getPropertyDefinitionSimple("delta").getType() == PropertySimpleType.INTEGER;
assert def.getPropertyDefinitionSimple("deltalong").getType() == PropertySimpleType.LONG;
assert def.getPropertyDefinitionSimple("echo").getType() == PropertySimpleType.PASSWORD;
assert def.getPropertyDefinitionSimple("foxtrot").getType() == PropertySimpleType.FLOAT;
assert def.getPropertyDefinitionSimple("foxtrotdouble").getType() == PropertySimpleType.DOUBLE;
assert def.getPropertyDefinitionSimple("golf").getType() == PropertySimpleType.DIRECTORY;
assert def.getPropertyDefinitionSimple("hotel").getType() == PropertySimpleType.FILE;
assert def.getPropertyDefinitionSimple("india").getType() == PropertySimpleType.LONG_STRING;
PropertyDefinitionList juliet = def.getPropertyDefinitionList("juliet");
assert juliet.getMin() == 3;
assert juliet.getMax() == 4;
PropertyDefinitionSimple foo = (PropertyDefinitionSimple) juliet.getMemberDefinition();
assert foo != null;
assert foo.getName().equals("foo");
assert foo.getType() == PropertySimpleType.STRING;
// This is an arbitrary entry map
assert def.getPropertyDefinitionMap("kilo").getMap().size() == 0;
assert def.getPropertyDefinitionMap("kilo").getName().equals("kilo");
PropertyDefinitionSimple mapEmbeddedSimpleDef = (PropertyDefinitionSimple) def.getPropertyDefinitionMap("lima")
.getMap().get("file");
assert mapEmbeddedSimpleDef != null;
assert mapEmbeddedSimpleDef.getType() == PropertySimpleType.FILE;
assert def.getPropertyDefinitionList("mike").getMin() == 0;
assert def.getPropertyDefinitionList("mike").getMax() == Integer.MAX_VALUE;
Map<String, ConfigurationTemplate> templates = def.getTemplates();
ConfigurationTemplate t = templates.get("First Template");
assert !t.isDefault();
assert t.getConfiguration().getSimple("alpha").getStringValue().equals("template1:alpha value");
assert t.getConfiguration().getSimple("charlie").getBooleanValue();
assert t.getConfiguration().getSimple("delta").getIntegerValue() == 42;
assert serverType.getBundleType() == null : "bundle should not be defined for type: " + serverType;
// ensure the bundle target metadata is correct
ResourceTypeBundleConfiguration bundleTargetConfig = serverType.getResourceTypeBundleConfiguration();
assert bundleTargetConfig != null;
Set<ResourceTypeBundleConfiguration.BundleDestinationBaseDirectory> set = bundleTargetConfig
.getBundleDestinationBaseDirectories();
assert set.size() == 2;
for (BundleDestinationBaseDirectory bdbd : set) {
if (bdbd.getName().equals("basedir1")) {
assert bdbd.getValueContext() == Context.pluginConfiguration : bdbd;
assert bdbd.getValueName().equals("alpha") : bdbd;
} else if (bdbd.getName().equals("basedir2")) {
assert bdbd.getValueContext() == Context.resourceConfiguration : bdbd;
assert bdbd.getValueName().equals("resourceAlpha") : bdbd;
} else {
assert false : "Bad bundle target name: " + bdbd;
}
}
}
private void outputTypes() {
Set<ResourceType> allTypes = metadataManager.getRootTypes();
for (ResourceType type : allTypes) {
outputType(type, 0);
}
System.out.flush();
}
private void outputType(ResourceType type, int depth) {
StringBuilder line = new StringBuilder();
for (int i = 0; i < depth; i++) {
line.append(" ");
}
line.append("+ ");
line.append(type.toString());
System.out.println(line.toString());
for (ResourceType child : type.getChildResourceTypes()) {
outputType(child, depth + 1);
}
}
}