diff --git a/src/ResourceManager/Compute/Commands.Compute.Test/Commands.Compute.Test.csproj b/src/ResourceManager/Compute/Commands.Compute.Test/Commands.Compute.Test.csproj
index 4ec67785cabd..8683842d8cc4 100644
--- a/src/ResourceManager/Compute/Commands.Compute.Test/Commands.Compute.Test.csproj
+++ b/src/ResourceManager/Compute/Commands.Compute.Test/Commands.Compute.Test.csproj
@@ -168,6 +168,7 @@
+
@@ -233,13 +234,7 @@
Always
-
- Always
-
-
- Always
-
-
+
Always
diff --git a/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/RunnerTests.cs b/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/RunnerTests.cs
new file mode 100644
index 000000000000..5e62cb991c17
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/RunnerTests.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.IdentityModel.Clients.ActiveDirectory;
+using Microsoft.Rest.ClientRuntime.Azure.TestFramework;
+using Xunit;
+
+namespace Microsoft.Azure.Commands.Compute.Test.ScenarioTests
+{
+ public class RunnerTests
+ {
+ [Fact]
+ public void ExecuteRunnerTests()
+ {
+ var mode = Environment.GetEnvironmentVariable("AZURE_TEST_MODE");
+ var csmAuth = Environment.GetEnvironmentVariable("TEST_CSM_ORGID_AUTHENTICATION");
+
+ if (mode == null || csmAuth == null || mode.ToLower() != "record")
+ {
+ return;
+ }
+
+ Assert.False(string.IsNullOrEmpty(csmAuth));
+ Assert.True(csmAuth.Contains("AADTenant"));
+
+ var envDictionary = TestUtilities.ParseConnectionString(csmAuth);
+ var testEnv = new TestEnvironment(envDictionary);
+ Assert.NotNull(testEnv.Tenant);
+ Assert.NotNull(testEnv.SubscriptionId);
+ Assert.NotNull(testEnv.ClientId);
+ Assert.True(envDictionary.ContainsKey("ApplicationSecret"));
+
+ var authenticationContext = new AuthenticationContext("https://login.windows.net/" + testEnv.Tenant);
+ var credential = new ClientCredential(testEnv.ClientId, envDictionary["ApplicationSecret"]);
+
+ var result = authenticationContext.AcquireToken("https://management.core.windows.net/", clientCredential: credential);
+
+ Assert.NotNull(result.AccessToken);
+ envDictionary["RawToken"] = result.AccessToken;
+
+ FixCSMAuthEnvVariable(envDictionary);
+
+ Console.WriteLine(Environment.GetEnvironmentVariable("TEST_CSM_ORGID_AUTHENTICATION"));
+
+ var testFile = File.ReadAllLines("ScenarioTests\\RunnerTests.csv");
+ foreach (var line in testFile)
+ {
+ var tokens = line.Split(';');
+ var className = tokens[0];
+ var type = Type.GetType(className);
+ var constructorInfo = type.GetConstructor(Type.EmptyTypes);
+ for (int i = 1; i < tokens.Length; i++)
+ {
+ var method = tokens[i];
+ var testClassInstance = constructorInfo.Invoke(new object[] {});
+ var testMethod = type.GetMethod(method);
+
+ Console.WriteLine("Invoking method : " + testMethod);
+
+ testMethod.Invoke(testClassInstance, new object[] {});
+
+ Console.WriteLine("Method " + testMethod + " has finished");
+ }
+ }
+ }
+
+ private void FixCSMAuthEnvVariable(IDictionary envDictionary)
+ {
+ var str = string.Empty;
+ foreach (var entry in envDictionary)
+ {
+ if (entry.Key != "AADClientId" && entry.Key != "ApplicationSecret")
+ {
+ str += string.Format("{0}={1};", entry.Key, entry.Value);
+ }
+ }
+
+ Environment.SetEnvironmentVariable("TEST_CSM_ORGID_AUTHENTICATION", str);
+ }
+ }
+}
diff --git a/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/RunnerTests.csv b/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/RunnerTests.csv
new file mode 100644
index 000000000000..8c31d8680a86
--- /dev/null
+++ b/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/RunnerTests.csv
@@ -0,0 +1 @@
+Microsoft.Azure.Commands.Compute.Test.ScenarioTests.VMDynamicTests;RunVMDynamicTests
\ No newline at end of file
diff --git a/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/VMDynamicTests.cs b/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/VMDynamicTests.cs
index 7ebe28708b0b..d22c639b10c6 100644
--- a/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/VMDynamicTests.cs
+++ b/src/ResourceManager/Compute/Commands.Compute.Test/ScenarioTests/VMDynamicTests.cs
@@ -12,6 +12,8 @@
// limitations under the License.
// ----------------------------------------------------------------------------------
+using System;
+using System.IO;
using Microsoft.Azure.Test.HttpRecorder;
using Microsoft.WindowsAzure.Commands.ScenarioTest;
using Xunit;
@@ -24,7 +26,7 @@ public partial class VMDynamicTests
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void RunVMDynamicTests()
{
- ComputeTestController.NewInstance.RunPsTest("Run-VMDynamicTests");
+ ComputeTestController.NewInstance.RunPsTest("Run-VMDynamicTests -num_total_generated_tests 1");
}
}
}
diff --git a/src/ServiceManagement/Common/Commands.ScenarioTest/Commands.ScenarioTest.csproj b/src/ServiceManagement/Common/Commands.ScenarioTest/Commands.ScenarioTest.csproj
index 8620540d600a..be769ee999f0 100644
--- a/src/ServiceManagement/Common/Commands.ScenarioTest/Commands.ScenarioTest.csproj
+++ b/src/ServiceManagement/Common/Commands.ScenarioTest/Commands.ScenarioTest.csproj
@@ -385,6 +385,7 @@
+
diff --git a/src/ServiceManagement/Common/Commands.ScenarioTest/ServiceManagement/UnitTests.cs b/src/ServiceManagement/Common/Commands.ScenarioTest/ServiceManagement/UnitTests.cs
new file mode 100644
index 000000000000..9f2503c66ddb
--- /dev/null
+++ b/src/ServiceManagement/Common/Commands.ScenarioTest/ServiceManagement/UnitTests.cs
@@ -0,0 +1,92 @@
+// ----------------------------------------------------------------------------------
+//
+// Copyright Microsoft Corporation
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ----------------------------------------------------------------------------------
+
+using Microsoft.WindowsAzure.Commands.ServiceManagement.Extensions;
+using System;
+using Xunit;
+
+namespace Microsoft.WindowsAzure.Commands.ScenarioTest
+{
+ public partial class ServiceManagementTests
+ {
+ [Fact]
+ [Trait(Category.Service, Category.ServiceManagement)]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ [Trait(Category.AcceptanceType, Category.BVT)]
+ public void TestExtensionRoleNames()
+ {
+ var roleNames = new string[]
+ {
+ "test Role Name",
+ "!!!!! _____ test Role Name ~~~",
+ "testRoleName",
+ " testRoleName",
+ "testRoleName ",
+ " testRoleName"
+ };
+ var expectedPrefixName = "testRoleName";
+ var expectedExtensionId = "testRoleName-test-test-Ext-0";
+ foreach (var roleName in roleNames)
+ {
+ ExtensionRole er = new ExtensionRole(roleName);
+ Assert.Equal(er.RoleName, roleName.Trim());
+ Assert.Equal(er.PrefixName, expectedPrefixName);
+ Assert.Equal(er.GetExtensionId("test", "test", 0), expectedExtensionId);
+ }
+
+ var longRoleNames = new string[]
+ {
+ "A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789",
+ " A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789 ~~~"
+ };
+
+ // PrefixName = A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789
+ // Extension Name = test
+ // Slot = test
+ // Index = 0
+ // Extension ID Format = {prefix_name_part}-{extension_name_part}-{slot}-Ext-{index}
+ // Extenion ID's Max Length: 60 = 43 + 1 + 4 + 1 + 4 + 1 + 5
+ // i.e. 'A123...E123' + '-' + 'test' + '-' + 'test' + '-' + 'Ext-0'
+ // L=43 L=1 L=4 L=1 L=4 L=1 L=5
+ expectedPrefixName = longRoleNames[0];
+ expectedExtensionId = "A123456789B123456789C123456789D123456789E123-test-test-Ext-0";
+ foreach (var roleName in longRoleNames)
+ {
+ ExtensionRole er = new ExtensionRole(roleName);
+ Assert.Equal(er.RoleName, roleName.Trim());
+ Assert.Equal(er.PrefixName, expectedPrefixName);
+ Assert.Equal(er.GetExtensionId("test", "test", 0), expectedExtensionId);
+ }
+
+
+ var longExtensionNames = longRoleNames;
+ // PrefixName = Default
+ // Extension Name = A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789
+ // Slot = test
+ // Index = 1
+ // Extension ID Format = {prefix_name_part}-{extension_name_part}-{slot}-Ext-{index}
+ // Extenion ID's Max Length: 60 = 1 + 1 + 47 + 1 + 4 + 1 + 5
+ // i.e. 'D' + '-' + 'A123...456' + '-' + 'test' + '-' + 'Ext-0'
+ // L=1 L=1 L=47 L=1 L=4 L=1 L=5
+ expectedExtensionId = "D-A123456789B123456789C123456789D123456789E123456-test-Ext-1";
+ foreach (var extensionName in longExtensionNames)
+ {
+ ExtensionRole er = new ExtensionRole();
+ Assert.Equal(er.RoleName, string.Empty);
+ Assert.Equal(er.PrefixName, "Default");
+ Assert.Equal(er.GetExtensionId(extensionName, "test", 1), expectedExtensionId);
+ }
+ }
+ }
+}
diff --git a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionRole.cs b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionRole.cs
index d3fff4a56c93..aa57a26dcbde 100644
--- a/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionRole.cs
+++ b/src/ServiceManagement/Compute/Commands.ServiceManagement/Extensions/Common/ExtensionRole.cs
@@ -14,6 +14,7 @@
using System;
using System.Text;
+using System.Text.RegularExpressions;
namespace Microsoft.WindowsAzure.Commands.ServiceManagement.Extensions
{
@@ -22,12 +23,21 @@ public class ExtensionRole
protected const string DefaultExtensionIdPrefixStr = "Default";
protected const string ExtensionIdSuffixTemplate = "-{0}-{1}-Ext-{2}";
protected const int MaxExtensionIdLength = 60;
+ protected const int MinRoleNamePartLength = 1;
+ protected const int MaxSuffixLength = MaxExtensionIdLength - MinRoleNamePartLength;
public string RoleName { get; private set; }
public string PrefixName { get; private set; }
public ExtensionRoleType RoleType { get; private set; }
public bool Default { get; private set; }
+ private static string RemoveDisallowedCharacters(string roleName)
+ {
+ // Remove characters that are not allowed in the extension id
+ var disallowedCharactersRegex = new Regex(@"[^A-Za-z0-9\-]");
+ return disallowedCharactersRegex.Replace(roleName, string.Empty);
+ }
+
public ExtensionRole()
{
RoleName = string.Empty;
@@ -48,9 +58,7 @@ public ExtensionRole(string roleName)
else
{
PrefixName = RoleName = roleName.Trim();
- PrefixName = PrefixName.Replace(".", string.Empty);
- PrefixName = PrefixName.Replace(" ", string.Empty);
- PrefixName = PrefixName.Replace("_", string.Empty);
+ PrefixName = RemoveDisallowedCharacters(PrefixName);
RoleType = ExtensionRoleType.NamedRoles;
Default = false;
}
@@ -63,13 +71,21 @@ public override string ToString()
public string GetExtensionId(string extensionName, string slot, int index)
{
- var normalizedExtName = extensionName.Replace(".", string.Empty);
- normalizedExtName = normalizedExtName.Replace(" ", string.Empty);
- normalizedExtName = normalizedExtName.Replace("_", string.Empty);
+ var normalizedExtName = RemoveDisallowedCharacters(extensionName);
var suffix = new StringBuilder();
+ // Suffix format: -{extension_name_part}-{slot}-Ext-{index}
suffix.AppendFormat(ExtensionIdSuffixTemplate, normalizedExtName, slot, index);
+ if (suffix.Length > MaxSuffixLength)
+ {
+ // If the suffix is too long, truncate the {extension_name_part}
+ int lenDiff = suffix.Length - MaxSuffixLength;
+ int startIndex = 1; // Suffix starts with '-'
+ suffix.Remove(startIndex + normalizedExtName.Length - lenDiff, lenDiff);
+ }
+ // Calculate the prefix length by the difference between the suffix and the max ID length.
+ // The difference should always be at least 1.
int prefixSubStrLen = Math.Min(Math.Max(MaxExtensionIdLength - suffix.Length, 0), PrefixName.Length);
var result = new StringBuilder();