Repository: wso2/testgrid
Issue: Cannot run two cloudformation-based test plans in parallel

**Description:**
Cannot run two cloudformation-based test plans in parallel. There will be a naming conflict if both cloudformation scripts tried to create stacks with same name.

We need to randomize the strings in order to fix this.

**Affected Product Version:**
0.9.0-m11

**Steps to reproduce:**
See above.

**Related Issues:**
N/A

Changed files:
core/src/main/java/org/wso2/testgrid/core/command/GenerateTestPlanCommand.java, common/src/main/java/org/wso2/testgrid/common/util/StringUtil.java

diff --git a/common/src/main/java/org/wso2/testgrid/common/util/StringUtil.java b/common/src/main/java/org/wso2/testgrid/common/util/StringUtil.java
index 50d2fca8..6dc78269 100644
--- a/common/src/main/java/org/wso2/testgrid/common/util/StringUtil.java
+++ b/common/src/main/java/org/wso2/testgrid/common/util/StringUtil.java
@@ -17,6 +17,8 @@
  */
 package org.wso2.testgrid.common.util;
 
+import java.util.Random;
+
 /**
  * Utility class to handle {@link String} related operations.
  *
@@ -47,4 +49,21 @@ public class StringUtil {
         }
         return stringBuilder.toString();
     }
+
+    /**
+     * Generates a random string with the given character count using the below charset as input:
+     * <i>ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890</i>
+     * @param characterCount number of characters
+     * @return a random string
+     */
+    public static String generateRandomString(int characterCount) {
+        final String saltChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+        StringBuilder salt = new StringBuilder();
+        Random rnd = new Random();
+        while (salt.length() < characterCount) {
+            int index = (int) (rnd.nextFloat() * saltChars.length());
+            salt.append(saltChars.charAt(index));
+        }
+        return salt.toString();
+    }
 }
diff --git a/core/src/main/java/org/wso2/testgrid/core/command/GenerateTestPlanCommand.java b/core/src/main/java/org/wso2/testgrid/core/command/GenerateTestPlanCommand.java
index 33519ee2..8615efce 100644
--- a/core/src/main/java/org/wso2/testgrid/core/command/GenerateTestPlanCommand.java
+++ b/core/src/main/java/org/wso2/testgrid/core/command/GenerateTestPlanCommand.java
@@ -22,6 +22,7 @@ import org.kohsuke.args4j.Option;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.wso2.testgrid.common.Product;
+import org.wso2.testgrid.common.Script;
 import org.wso2.testgrid.common.exception.CommandExecutionException;
 import org.wso2.testgrid.common.infrastructure.InfrastructureCombination;
 import org.wso2.testgrid.common.infrastructure.InfrastructureParameter;
@@ -61,6 +62,7 @@ public class GenerateTestPlanCommand implements Command {
 
     private static final Logger logger = LoggerFactory.getLogger(GenerateTestPlanCommand.class);
     private static final String YAML_EXTENSION = ".yaml";
+    private static final int RANDOMIZED_STR_LENGTH = 6;
 
     @Option(name = "--product",
             usage = "Product Name",
@@ -164,6 +166,8 @@ public class GenerateTestPlanCommand implements Command {
 
         for (String deploymentPattern : deploymentPatterns) {
             for (InfrastructureCombination combination : combinations) {
+                setUniqueScriptName(inputTestConfig.getInfrastructure().getScripts());
+
                 TestConfig testConfig = new TestConfig();
                 testConfig.setProductName(inputTestConfig.getProductName());
                 testConfig.setDeploymentPatterns(Collections.singletonList(deploymentPattern));
@@ -179,6 +183,18 @@ public class GenerateTestPlanCommand implements Command {
         return testConfigurations;
     }
 
+    /**
+     * We need unique script names because this is referenced as an id
+     * for cloudformation stack name etc.
+     *
+     * @param scripts list of Scripts in a given test-config.
+     */
+    private void setUniqueScriptName(List<Script> scripts) {
+        for (Script script : scripts) {
+            script.setName(script.getName() + '-' + StringUtil.generateRandomString(RANDOMIZED_STR_LENGTH));
+        }
+    }
+
     private List<Map<String, Object>> toConfigAwareInfrastructureCombination(Set<InfrastructureParameter> parameters) {
         Map<String, Object> configAwareInfrastructureCombination = new HashMap<>(parameters.size());
         for (InfrastructureParameter parameter : parameters) {