package org.jboss.as.subsystem.test;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javax.xml.stream.XMLStreamException;
import org.jboss.as.controller.Extension;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.model.test.EAPRepositoryReachableUtil;
import org.jboss.as.model.test.ModelFixer;
import org.jboss.as.model.test.ModelTestKernelServices;
import org.jboss.as.model.test.ModelTestModelControllerService;
import org.jboss.as.model.test.ModelTestUtils;
import org.jboss.dmr.ModelNode;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
/**
* The base class for parsing tests which does the work of setting up the environment for parsing
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @author <a href="stefano.maestri@redhat.com>Stefano Maestri</a>
*/
public abstract class AbstractSubsystemTest {
/**
* Use {@link AbstractSubsystemTest#getMainSubsystemName()}
*/
@Deprecated
protected final String mainSubsystemName;
private final SubsystemTestDelegate delegate;
protected AbstractSubsystemTest(final String mainSubsystemName, final Extension mainExtension) {
this(mainSubsystemName, mainExtension, null);
}
@SuppressWarnings("deprecation")
protected AbstractSubsystemTest(final String mainSubsystemName, final Extension mainExtension, final Comparator<PathAddress> removeOrderComparator) {
this.mainSubsystemName = mainSubsystemName;
this.delegate = new SubsystemTestDelegate(this.getClass(), mainSubsystemName, mainExtension, removeOrderComparator);
}
public String getMainSubsystemName() {
return delegate.getMainSubsystemName();
}
@Before
public void initializeParser() throws Exception {
delegate.initializeParser();
}
@After
public void cleanup() throws Exception {
delegate.cleanup();
}
protected Extension getMainExtension() {
return delegate.getMainExtension();
}
/**
* Read the classpath resource with the given name and return its contents as a string. Hook to
* for reading in classpath resources for subsequent parsing. The resource is loaded using similar
* semantics to {@link Class#getResource(String)}
*
* @param name the name of the resource
* @return the contents of the resource as a string
* @throws IOException
*/
protected String readResource(final String name) throws IOException {
return ModelTestUtils.readResource(getClass(), name);
}
/**
* Parse the subsystem xml and create the operations that will be passed into the controller
*
* @param subsystemXml the subsystem xml to be parsed
* @return the created operations
* @throws XMLStreamException if there is a parsing problem
*/
protected List<ModelNode> parse(String subsystemXml) throws XMLStreamException {
return delegate.parse(subsystemXml);
}
/**
* Parse the subsystem xml and create the operations that will be passed into the controller
*
* @param additionalParsers additional initialization that should be done to the parsers before initializing our extension. These parsers
* will only be initialized the first time this method is called from within a test
* @param subsystemXml the subsystem xml to be parsed
* @return the created operations
* @throws XMLStreamException if there is a parsing problem
*/
protected List<ModelNode> parse(AdditionalParsers additionalParsers, String subsystemXml) throws XMLStreamException {
return delegate.parse(additionalParsers, subsystemXml);
}
/**
* Output the model to xml
*
* @param model the model to marshall
* @return the xml
*/
protected String outputModel(ModelNode model) throws Exception {
return delegate.outputModel(model);
}
/**
* Initializes the controller and populates the subsystem model from the passed in xml.
*
* @param subsystemXml the subsystem xml to be parsed
* @return the kernel services allowing access to the controller and service container
* @deprecated Use {@link #createKernelServicesBuilder(AdditionalInitialization)} instead
*/
@Deprecated
@SuppressWarnings("deprecation")
protected KernelServices installInController(String subsystemXml) throws Exception {
return delegate.installInController(subsystemXml);
}
/**
* Initializes the controller and populates the subsystem model from the passed in xml.
*
* @param additionalInit Additional initialization that should be done to the parsers, controller and service container before initializing our extension
* @param subsystemXml the subsystem xml to be parsed
* @deprecated Use {@link #createKernelServicesBuilder(AdditionalInitialization)} instead
*/
@Deprecated
@SuppressWarnings("deprecation")
protected KernelServices installInController(AdditionalInitialization additionalInit, String subsystemXml) throws Exception {
return delegate.installInController(additionalInit, subsystemXml);
}
/**
* Create a new controller with the passed in operations.
*
* @param bootOperations the operations
* @deprecated Use {@link #createKernelServicesBuilder(AdditionalInitialization)} instead
*/
@Deprecated
@SuppressWarnings("deprecation")
protected KernelServices installInController(List<ModelNode> bootOperations) throws Exception {
return delegate.installInController(bootOperations);
}
/**
* Create a new controller with the passed in operations.
*
* @param additionalInit Additional initialization that should be done to the parsers, controller and service container before initializing our extension
* @param bootOperations the operations
* @deprecated Use {@link #createKernelServicesBuilder(AdditionalInitialization)} instead
*/
@Deprecated
protected KernelServices installInController(AdditionalInitialization additionalInit, List<ModelNode> bootOperations) throws Exception {
return delegate.installInController(additionalInit, bootOperations);
}
/**
* Creates a new kernel services builder used to create a new controller containing the subsystem being tested
*
* @param additionalInit Additional initialization that should be done to the parsers, controller and service container before initializing our extension
*/
protected KernelServicesBuilder createKernelServicesBuilder(AdditionalInitialization additionalInit) {
return delegate.createKernelServicesBuilder(additionalInit);
}
/**
* Gets the ProcessType to use when initializing the parsers. Defaults to {@link ProcessType#EMBEDDED_SERVER}
* To tweak the process type when installing a controller, override {@link AdditionalInitialization} and pass in to
* {@link #createKernelServicesBuilder(AdditionalInitialization)} instead.
*
* @return the process type
*/
protected final ProcessType getProcessType() {
return ProcessType.EMBEDDED_SERVER;
}
/**
* Checks that the result was successful and gets the real result contents
*
* @param result the result to check
* @return the result contents
*/
protected static ModelNode checkResultAndGetContents(ModelNode result) {
return ModelTestUtils.checkResultAndGetContents(result);
}
/**
* Checks that the result was successful
*
* @param result the result to check
* @return the result contents
*/
protected static ModelNode checkOutcome(ModelNode result) {
return ModelTestUtils.checkOutcome(result);
}
/**
* Checks that the subystem resources can be removed, i.e. that people have registered
* working 'remove' operations for every 'add' level. This cannot be called after the
* kernelServices have been shut down.
*
*
* @param kernelServices the kernel services used to access the controller
*/
protected void assertRemoveSubsystemResources(KernelServices kernelServices) {
delegate.assertRemoveSubsystemResources(kernelServices);
}
/**
* Checks that the subystem resources can be removed, i.e. that people have registered
* working 'remove' operations for every 'add' level.
*
* @param kernelServices the kernel services used to access the controller
* @param ignoredChildAddresses child addresses that should not be removed, they are managed by one of the parent resources.
* This set cannot contain the subsystem resource itself
*/
protected void assertRemoveSubsystemResources(KernelServices kernelServices, Set<PathAddress> ignoredChildAddresses) {
delegate.assertRemoveSubsystemResources(kernelServices, ignoredChildAddresses);
}
/**
* Grabs the current root resource
*
* @param kernelServices the kernel services used to access the controller
*/
protected Resource grabRootResource(ModelTestKernelServices<?> kernelServices) {
return ModelTestModelControllerService.grabRootResource(kernelServices);
}
/**
* Dumps the target subsystem resource description to DMR format, needed by TransformerRegistry for non-standard subsystems
*
* @param kernelServices the kernel services for the started controller
* @param modelVersion the target subsystem model version
* @deprecated this might no longer be needed following refactoring of TransformerRegistry
*/
@Deprecated
@SuppressWarnings("deprecation")
protected void generateLegacySubsystemResourceRegistrationDmr(KernelServices kernelServices, ModelVersion modelVersion) throws IOException {
delegate.generateLegacySubsystemResourceRegistrationDmr(kernelServices, modelVersion);
}
/**
* Checks that the transformed model is the same as the model built up in the legacy subsystem controller via the transformed operations,
* and that the transformed model is valid according to the resource definition in the legacy subsystem controller.
*
* @param kernelServices the main kernel services
* @param modelVersion the model version of the targeted legacy subsystem
* @return the whole model of the legacy controller
*/
protected ModelNode checkSubsystemModelTransformation(KernelServices kernelServices, ModelVersion modelVersion) throws IOException, OperationFailedException {
return checkSubsystemModelTransformation(kernelServices, modelVersion, null, true);
}
/**
* Checks that the transformed model is the same as the model built up in the legacy subsystem controller via the transformed operations,
* and that the transformed model is valid according to the resource definition in the legacy subsystem controller.
*
* @param kernelServices the main kernel services
* @param modelVersion the model version of the targeted legacy subsystem
* @param legacyModelFixer use to touch up the model read from the legacy controller, use sparingly when the legacy model is just wrong. May be {@code null}
* @return the whole model of the legacy controller
*/
protected ModelNode checkSubsystemModelTransformation(KernelServices kernelServices, ModelVersion modelVersion, ModelFixer legacyModelFixer) throws IOException, OperationFailedException {
return checkSubsystemModelTransformation(kernelServices, modelVersion, legacyModelFixer, true);
}
/**
* Checks that the transformed model is the same as the model built up in the legacy subsystem controller via the transformed operations,
* and that the transformed model is valid according to the resource definition in the legacy subsystem controller.
*
* @param kernelServices the main kernel services
* @param modelVersion the model version of the targeted legacy subsystem
* @param legacyModelFixer use to touch up the model read from the legacy controller, use sparingly when the legacy model is just wrong. May be {@code null}
* @return the whole model of the legacy controller
*/
protected ModelNode checkSubsystemModelTransformation(KernelServices kernelServices, ModelVersion modelVersion,
ModelFixer legacyModelFixer, boolean includeDefaults) throws IOException, OperationFailedException {
return delegate.checkSubsystemModelTransformation(kernelServices, modelVersion, legacyModelFixer, includeDefaults);
}
/**
* Compares two models to make sure that they are the same
*
* @param node1 the first model
* @param node2 the second model
*/
protected void compare(ModelNode node1, ModelNode node2) {
ModelTestUtils.compare(node1, node2);
}
/**
* Resolve two models and compare them to make sure that they have same
* content after expression resolution
*
* @param node1 the first model
* @param node2 the second model
*/
protected void resolveandCompareModel(ModelNode node1, ModelNode node2) {
ModelTestUtils.resolveAndCompareModels(node1, node2);
}
/**
* Compares two models to make sure that they are the same
*
* @param node1 the first model
* @param node2 the second model
* @param ignoreUndefined {@code true} if keys containing undefined nodes should be ignored
*/
protected void compare(ModelNode node1, ModelNode node2, boolean ignoreUndefined) {
ModelTestUtils.compare(node1, node2, ignoreUndefined);
}
/**
* Normalize and pretty-print XML so that it can be compared using string
* compare. The following code does the following: - Removes comments -
* Makes sure attributes are ordered consistently - Trims every element -
* Pretty print the document
*
* @param xml The XML to be normalized
* @return The equivalent XML, but now normalized
*/
protected String normalizeXML(String xml) throws Exception {
return ModelTestUtils.normalizeXML(xml);
}
public static void validateModelDescriptions(PathAddress address, ManagementResourceRegistration reg) {
ModelTestUtils.validateModelDescriptions(address, reg);
}
/**
* Validate the marshalled xml without adjusting the namespaces for the original and marshalled xml.
*
* @param configId the id of the xml configuration
* @param original the original subsystem xml
* @param marshalled the marshalled subsystem xml
* @throws Exception
*/
protected void compareXml(String configId, final String original, final String marshalled) throws Exception {
ModelTestUtils.compareXml(original, marshalled);
}
/**
* Validate the marshalled xml without adjusting the namespaces for the original and marshalled xml.
*
* @param configId TODO
* @param original the original subsystem xml
* @param marshalled the marshalled subsystem xml
* @param ignoreNamespace if {@code true} the subsystem's namespace is ignored, otherwise it is taken into account when comparing the normalized xml.
* @throws Exception
*/
protected void compareXml(String configId, final String original, final String marshalled, final boolean ignoreNamespace) throws Exception {
ModelTestUtils.compareXml(original, marshalled, ignoreNamespace);
}
/**
* Uses {@link org.junit.Assume#assumeTrue(boolean)} to check that -Djboss.test.transformers.eap is set AND the EAP repository is reachable. If those two conditions are not true,
* an {@link org.junit.internal.AssumptionViolatedException} is thrown causing the test to be conditionally ignored. The purpose of this method is to be called at the beginning of transformers
* tests against legacy EAP versions. If the internal EAP repository is not available to the caller, the test is conditionally @Ignored if running with the standard JUnit test runner.
* This means that no special setup is needed for being on the VPN or not. The {@code -Djboss.test.transformers.eap} is required to not add unnecessary time to every day builds.
*
* <p>
* Normally you should not have to call this method, tests involving EAP do something similar as part of calling
* {@link KernelServicesBuilder#createLegacyKernelServicesBuilder(AdditionalInitialization, org.jboss.as.model.test.ModelTestControllerVersion, ModelVersion)} if the
* passed in ModelTestControllerVersion is an EAP version.
*/
protected void ignoreThisTestIfEAPRepositoryIsNotReachable() {
Assume.assumeTrue(EAPRepositoryReachableUtil.isReachable());
}
}