/*
* JBoss, Home of Professional Open Source
* Copyright 2015, Red Hat Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.test.integration.domain.management.cli;
import static java.nio.file.Files.readAllLines;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.jboss.as.test.integration.domain.management.util.DomainTestSupport;
import org.jboss.as.test.integration.domain.suites.CLITestSuite;
import org.jboss.as.test.integration.management.base.AbstractCliTestBase;
import org.jboss.logging.Logger;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Test for providing profile cloning ability (runtime (CLI)) to create
* new profiles based on existing JBoss profiles.
*
* Test clone "default" profile to "clone-profile-test-case-default" profile.
*
* https://issues.jboss.org/browse/WFCORE-797
*
* @author Marek Kopecky <mkopecky@redhat.com>
*/
public class CloneProfileTestCase extends AbstractCliTestBase {
private static Logger log = Logger.getLogger(CloneProfileTestCase.class);
private static final String ORIGINAL_PROFILE = "default";
private static final String NEW_PROFILE = "clone-profile-test-case-default";
/**
* Domain configuration
*/
private static File domainCfg;
@BeforeClass
public static void beforeClass() throws Exception {
DomainTestSupport domainSupport = CLITestSuite.createSupport(CloneProfileTestCase.class.getSimpleName());
AbstractCliTestBase.initCLI(DomainTestSupport.masterAddress);
File masterDir = new File(domainSupport.getDomainMasterConfiguration().getDomainDirectory());
domainCfg = new File(masterDir, "configuration"
+ File.separator + "testing-domain-standard.xml");
}
@AfterClass
public static void afterClass() throws Exception {
AbstractCliTestBase.closeCLI();
CLITestSuite.stopSupport();
}
/**
* Sends command line to CLI, validate and return output.
*
* @param line command line
* @return CLI output
*/
private String cliRequest(String line, boolean successRequired) {
log.info(line);
cli.sendLine(line);
String output = cli.readOutput();
if (successRequired) {
assertTrue("CLI command \"" + line + " doesn't contain \"success\"", output.contains("success"));
}
return output;
}
private String readFileToString(File file) throws IOException {
StringBuilder builder = new StringBuilder();
for(String line : readAllLines(file.toPath())){
builder.append(line);
}
return builder.toString();
}
@Test
public void testProfile() throws IOException, SAXException, ParserConfigurationException {
// get domain configuration
String domainCfgContent = readFileToString(domainCfg);
assertFalse("Domain configuration is not initialized correctly.", domainCfgContent.contains(NEW_PROFILE));
// clone profile
cliRequest("/profile=" + ORIGINAL_PROFILE + ":clone(to-profile=" + NEW_PROFILE + ")", true);
// get and check submodules
String originSubmodules = cliRequest("ls /profile=" + ORIGINAL_PROFILE + "/subsystem", false);
String newSubmodules = cliRequest("ls /profile=" + NEW_PROFILE + "/subsystem", false);
assertEquals("New profile has different submodules than origin profile.", originSubmodules, newSubmodules);
// check domain configuration
domainCfgContent = readFileToString(domainCfg);
assertTrue("Domain configuration doesn't contain " + NEW_PROFILE + " profile.", domainCfgContent.contains(NEW_PROFILE));
//check xml
checkXML();
// Remove the new profile (WFCORE-808 test)
cliRequest("/profile=" + NEW_PROFILE + ":remove", true);
// check domain configuration
domainCfgContent = readFileToString(domainCfg);
assertFalse("Domain configuration still contains " + NEW_PROFILE + " profile.", domainCfgContent.contains(NEW_PROFILE));
}
/**
* Check subsystems from original and new profile
*/
private void checkXML() throws ParserConfigurationException, IOException, SAXException {
// parse xml
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse(domainCfg);
// get subsystems
List<String> originalSubsystemsInXML = findProfileSubsystemsInXML(doc, ORIGINAL_PROFILE);
List<String> newSubsystemsInXML = findProfileSubsystemsInXML(doc, NEW_PROFILE);
// basic check
if (originalSubsystemsInXML == null || newSubsystemsInXML == null) {
Assert.fail("Error during parsing domain.xml file");
}
if (originalSubsystemsInXML.size() != newSubsystemsInXML.size()) {
Assert.fail("Different subsystems in original and new profile in domain.xml file");
}
// log subsystems
log.info("Subsystems in original profile in xml: " + originalSubsystemsInXML);
log.info("Subsystems in new profile in xml: " + newSubsystemsInXML);
// check order
Iterator<String> itOriginal = originalSubsystemsInXML.iterator();
Iterator<String> itNew = newSubsystemsInXML.iterator();
while (itOriginal.hasNext()) {
String originalSubsystem = itOriginal.next();
String newSubsystem = itNew.next();
if (!originalSubsystem.equals(newSubsystem)) {
Assert.fail("Different order of subsystems in cloned profile.");
}
}
}
/**
* Parse root node
*/
private List<String> findProfileSubsystemsInXML(Document doc, String profileName) {
List<String> output = null;
if (!doc.hasChildNodes()) {
return output;
}
NodeList nodeList = doc.getChildNodes();
return findProfileSubsystems(nodeList, profileName);
}
/**
* Find profile node in XML
*/
private List<String> findProfileSubsystems(NodeList nodeList, String profileName) {
List<String> output = null;
for (int i = 0; i < nodeList.getLength(); i++) {
Node tempNode = nodeList.item(i);
if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
String nodeName = tempNode.getNodeName();
if (!nodeName.contains("domain") && !nodeName.contains("profiles") && !nodeName.contains("profile")) {
continue;
}
if (nodeName.equals("profile") && tempNode.hasAttributes()) {
NamedNodeMap nodeMap = tempNode.getAttributes();
for (int j = 0; j < nodeMap.getLength(); j++) {
Node node = nodeMap.item(j);
if (node.getNodeName().equals("name") && node.getNodeValue().equals(profileName)) {
return findSubsystemsInProfile(tempNode.getChildNodes());
}
}
}
if (!nodeName.equals("profile") && tempNode.hasChildNodes()) {
return findProfileSubsystems(tempNode.getChildNodes(), profileName);
}
}
}
return output;
}
/**
* Find subsystems from profile node
*/
private List<String> findSubsystemsInProfile(NodeList nodeList) {
List<String> output = new LinkedList<>();
for (int i = 0; i < nodeList.getLength(); i++) {
Node tempNode = nodeList.item(i);
if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
String nodeName = tempNode.getNodeName();
if (!nodeName.contains("subsystem")) {
continue;
}
if (tempNode.hasAttributes()) {
NamedNodeMap nodeMap = tempNode.getAttributes();
for (int j = 0; j < nodeMap.getLength(); j++) {
Node node = nodeMap.item(j);
if (node.getNodeName().equals("xmlns")) {
output.add(node.getNodeValue());
}
}
}
}
}
return output;
}
}