/*
* RHQ Management Platform
* Copyright (C) 2005-2010 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.bundle.filetemplate.recipe;
import java.util.Map;
import java.util.Set;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.rhq.core.system.SystemInfoFactory;
import org.rhq.core.util.updater.DeploymentProperties;
@Test
public class RecipeParserTest {
private StringBuilder recipe;
@BeforeMethod
public void cleanRecipeBeforeMethod() {
cleanRecipe();
}
public void testBundleCommand() throws Exception {
addRecipeCommand("bundle --version \"1.0\" --name \"my-name\" --description \"my description here\"");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
DeploymentProperties props = context.getDeploymentProperties();
assert props.getBundleName().equals("my-name");
assert props.getBundleVersion().equals("1.0");
assert props.getDescription().equals("my description here");
assert props.getDeploymentId() == 0;
cleanRecipe();
addRecipeCommand("bundle --name=my-name --version=1.0 \"--description=my description here\"");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
props = context.getDeploymentProperties();
assert props.getBundleName().equals("my-name");
assert props.getBundleVersion().equals("1.0");
assert props.getDescription().equals("my description here");
assert props.getDeploymentId() == 0;
// use the "-arg value" notation, as opposed to "--arg=value"
cleanRecipe();
addRecipeCommand("bundle -n my-name2 -v 2.0 -d \"my description here 2\"");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
props = context.getDeploymentProperties();
assert props.getBundleName().equals("my-name2");
assert props.getBundleVersion().equals("2.0");
assert props.getDescription().equals("my description here 2");
assert props.getDeploymentId() == 0;
// show that you only need name and version but not description
cleanRecipe();
addRecipeCommand("bundle -n one -v 1.0");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
props = context.getDeploymentProperties();
assert props.getBundleName().equals("one");
assert props.getBundleVersion().equals("1.0");
assert props.getDescription() == null;
assert props.getDeploymentId() == 0;
// show that you need name and version
cleanRecipe();
addRecipeCommand("bundle -n one");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
try {
parser.parseRecipe(context);
assert false : "should not have parsed, missing version";
} catch (Exception ok) {
// expected
}
cleanRecipe();
addRecipeCommand("bundle --name \" \" -v 1");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
try {
parser.parseRecipe(context);
assert false : "should not have parsed, blank name not allowed";
} catch (Exception ok) {
// expected
}
cleanRecipe();
addRecipeCommand("bundle --version \" \" -n name");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
try {
parser.parseRecipe(context);
assert false : "should not have parsed, blank version not allowed";
} catch (Exception ok) {
// expected
}
cleanRecipe();
addRecipeCommand("bundle -v 1.0");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
try {
parser.parseRecipe(context);
assert false : "should not have parsed, missing name";
} catch (Exception ok) {
// expected
}
// show that you can't have two bundle commands in the same recipe
cleanRecipe();
addRecipeCommand("bundle -n first -v 1.0");
addRecipeCommand("bundle -n second -v 2.0");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
try {
parser.parseRecipe(context);
assert false : "should not have parsed, not allowed multiple bundle commands";
} catch (Exception ok) {
// expected
}
}
public void testConfigDefRecipe() throws Exception {
addRecipeCommand("configdef --name=my.first.property");
addRecipeCommand("configdef -n custom.prop");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Set<String> vars = context.getReplacementVariables();
assert vars.size() == 2 : vars;
assert vars.contains("my.first.property");
assert vars.contains("custom.prop");
assert context.getReplacementVariableDefaultValues().isEmpty();
cleanRecipe();
addRecipeCommand("configdef -n custom.prop -d 8080");
addRecipeCommand("configdef --name another.prop --default some.default.value");
parser = new RecipeParser();
context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
vars = context.getReplacementVariables();
assert vars.size() == 2 : vars;
assert vars.contains("custom.prop");
assert vars.contains("another.prop");
assert context.getReplacementVariableDefaultValues().containsKey("another.prop");
assert context.getReplacementVariableDefaultValues().get("another.prop").equals("some.default.value");
}
public void testRealizeRecipe() throws Exception {
addRecipeCommand("realize --file=@@opt.dir@@/config.ini");
addRecipeCommand("realize -f @@opt2.dir@@/config2.ini");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Set<String> files = context.getRealizedFiles();
assert files.size() == 2 : files;
assert files.contains("@@opt.dir@@/config.ini") : files;
assert files.contains("@@opt2.dir@@/config2.ini") : files;
}
public void testFileRecipe() throws Exception {
addRecipeCommand("file --source=run-me.sh --destination=/opt/run.sh");
addRecipeCommand("file -s META-INF/another.xml -d /etc/another.xml");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getFiles();
assert files.size() == 2 : files;
assert files.get("run-me.sh") != null : files;
assert files.get("run-me.sh").equals("/opt/run.sh") : files;
assert files.get("META-INF/another.xml") != null : files;
assert files.get("META-INF/another.xml").equals("/etc/another.xml") : files;
}
public void testScriptRecipe() throws Exception {
addRecipeCommand("script run-me.sh");
addRecipeCommand("script lots-o-params.sh -d /opt/jboss -- foo.txt \"hello world\"");
addRecipeCommand("script run-me.sh with params");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Set<String> scripts = context.getScriptFiles();
assert scripts.size() == 2 : scripts;
assert scripts.contains("run-me.sh") : scripts;
assert scripts.contains("lots-o-params.sh") : scripts;
}
public void testSimpleRecipeReplacementVariables() throws Exception {
addRecipeCommand("# @@ ignored.inside.comment @@");
addRecipeCommand("deploy -f jboss.tar -d \"@@ opt.dir @@/jboss\"");
addRecipeCommand("deploy -f tomcat.tar -d @@opt.dir@@/tomcat");
addRecipeCommand("deploy -f jboss.zip -d @@rhq.system.hostname@@/opt/tomcat"); // this is ignored, its an agent fact variable
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.containsKey("jboss.tar") : files;
assert files.get("jboss.tar").equals("@@ opt.dir @@/jboss") : files;
assert files.containsKey("tomcat.tar") : files;
assert files.get("tomcat.tar").equals("@@opt.dir@@/tomcat") : files;
assert files.containsKey("jboss.zip") : files;
assert files.get("jboss.zip").equals("@@rhq.system.hostname@@/opt/tomcat") : files;
assert context.getReplacementVariables().contains("opt.dir") : context.getReplacementVariables();
assert context.getReplacementVariables().size() == 1 : context.getReplacementVariables();
}
public void testSimpleRecipeReplaceReplacementVariables() throws Exception {
addRecipeCommand("deploy -f jboss.tar -d @@ opt.dir @@/jboss");
addRecipeCommand("deploy -f jboss2.tar -d @@unknown@@/jboss");
addRecipeCommand("deploy -f jboss3.tar -d @@ rhq.system.hostname @@/jboss");
RecipeParser parser = new RecipeParser();
parser.setReplaceReplacementVariables(true);
RecipeContext context = new RecipeContext(getRecipe());
context.addReplacementVariableValue("opt.dir", "/foo/bar");
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.containsKey("jboss.tar") : files;
assert files.get("jboss.tar").equals("/foo/bar/jboss") : files;
assert files.containsKey("jboss2.tar") : files;
assert files.get("jboss2.tar").equals("@@unknown@@/jboss") : files;
assert files.containsKey("jboss3.tar") : files;
assert files.get("jboss3.tar").equals(SystemInfoFactory.createSystemInfo().getHostname() + "/jboss") : files;
}
public void testSimpleRecipeReplaceJavaSystemPropertyReplacementVariables() throws Exception {
/*
java.util.Properties sysprops = System.getProperties();
for (Map.Entry<Object, Object> sysprop : sysprops.entrySet()) {
if (sysprop.getValue().toString().length() < 60) {
System.out.println("==>" + sysprop.getKey() + "=" + sysprop.getValue());
}
}
*/
addRecipeCommand("deploy -f jboss1.tar -d @@rhq.system.sysprop.java.io.tmpdir@@");
addRecipeCommand("deploy -f jboss2.tar -d @@rhq.system.sysprop.file.separator@@");
//addRecipeCommand("deploy -f jboss3.tar -d @@rhq.system.sysprop.line.separator@@"); // can't test this here
addRecipeCommand("deploy -f jboss4.tar -d @@rhq.system.sysprop.path.separator@@");
addRecipeCommand("deploy -f jboss5.tar -d \"@@rhq.system.sysprop.java.home@@\"");
addRecipeCommand("deploy -f jboss6.tar -d @@rhq.system.sysprop.java.version@@");
//addRecipeCommand("deploy -f jboss7.tar -d @@rhq.system.sysprop.user.timezone@@"); // sometimes this is empty
//addRecipeCommand("deploy -f jboss8.tar -d @@rhq.system.sysprop.user.region@@"); // sometimes this doesn't exist
addRecipeCommand("deploy -f jboss9.tar -d @@rhq.system.sysprop.user.country@@");
addRecipeCommand("deploy -f jboss10.tar -d @@rhq.system.sysprop.user.language@@");
addRecipeCommand("deploy -f jboss11.tar -d @@rhq.system.sysprop.custom.sysprop@@"); // non-standard sysprop
RecipeParser parser = new RecipeParser();
parser.setReplaceReplacementVariables(true);
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.get("jboss1.tar").equals(System.getProperty("java.io.tmpdir").replace('\\', '/')) : files;
assert files.get("jboss2.tar").equals(System.getProperty("file.separator").replace('\\', '/')) : files;
//assert files.get("jboss3.tar").equals(System.getProperty("line.separator")) : files;
assert files.get("jboss4.tar").equals(System.getProperty("path.separator")) : files;
assert files.get("jboss5.tar").equals(System.getProperty("java.home").replace('\\', '/')) : files;
assert files.get("jboss6.tar").equals(System.getProperty("java.version")) : files;
//assert files.get("jboss7.tar").equals(System.getProperty("user.timezone")) : files;
//assert files.get("jboss8.tar").equals(System.getProperty("user.region")) : files;
assert files.get("jboss9.tar").equals(System.getProperty("user.country")) : files;
assert files.get("jboss10.tar").equals(System.getProperty("user.language")) : files;
assert files.get("jboss11.tar").equals("@@rhq.system.sysprop.custom.sysprop@@") : files;
// now set a custom system property and see that it does NOT get replaced - we ignore custom sysprops!
System.setProperty("custom.sysprop", "MY/CUSTOM/PROPERTY/HERE");
parser = new RecipeParser();
parser.setReplaceReplacementVariables(true);
context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
files = context.getDeployFiles();
assert files.get("jboss11.tar").equals("@@rhq.system.sysprop.custom.sysprop@@") : files;
}
public void testSimpleRecipe() throws Exception {
addRecipeCommand("deploy -f jboss.tar -d /opt/jboss");
addRecipeCommand("deploy -f tomcat.tar -d /opt/tomcat");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.containsKey("jboss.tar") : files;
assert files.get("jboss.tar").equals("/opt/jboss") : files;
assert files.containsKey("tomcat.tar") : files;
assert files.get("tomcat.tar").equals("/opt/tomcat") : files;
}
public void testSimpleRecipeWithQuotes() throws Exception {
addRecipeCommand("deploy -f jboss1.zip -d \"/opt/jboss1\"");
addRecipeCommand("deploy -f jboss.tar --directory='/opt/jboss'");
addRecipeCommand("deploy -f tomcat.tar \"--directory=/opt/tomcat\"");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.containsKey("jboss1.zip") : files;
assert files.get("jboss1.zip").equals("/opt/jboss1") : files;
assert files.containsKey("jboss.tar") : files;
assert files.get("jboss.tar").equals("'/opt/jboss'") : files;
assert files.containsKey("tomcat.tar") : files;
assert files.get("tomcat.tar").equals("/opt/tomcat") : files;
}
public void testSimpleRecipeWithBackslashes() throws Exception {
addRecipeCommand("deploy -f jboss1.zip -d \"C:\\opt\\jboss1\"");
addRecipeCommand("deploy -f tomcat.tar \"--directory=C:\\Documents and Settings\\user\\\"");
addRecipeCommand("deploy -f jboss2.zip -d C:\\opt\\jboss1");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.containsKey("jboss1.zip") : files;
assert files.get("jboss1.zip").equals("C:/opt/jboss1") : files;
assert files.containsKey("tomcat.tar") : files;
assert files.get("tomcat.tar").equals("C:/Documents and Settings/user/") : files;
assert files.containsKey("jboss2.zip") : files;
assert files.get("jboss2.zip").equals("C:/opt/jboss1") : files;
}
public void testSimpleRecipeError() throws Exception {
addRecipeCommand("deploy -f jboss.tar");
RecipeParser parser = new RecipeParser();
try {
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
assert false : "This should have failed - need to provide a -d to the deploy command";
} catch (Exception ok) {
// to be expected
}
cleanRecipe();
addRecipeCommand("deploy -d /opt/jboss");
try {
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
assert false : "This should have failed - need to provide a -f to the deploy command";
} catch (Exception ok) {
// to be expected
}
}
public void testSimpleRecipeComments() throws Exception {
addRecipeCommand("");
addRecipeCommand("#");
addRecipeCommand("### comment here");
addRecipeCommand("deploy -f jboss.tar -d /opt/jboss");
addRecipeCommand("");
addRecipeCommand("#");
addRecipeCommand("### comment here");
addRecipeCommand("deploy -f tomcat.tar -d /opt/tomcat");
addRecipeCommand("");
addRecipeCommand("#");
addRecipeCommand("### comment here");
addRecipeCommand("");
RecipeParser parser = new RecipeParser();
RecipeContext context = new RecipeContext(getRecipe());
parser.parseRecipe(context);
Map<String, String> files = context.getDeployFiles();
assert files.containsKey("jboss.tar") : files;
assert files.get("jboss.tar").equals("/opt/jboss") : files;
assert files.containsKey("tomcat.tar") : files;
assert files.get("tomcat.tar").equals("/opt/tomcat") : files;
}
private void cleanRecipe() {
this.recipe = new StringBuilder();
}
private void addRecipeCommand(String commandLine) {
this.recipe.append(commandLine).append("\n");
}
private String getRecipe() {
return this.recipe.toString();
}
}