/* * JBoss, Home of Professional Open Source. * Copyright 2015, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file 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.cli.parsing.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.jboss.as.cli.CommandFormatException; import org.jboss.as.cli.operation.OperationRequestAddress; import org.jboss.as.cli.operation.ParsedCommandLine; import org.jboss.as.cli.operation.impl.DefaultCallbackHandler; import org.jboss.as.cli.util.CLIExpressionResolver; import org.jboss.dmr.ModelNode; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.wildfly.security.manager.WildFlySecurityManager; /** * System property replacement tests. * * @author Alexey Loubyansky */ public class PropertyReplacementTestCase { private static final String NODE_TYPE_PROP_NAME = "test.node-type"; private static final String NODE_TYPE_PROP_VALUE = "test-node-type"; private static final String NODE_NAME_PROP_NAME = "test.node-name"; private static final String NODE_NAME_PROP_VALUE = "test-node-name"; private static final String OP_PROP_NAME = "test.op-name"; private static final String OP_PROP_VALUE = "test-op"; private static final String OP_PROP_PROP_NAME = "test.prop-name"; private static final String OP_PROP_PROP_VALUE = "test-prop"; private static final String PROP_PART1_NAME = "test.p1"; private static final String PROP_PART1_VALUE = "test"; private static final String PROP_PART2_NAME = "test.p2"; private static final String PROP_PART2_VALUE = "op-name"; private static final String PROP_RECURSIVE_NAME = "test.prop.recursive"; private static final String PROP_RECURSIVE_VALUE = "${" + OP_PROP_NAME + "}"; private static final String ENV_PROP_NAME = "env.test.prop"; private static final String ENV_PROP_VALUE = "sysprop"; private static final String EMPTY_PROP_NAME = "test.node-name-empty"; // an empty property private static final String EMPTY_PROP_VALUE = ""; private static final String PREFIX = "prefix"; @BeforeClass public static void setup() { WildFlySecurityManager.setPropertyPrivileged(NODE_TYPE_PROP_NAME, NODE_TYPE_PROP_VALUE); WildFlySecurityManager.setPropertyPrivileged(NODE_NAME_PROP_NAME, NODE_NAME_PROP_VALUE); WildFlySecurityManager.setPropertyPrivileged(OP_PROP_NAME, OP_PROP_VALUE); WildFlySecurityManager.setPropertyPrivileged(OP_PROP_PROP_NAME, OP_PROP_PROP_VALUE); WildFlySecurityManager.setPropertyPrivileged(PROP_PART1_NAME, PROP_PART1_VALUE); WildFlySecurityManager.setPropertyPrivileged(PROP_PART2_NAME, PROP_PART2_VALUE); WildFlySecurityManager.setPropertyPrivileged(PROP_RECURSIVE_NAME, PROP_RECURSIVE_VALUE); WildFlySecurityManager.setPropertyPrivileged(ENV_PROP_NAME, ENV_PROP_VALUE); WildFlySecurityManager.setPropertyPrivileged(EMPTY_PROP_NAME, EMPTY_PROP_VALUE); } @AfterClass public static void cleanup() { WildFlySecurityManager.clearPropertyPrivileged(NODE_TYPE_PROP_NAME); WildFlySecurityManager.clearPropertyPrivileged(NODE_NAME_PROP_NAME); WildFlySecurityManager.clearPropertyPrivileged(OP_PROP_NAME); WildFlySecurityManager.clearPropertyPrivileged(OP_PROP_PROP_NAME); WildFlySecurityManager.clearPropertyPrivileged(PROP_PART1_NAME); WildFlySecurityManager.clearPropertyPrivileged(PROP_PART2_NAME); WildFlySecurityManager.clearPropertyPrivileged(PROP_RECURSIVE_NAME); WildFlySecurityManager.clearPropertyPrivileged(EMPTY_PROP_NAME); } @Test public void testDefaultAsProperty() throws Exception { assertEquals("$test-op", CLIExpressionResolver.resolve("${unknown:$$${test.op-name}}")); assertEquals("test-op", CLIExpressionResolver.resolve("${unknown:${test.op-name}}")); assertEquals("test-op", CLIExpressionResolver.resolve("${test.op-name:${unknown}}")); assertEquals("${unknown1:${unknown2}}", CLIExpressionResolver.resolveOrOriginal("${unknown1:${unknown2}}")); assertEquals("test-op${unknown1}", CLIExpressionResolver.resolveLax("${test.op-name}${unknown1}")); assertEquals("${unknown1}test-op", CLIExpressionResolver.resolveLax("${unknown1}${test.op-name}")); } @Test public void testDollarAsEscape() throws Exception { assertEquals("$test-op", CLIExpressionResolver.resolve("$$${test.op-name}")); } @Test public void testRecursiveReplacement() throws Exception { final ParsedCommandLine parsed = parse("${" + PROP_RECURSIVE_NAME + "}"); assertEquals(OP_PROP_VALUE, parsed.getOperationName()); } @Test public void testNestedReplacement() throws Exception { final ParsedCommandLine parsed = parse("${${" + PROP_PART1_NAME + "}.${" + PROP_PART2_NAME + "}}"); assertEquals(OP_PROP_VALUE, parsed.getOperationName()); } @Test public void testUnresolvedOperationName() { assertFailedToParse(":${" + OP_PROP_NAME + "xxx}"); } @Test public void testOperationName() throws Exception { final ParsedCommandLine parsed = parse(":${" + OP_PROP_NAME + "}"); assertEquals(OP_PROP_VALUE, parsed.getOperationName()); } @Test public void testUnresolvedNodeType() throws Exception { assertFailedToParse("/${" + NODE_TYPE_PROP_NAME + "xxx}=test:op"); } @Test public void testNodeType() throws Exception { final ParsedCommandLine parsed = parse("/${" + NODE_TYPE_PROP_NAME + "}=test:op"); final OperationRequestAddress address = parsed.getAddress(); assertNotNull(address); assertEquals(NODE_TYPE_PROP_VALUE, address.getNodeType()); assertEquals("test", address.getNodeName()); } @Test public void testNodeTypeWithEmptyProperty() throws Exception { final ParsedCommandLine parsed = parse("/" + PREFIX + "${" + EMPTY_PROP_NAME + "}${" + NODE_TYPE_PROP_NAME + "}=test:op"); final OperationRequestAddress address = parsed.getAddress(); assertNotNull(address); assertEquals(PREFIX + NODE_TYPE_PROP_VALUE, address.getNodeType()); assertEquals("test", address.getNodeName()); } @Test public void testUnresolvedNodeName() throws Exception { assertFailedToParse("/test=${" + NODE_TYPE_PROP_NAME + "xxx}:op"); } @Test public void testNodeName() throws Exception { final ParsedCommandLine parsed = parse("/test=${" + NODE_NAME_PROP_NAME + "}:op"); final OperationRequestAddress address = parsed.getAddress(); assertNotNull(address); assertEquals("test", address.getNodeType()); assertEquals(NODE_NAME_PROP_VALUE, address.getNodeName()); } @Test public void testNodeNameWithEmptyProperty() throws Exception { final ParsedCommandLine parsed = parse("/test=" + PREFIX +"${" + EMPTY_PROP_NAME + "}${" + NODE_NAME_PROP_NAME + "}:op"); final OperationRequestAddress address = parsed.getAddress(); assertNotNull(address); assertEquals("test", address.getNodeType()); assertEquals(PREFIX + NODE_NAME_PROP_VALUE, address.getNodeName()); } @Test public void testUnresolvedOperationPropertyName() { assertFailedToParse(":write-attribute(${" + OP_PROP_PROP_NAME + "xxx}=value)"); } @Test public void testOperationPropertyName() throws Exception { final ParsedCommandLine parsed = parse(":write-attribute(${" + OP_PROP_PROP_NAME + "}=test)"); assertEquals("write-attribute", parsed.getOperationName()); assertEquals(parsed.getPropertyValue(OP_PROP_PROP_VALUE), "test"); } @Test public void testOperationNameAndValue() throws Exception { final ParsedCommandLine parsed = parse(":write-attribute(${" + OP_PROP_PROP_NAME + "}=${" + OP_PROP_PROP_NAME + "})"); assertEquals("write-attribute", parsed.getOperationName()); // variables unlike system properties are always resolved assertEquals("${" + OP_PROP_PROP_NAME + "}", parsed.getPropertyValue(OP_PROP_PROP_VALUE)); } @Test public void testUnresolvedCommandName() { assertFailedToParse("${" + OP_PROP_NAME + "xxx}"); } @Test public void testCommandName() throws Exception { final ParsedCommandLine parsed = parse("${" + OP_PROP_NAME + "}"); assertEquals(OP_PROP_VALUE, parsed.getOperationName()); } @Test public void testUnresolvedCommandArgumentName() { assertFailedToParse("command-name --${" + OP_PROP_PROP_NAME + "xxx}=value"); } @Test public void testCommandArgumentName() throws Exception { final ParsedCommandLine parsed = parse("command-name --${" + OP_PROP_PROP_NAME + "}=test"); assertEquals("command-name", parsed.getOperationName()); assertEquals(parsed.getPropertyValue("--" + OP_PROP_PROP_VALUE), "test"); } @Test public void testCommandArgumentNameAndValue() throws Exception { final ParsedCommandLine parsed = parse("command-name --${" + OP_PROP_PROP_NAME + "}=${" + OP_PROP_PROP_NAME + "}"); assertEquals("command-name", parsed.getOperationName()); // there is a different config option whether to resolve argument values assertEquals(parsed.getPropertyValue("--" + OP_PROP_PROP_VALUE), "${" + OP_PROP_PROP_NAME + "}"); } @Test // there is a different config option whether to resolve argument values public void testUnresolvedCommandArgumentValue() throws Exception { final ParsedCommandLine parsed = parse("command-name ${" + OP_PROP_PROP_NAME + "}=test"); assertEquals("command-name", parsed.getOperationName()); assertFalse(parsed.hasProperty(OP_PROP_PROP_VALUE)); assertFalse(parsed.hasProperty("--" + OP_PROP_PROP_VALUE)); assertEquals(1, parsed.getOtherProperties().size()); assertEquals("${" + OP_PROP_PROP_NAME + "}=test", parsed.getOtherProperties().get(0)); } @Test public void testUnresolvedHeaderName() { assertFailedToParse(":write-attribute{${" + OP_PROP_PROP_NAME + "xxx}=value}"); } @Test public void testHeaderNameAndValue() throws Exception { ParsedCommandLine parsed = parse(":write-attribute{${" + OP_PROP_PROP_NAME + "}=${" + OP_PROP_NAME + "}}"); assertEquals("write-attribute", parsed.getOperationName()); assertTrue(parsed.hasHeaders()); assertTrue(parsed.hasHeader(OP_PROP_PROP_VALUE)); ModelNode headers = new ModelNode(); parsed.getLastHeader().addTo(null, headers); assertEquals(OP_PROP_VALUE, headers.get(OP_PROP_PROP_VALUE).asString()); parsed = parse(":write-attribute{${" + OP_PROP_PROP_NAME + "} ${" + OP_PROP_NAME + "}}"); assertEquals("write-attribute", parsed.getOperationName()); assertTrue(parsed.hasHeaders()); assertTrue(parsed.hasHeader(OP_PROP_PROP_VALUE)); headers = new ModelNode(); parsed.getLastHeader().addTo(null, headers); assertEquals(OP_PROP_VALUE, headers.get(OP_PROP_PROP_VALUE).asString()); } @Test public void testSystemPropertiesInTheMix() throws Exception { final ParsedCommandLine parsed = parse("co${" + OP_PROP_NAME + "}${" + OP_PROP_NAME + "} " + "--${" + OP_PROP_PROP_NAME + "}_${" + OP_PROP_PROP_NAME + "}=${" + OP_PROP_PROP_NAME + "}"); assertEquals("co" + OP_PROP_VALUE + OP_PROP_VALUE, parsed.getOperationName()); assertTrue(parsed.getOtherProperties().isEmpty()); assertEquals("${" + OP_PROP_PROP_NAME + "}", parsed.getPropertyValue("--" + OP_PROP_PROP_VALUE + "_" + OP_PROP_PROP_VALUE)); } private void assertFailedToParse(String line) { try { parse(line); fail("should fail to resolve the property"); } catch(CommandFormatException e) { // expected } } protected ParsedCommandLine parse(String line) throws CommandFormatException { DefaultCallbackHandler args = new DefaultCallbackHandler(); args.parse(null, line, null); return args; } }