diff --git a/AzurePowershell.Test.targets b/AzurePowershell.Test.targets
index 96d75364a44b..a4adcf2014e1 100644
--- a/AzurePowershell.Test.targets
+++ b/AzurePowershell.Test.targets
@@ -24,6 +24,7 @@
.\src\ResourceManager\OperationalInsights\Commands.OperationalInsights.Test\bin\Debug\Microsoft.Azure.Commands.OperationalInsights.Test.dll
.\src\ResourceManager\AzureBatch\Commands.Batch.Test\bin\Debug\Microsoft.Azure.Commands.Batch.Test.dll
.\src\ResourceManager\Websites\Commands.Websites.Test\bin\Debug\Microsoft.Azure.Commands.Websites.Test.dll
+ .\src\ResourceManager\LogicApp\Commands.LogicApp.Test\bin\Debug\Microsoft.Azure.Commands.LogicApp.Test.dll
.\src\ServiceManagement\RemoteApp\Commands.RemoteApp.Test\bin\Debug\Microsoft.Azure.Commands.RemoteApp.Tests.dll
.\src\ServiceManagement\Compute\Commands.ServiceManagement.Test\bin\Debug\Microsoft.WindowsAzure.Commands.ServiceManagement.Test.dll
.\src\ServiceManagement\Sql\Commands.SqlDatabase.Test\bin\Debug\Microsoft.WindowsAzure.Commands.SqlDatabase.Test.dll
@@ -76,13 +77,15 @@
+
-
+
+
@@ -96,19 +99,37 @@
-
-
+
+
-
-
+
+
@@ -163,6 +184,12 @@
IncludeTraits="$(XUnitIncludedTrait)" MaxParallelThreads="0" ParallelizeAssemblies="false" ParallelizeTestCollections="false" />
+
+
+
+
+
@@ -450,7 +477,7 @@
-
+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3d1f3b4279e2..0cb8f7c9aba6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1,5 @@
# Contribute Code or Provide Feedback
-If you would like to become an active contributor to this project please follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines](http://windowsazure.github.com/guidelines.html).
+If you would like to become an active contributor to this project please follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines](http://azure.github.io/guidelines/).
If you encounter any bugs with Microsoft Azure PowerShell please file an issue in the [Issues](https://github.com/Azure/azure-powershell/issues) section of the project.
diff --git a/ChangeLog.md b/ChangeLog.md
index 5a5f0f612015..e9d60bbe5bbb 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,44 @@
+##2016.03.03 version 1.2.2
+* Azure Compute (ARM):
+ * Add -LicenseType parameter to New-AzureRmVM for bring your own license (BYOL)
+ * Add -SecureExecution parameter to Set-AzureRmVMCustomScriptExtension
+ * Add -DisableAutoUpgradeMinorVersion and -ForceRerun parameters to Set-AzureRmVMExtension
+ * Add Set-AzureRmVMPlan cmdlet
+ * Add -Redeploy parameter to Set-AzureRmVM
+ * Add AutoUpgradeMinorVersion and ForceUpdateTag parameters for Get-AzureRmVMExtension
+ * Update positions of parameters for New-AzureRmVM
+* Azure Compute (Service Management):
+ * Add Set-AzureBootDiagnostics cmdlets
+ * Enable boot diagnostics by default for New-AzureVM and New-AzureQuickVM
+* Azure LogicApp: New cmdlets for managing LogicApps
+ * Get-AzureLogicAppAccessKey
+ * Get-AzureLogicApp
+ * Get-AzureLogicAppRunAction
+ * Get-AzureLogicAppRunHistory
+ * Get-AzureLogicAppTrigger
+ * Get-AzureLogicAppTriggerHistory
+ * New-AzureLogicApp
+ * Remove-AzureLogicApp
+ * Start-AzureLogicApp
+ * Set-AzureLogicAppAccessKey
+ * Set-AzureLogicApp
+ * Stop-AzureLogicAppRun
+ * Azure Storage
+ * Added cmdlet to generate SAS token against storage account
+ - New-AzureStorageAccountSASToken
+ * Added IPAddressOrRange/Protocol support in cmdlets to generate SAS token against blob, container, file, share, table, queue
+ - New-AzureStorageBlobSASToken
+ - New-AzureStorageContainerSASToken
+ - New-AzureStorageFileSASToken
+ - New-AzureStorageShareSASToken
+ - New-AzureStorageQueueSASToken
+ - New-AzureStorageTableSASToken
+* Azure SQL DB Backup/restore
+ * Get-AzureRmSqlDatabaseGeoBackup
+ * Get-AzureRmSqlDeletedDatabaseBackup
+ * Restore-AzureRmSqlDatabase
+ * This cmdlet accepts as pipelined input the result of one of the first two cmdlets (or Get-AzureRmSqlDatabase if restoring a live DB to a point-in-time)
+
## 2016.02.04 version 1.2.1
* Fix installer issue - remove PSGallery modules on install
diff --git a/build.proj b/build.proj
index b1679966918c..1de7a0a2ce61 100644
--- a/build.proj
+++ b/build.proj
@@ -53,6 +53,7 @@
+
@@ -161,6 +162,14 @@
Properties="Configuration=$(Configuration);Platform=Any CPU"
ContinueOnError="false"
Condition=" '$(Scope)' == 'all' "/>
+
+
+
+
@@ -280,6 +289,12 @@
+
+
+
+
+
+
diff --git a/packages.config b/packages.config
index acdf0e730003..4e3a43699ecd 100644
--- a/packages.config
+++ b/packages.config
@@ -1,5 +1,5 @@
-
-
+
+
diff --git a/setup/azurecmd.wxs b/setup/azurecmd.wxs
index 199684b9e8ce..303600c11759 100644
--- a/setup/azurecmd.wxs
+++ b/setup/azurecmd.wxs
@@ -1,11 +1,11 @@
-
+
-
+
-
-
+
+
@@ -71,6 +71,9 @@
+
+
+
@@ -83,9 +86,6 @@
-
-
-
@@ -107,6 +107,9 @@
+
+
+
@@ -142,12 +145,12 @@
+
+
+
-
-
-
@@ -202,9 +205,6 @@
-
-
-
@@ -237,6 +237,9 @@
+
+
+
@@ -246,9 +249,6 @@
-
-
-
@@ -285,9 +285,6 @@
-
-
-
@@ -298,69 +295,69 @@
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -373,12 +370,12 @@
+
+
+
-
-
-
@@ -430,9 +427,6 @@
-
-
-
@@ -462,12 +456,12 @@
+
+
+
-
-
-
@@ -548,12 +542,12 @@
+
+
+
-
-
-
@@ -602,9 +596,6 @@
-
-
-
@@ -661,12 +652,12 @@
+
+
+
-
-
-
@@ -682,9 +673,6 @@
-
-
-
@@ -694,9 +682,6 @@
-
-
-
@@ -736,9 +721,6 @@
-
-
-
@@ -814,9 +796,6 @@
-
-
-
@@ -849,6 +828,9 @@
+
+
+
@@ -861,9 +843,6 @@
-
-
-
@@ -944,6 +923,9 @@
+
+
+
@@ -959,9 +941,6 @@
-
-
-
@@ -971,12 +950,6 @@
-
-
-
-
-
-
@@ -989,6 +962,9 @@
+
+
+
@@ -1027,6 +1003,9 @@
+
+
+
@@ -1042,9 +1021,6 @@
-
-
-
@@ -1054,9 +1030,6 @@
-
-
-
@@ -1072,6 +1045,9 @@
+
+
+
@@ -1113,6 +1089,9 @@
+
+
+
@@ -1131,9 +1110,6 @@
-
-
-
@@ -1176,9 +1152,6 @@
-
-
-
@@ -1202,21 +1175,18 @@
+
+
+
-
-
-
-
-
-
@@ -1271,12 +1241,6 @@
-
-
-
-
-
-
@@ -1297,6 +1261,9 @@
+
+
+
@@ -1309,9 +1276,6 @@
-
-
-
@@ -1354,12 +1318,6 @@
-
-
-
-
-
-
@@ -1392,6 +1350,9 @@
+
+
+
@@ -1428,9 +1389,6 @@
-
-
-
@@ -1507,6 +1465,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1541,12 +1615,12 @@
+
+
+
-
-
-
@@ -1589,9 +1663,6 @@
-
-
-
@@ -1652,9 +1723,6 @@
-
-
-
@@ -1684,6 +1752,9 @@
+
+
+
@@ -1693,9 +1764,6 @@
-
-
-
@@ -1729,9 +1797,6 @@
-
-
-
@@ -1752,6 +1817,9 @@
+
+
+
@@ -1764,9 +1832,6 @@
-
-
-
@@ -1832,6 +1897,9 @@
+
+
+
@@ -1844,9 +1912,6 @@
-
-
-
@@ -1903,6 +1968,9 @@
+
+
+
@@ -1912,9 +1980,6 @@
-
-
-
@@ -1948,9 +2013,6 @@
-
-
-
@@ -1974,6 +2036,9 @@
+
+
+
@@ -1986,9 +2051,6 @@
-
-
-
@@ -2040,9 +2102,6 @@
-
-
-
@@ -2075,6 +2134,9 @@
+
+
+
@@ -2102,9 +2164,6 @@
-
-
-
@@ -2176,6 +2235,9 @@
+
+
+
@@ -2185,9 +2247,6 @@
-
-
-
@@ -2221,9 +2280,6 @@
-
-
-
@@ -2256,6 +2312,9 @@
+
+
+
@@ -2295,9 +2354,6 @@
-
-
-
@@ -2352,9 +2408,6 @@
-
-
-
@@ -2402,12 +2455,12 @@
+
+
+
-
-
-
@@ -2441,9 +2494,6 @@
-
-
-
@@ -2486,9 +2536,6 @@
-
-
-
@@ -2507,9 +2554,6 @@
-
-
-
@@ -2542,6 +2586,9 @@
+
+
+
@@ -2554,9 +2601,6 @@
-
-
-
@@ -2628,6 +2672,9 @@
+
+
+
@@ -2640,9 +2687,6 @@
-
-
-
@@ -2702,6 +2746,9 @@
+
+
+
@@ -2720,9 +2767,6 @@
-
-
-
@@ -2753,9 +2797,6 @@
-
-
-
@@ -2770,6 +2811,9 @@
+
+
+
@@ -2785,9 +2829,6 @@
-
-
-
@@ -2818,9 +2859,6 @@
-
-
-
@@ -2844,6 +2882,9 @@
+
+
+
@@ -2874,9 +2915,6 @@
-
-
-
@@ -2925,9 +2963,6 @@
-
-
-
@@ -2961,8 +2996,8 @@
-
-
+
+
@@ -3032,8 +3067,8 @@
-
-
+
+
@@ -3086,6 +3121,9 @@
+
+
+
@@ -3098,9 +3136,6 @@
-
-
-
@@ -3122,6 +3157,9 @@
+
+
+
@@ -3148,8 +3186,8 @@
-
-
+
+
@@ -3241,9 +3279,6 @@
-
-
-
@@ -3336,8 +3371,8 @@
-
-
+
+
@@ -3413,8 +3448,8 @@
-
-
+
+
@@ -3476,9 +3511,6 @@
-
-
-
@@ -3517,9 +3549,6 @@
-
-
-
@@ -3529,15 +3558,15 @@
+
+
+
-
-
-
@@ -3622,9 +3651,6 @@
-
-
-
@@ -3693,8 +3719,8 @@
-
-
+
+
@@ -3795,9 +3821,6 @@
-
-
-
@@ -4070,15 +4093,15 @@
+
+
+
-
-
-
@@ -4152,8 +4175,8 @@
-
-
+
+
@@ -4209,9 +4232,6 @@
-
-
-
@@ -4262,8 +4282,8 @@
-
-
+
+
@@ -4633,9 +4653,6 @@
-
-
-
@@ -4651,8 +4668,8 @@
-
-
+
+
@@ -4759,9 +4776,6 @@
-
-
-
@@ -4830,8 +4844,8 @@
-
-
+
+
@@ -4910,8 +4924,8 @@
-
-
+
+
@@ -4964,9 +4978,6 @@
-
-
-
@@ -4999,7 +5010,7 @@
-
+
@@ -5017,11 +5028,11 @@
+
-
@@ -5029,6 +5040,7 @@
+
@@ -5040,8 +5052,8 @@
+
-
@@ -5060,7 +5072,6 @@
-
@@ -5071,10 +5082,10 @@
+
-
@@ -5087,36 +5098,35 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -5134,7 +5144,6 @@
-
@@ -5144,8 +5153,8 @@
+
-
@@ -5172,8 +5181,8 @@
+
-
@@ -5190,7 +5199,6 @@
-
@@ -5209,18 +5217,16 @@
+
-
-
-
@@ -5234,7 +5240,6 @@
-
@@ -5260,7 +5265,6 @@
-
@@ -5271,11 +5275,11 @@
+
-
@@ -5302,21 +5306,20 @@
+
-
-
-
+
@@ -5329,21 +5332,21 @@
+
-
-
+
@@ -5357,13 +5360,13 @@
+
-
@@ -5378,7 +5381,6 @@
-
@@ -5386,11 +5388,10 @@
+
-
-
@@ -5409,19 +5410,17 @@
-
-
+
-
@@ -5436,8 +5435,6 @@
-
-
@@ -5448,6 +5445,7 @@
+
@@ -5460,7 +5458,6 @@
-
@@ -5486,6 +5483,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5497,8 +5532,8 @@
+
-
@@ -5513,7 +5548,6 @@
-
@@ -5534,7 +5568,6 @@
-
@@ -5544,10 +5577,10 @@
+
-
@@ -5559,18 +5592,17 @@
-
+
-
@@ -5592,11 +5624,11 @@
+
-
@@ -5615,10 +5647,10 @@
+
-
@@ -5630,7 +5662,6 @@
-
@@ -5638,11 +5669,11 @@
+
-
@@ -5660,7 +5691,6 @@
-
@@ -5671,6 +5701,7 @@
+
@@ -5680,7 +5711,6 @@
-
@@ -5704,10 +5734,10 @@
+
-
@@ -5719,7 +5749,6 @@
-
@@ -5730,6 +5759,7 @@
+
@@ -5743,7 +5773,6 @@
-
@@ -5762,7 +5791,6 @@
-
@@ -5778,8 +5806,8 @@
+
-
@@ -5791,7 +5819,6 @@
-
@@ -5806,14 +5833,12 @@
-
-
@@ -5824,11 +5849,11 @@
+
-
@@ -5852,11 +5877,11 @@
+
-
@@ -5876,13 +5901,13 @@
+
-
@@ -5893,17 +5918,16 @@
-
+
-
@@ -5914,7 +5938,6 @@
-
@@ -5922,6 +5945,7 @@
+
@@ -5932,7 +5956,6 @@
-
@@ -5949,7 +5972,6 @@
-
@@ -5959,7 +5981,7 @@
-
+
@@ -5982,7 +6004,7 @@
-
+
@@ -6000,11 +6022,11 @@
+
-
@@ -6012,6 +6034,7 @@
+
@@ -6020,7 +6043,7 @@
-
+
@@ -6051,7 +6074,6 @@
-
@@ -6082,7 +6104,7 @@
-
+
@@ -6107,7 +6129,7 @@
-
+
@@ -6128,7 +6150,6 @@
-
@@ -6141,13 +6162,12 @@
-
+
-
@@ -6176,7 +6196,6 @@
-
@@ -6199,7 +6218,7 @@
-
+
@@ -6233,7 +6252,6 @@
-
@@ -6314,9 +6332,9 @@
+
-
@@ -6340,7 +6358,7 @@
-
+
@@ -6359,7 +6377,6 @@
-
@@ -6376,7 +6393,7 @@
-
+
@@ -6489,13 +6506,12 @@
-
-
+
@@ -6531,7 +6547,6 @@
-
@@ -6554,7 +6569,7 @@
-
+
@@ -6580,7 +6595,7 @@
-
+
@@ -6598,7 +6613,6 @@
-
diff --git a/src/Common/Commands.Common.Authentication.Test/AuthenticationFactoryTests.cs b/src/Common/Commands.Common.Authentication.Test/AuthenticationFactoryTests.cs
new file mode 100644
index 000000000000..7f2afce7000d
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/AuthenticationFactoryTests.cs
@@ -0,0 +1,111 @@
+// ----------------------------------------------------------------------------------
+//
+// 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.Azure.Commands.Common.Authentication;
+using Microsoft.Azure.Commands.Common.Authentication.Factories;
+using Microsoft.Azure.Commands.Common.Authentication.Models;
+using Microsoft.WindowsAzure.Commands.Test.Utilities.Common;
+using System;
+using System.Collections.Generic;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Xunit;
+
+namespace Common.Authentication.Test
+{
+ public class AuthenticationFactoryTests
+ {
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void VerifySubscriptionTokenCacheRemove()
+ {
+ var authFactory = new AuthenticationFactory
+ {
+ TokenProvider = new MockAccessTokenProvider("testtoken", "testuser")
+ };
+
+ var subscriptionId = Guid.NewGuid();
+
+ var credential = authFactory.GetSubscriptionCloudCredentials(new AzureContext
+ (
+ new AzureSubscription
+ {
+ Id = subscriptionId,
+ Properties = new Dictionary
+ {
+ { AzureSubscription.Property.Tenants, "123"}
+ }
+ },
+ new AzureAccount
+ {
+ Id = "testuser",
+ Type = AzureAccount.AccountType.User,
+ Properties = new Dictionary
+ {
+ { AzureAccount.Property.Tenants, "123" }
+ }
+ },
+ AzureEnvironment.PublicEnvironments["AzureCloud"]
+ ));
+
+ Assert.True(credential is AccessTokenCredential);
+ Assert.Equal(subscriptionId, new Guid(((AccessTokenCredential)credential).SubscriptionId));
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void VerifyValidateAuthorityFalseForOnPremise()
+ {
+ var authFactory = new AuthenticationFactory
+ {
+ TokenProvider = new MockAccessTokenProvider("testtoken", "testuser")
+ };
+
+ var subscriptionId = Guid.NewGuid();
+ var context = new AzureContext
+ (
+ new AzureSubscription
+ {
+ Id = subscriptionId,
+ Properties = new Dictionary
+ {
+ { AzureSubscription.Property.Tenants, "123"}
+ }
+ },
+ new AzureAccount
+ {
+ Id = "testuser",
+ Type = AzureAccount.AccountType.User,
+ Properties = new Dictionary
+ {
+ { AzureAccount.Property.Tenants, "123" }
+ }
+ },
+ new AzureEnvironment
+ {
+ Name = "Katal",
+ OnPremise = true,
+ Endpoints = new Dictionary
+ {
+ { AzureEnvironment.Endpoint.ActiveDirectory, "http://ad.com" },
+ { AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId, "http://adresource.com" }
+ }
+ }
+ );
+
+ var credential = authFactory.Authenticate(context.Account, context.Environment, "common", null, ShowDialog.Always);
+
+ Assert.False(((MockAccessTokenProvider)authFactory.TokenProvider).AdalConfiguration.ValidateAuthority);
+ }
+ }
+}
diff --git a/src/Common/Commands.Common.Authentication.Test/AzureRMProfileTests.cs b/src/Common/Commands.Common.Authentication.Test/AzureRMProfileTests.cs
new file mode 100644
index 000000000000..49cf5fdcd40c
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/AzureRMProfileTests.cs
@@ -0,0 +1,230 @@
+// ----------------------------------------------------------------------------------
+//
+// 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.Azure.Commands.Common.Authentication;
+using Microsoft.Azure.Commands.Common.Authentication.Models;
+using Microsoft.WindowsAzure.Commands.Common.Test.Mocks;
+using System;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Xunit;
+
+namespace Common.Authentication.Test
+{
+ public class AzureRMProfileTests
+ {
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ProfileSerializeDeserializeWorks()
+ {
+ var dataStore = new MockDataStore();
+ AzureSession.DataStore = dataStore;
+ var profilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AzureSession.ProfileFile);
+ var currentProfile = new AzureRMProfile(profilePath);
+ var tenantId = Guid.NewGuid().ToString();
+ var environment = new AzureEnvironment
+ {
+ Name = "testCloud",
+ Endpoints = { { AzureEnvironment.Endpoint.ActiveDirectory, "http://contoso.com" } }
+ };
+ var account = new AzureAccount
+ {
+ Id = "me@contoso.com",
+ Type = AzureAccount.AccountType.User,
+ Properties = { { AzureAccount.Property.Tenants, tenantId } }
+ };
+ var sub = new AzureSubscription
+ {
+ Account = account.Id,
+ Environment = environment.Name,
+ Id = new Guid(),
+ Name = "Contoso Test Subscription",
+ Properties = { { AzureSubscription.Property.Tenants, tenantId } }
+ };
+ var tenant = new AzureTenant
+ {
+ Id = new Guid(tenantId),
+ Domain = "contoso.com"
+ };
+
+ currentProfile.Context = new AzureContext(sub, account, environment, tenant);
+ currentProfile.Environments[environment.Name] = environment;
+ currentProfile.Context.TokenCache = new byte[] { 1, 2, 3, 4, 5, 6, 8, 9, 0 };
+
+ AzureRMProfile deserializedProfile;
+ // Round-trip the exception: Serialize and de-serialize with a BinaryFormatter
+ BinaryFormatter bf = new BinaryFormatter();
+ using (MemoryStream ms = new MemoryStream())
+ {
+ // "Save" object state
+ bf.Serialize(ms, currentProfile);
+
+ // Re-use the same stream for de-serialization
+ ms.Seek(0, 0);
+
+ // Replace the original exception with de-serialized one
+ deserializedProfile = (AzureRMProfile)bf.Deserialize(ms);
+ }
+ Assert.NotNull(deserializedProfile);
+ var jCurrentProfile = currentProfile.ToString();
+ var jDeserializedProfile = deserializedProfile.ToString();
+ Assert.Equal(jCurrentProfile, jDeserializedProfile);
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void SavingProfileWorks()
+ {
+ string expected = @"{
+ ""Environments"": {
+ ""testCloud"": {
+ ""Name"": ""testCloud"",
+ ""OnPremise"": false,
+ ""Endpoints"": {
+ ""ActiveDirectory"": ""http://contoso.com""
+ }
+ }
+ },
+ ""Context"": {
+ ""Account"": {
+ ""Id"": ""me@contoso.com"",
+ ""Type"": 1,
+ ""Properties"": {
+ ""Tenants"": ""3c0ff8a7-e8bb-40e8-ae66-271343379af6""
+ }
+ },
+ ""Subscription"": {
+ ""Id"": ""00000000-0000-0000-0000-000000000000"",
+ ""Name"": ""Contoso Test Subscription"",
+ ""Environment"": ""testCloud"",
+ ""Account"": ""me@contoso.com"",
+ ""State"": ""Enabled"",
+ ""Properties"": {
+ ""Tenants"": ""3c0ff8a7-e8bb-40e8-ae66-271343379af6""
+ }
+ },
+ ""Environment"": {
+ ""Name"": ""testCloud"",
+ ""OnPremise"": false,
+ ""Endpoints"": {
+ ""ActiveDirectory"": ""http://contoso.com""
+ }
+ },
+ ""Tenant"": {
+ ""Id"": ""3c0ff8a7-e8bb-40e8-ae66-271343379af6"",
+ ""Domain"": ""contoso.com""
+ },
+ ""TokenCache"": ""AQIDBAUGCAkA""
+ }
+}";
+ var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AzureSession.ProfileFile);
+ var dataStore = new MockDataStore();
+ AzureSession.DataStore = dataStore;
+ AzureRMProfile profile = new AzureRMProfile(path);
+ var tenantId = new Guid("3c0ff8a7-e8bb-40e8-ae66-271343379af6");
+ var environment = new AzureEnvironment
+ {
+ Name = "testCloud",
+ Endpoints = { { AzureEnvironment.Endpoint.ActiveDirectory, "http://contoso.com" } }
+ };
+ var account = new AzureAccount
+ {
+ Id = "me@contoso.com",
+ Type = AzureAccount.AccountType.User,
+ Properties = { { AzureAccount.Property.Tenants, tenantId.ToString() } }
+ };
+ var sub = new AzureSubscription
+ {
+ Account = account.Id,
+ Environment = environment.Name,
+ Id = new Guid(),
+ Name = "Contoso Test Subscription",
+ State = "Enabled",
+ Properties = { { AzureSubscription.Property.Tenants, tenantId.ToString() } }
+ };
+ var tenant = new AzureTenant
+ {
+ Id = tenantId,
+ Domain = "contoso.com"
+ };
+ profile.Context = new AzureContext(sub, account, environment, tenant);
+ profile.Environments[environment.Name] = environment;
+ profile.Context.TokenCache = new byte[] { 1, 2, 3, 4, 5, 6, 8, 9, 0 };
+ profile.Save();
+ string actual = dataStore.ReadFileAsText(path);
+ Assert.Equal(expected, actual);
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void LoadingProfileWorks()
+ {
+ string contents = @"{
+ ""Environments"": {
+ ""testCloud"": {
+ ""Name"": ""testCloud"",
+ ""OnPremise"": false,
+ ""Endpoints"": {
+ ""ActiveDirectory"": ""http://contoso.com""
+ }
+ }
+ },
+ ""Context"": {
+ ""TokenCache"": ""AQIDBAUGCAkA"",
+ ""Account"": {
+ ""Id"": ""me@contoso.com"",
+ ""Type"": 1,
+ ""Properties"": {
+ ""Tenants"": ""3c0ff8a7-e8bb-40e8-ae66-271343379af6""
+ }
+ },
+ ""Subscription"": {
+ ""Id"": ""00000000-0000-0000-0000-000000000000"",
+ ""Name"": ""Contoso Test Subscription"",
+ ""Environment"": ""testCloud"",
+ ""Account"": ""me@contoso.com"",
+ ""Properties"": {
+ ""Tenants"": ""3c0ff8a7-e8bb-40e8-ae66-271343379af6""
+ }
+ },
+ ""Environment"": {
+ ""Name"": ""testCloud"",
+ ""OnPremise"": false,
+ ""Endpoints"": {
+ ""ActiveDirectory"": ""http://contoso.com""
+ }
+ },
+ ""Tenant"": {
+ ""Id"": ""3c0ff8a7-e8bb-40e8-ae66-271343379af6"",
+ ""Domain"": ""contoso.com""
+ }
+ }
+}";
+ var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AzureSession.ProfileFile);
+ var dataStore = new MockDataStore();
+ AzureSession.DataStore = dataStore;
+ dataStore.WriteFile(path, contents);
+ var profile = new AzureRMProfile(path);
+ Assert.Equal(4, profile.Environments.Count);
+ Assert.Equal("3c0ff8a7-e8bb-40e8-ae66-271343379af6", profile.Context.Tenant.Id.ToString());
+ Assert.Equal("contoso.com", profile.Context.Tenant.Domain);
+ Assert.Equal("00000000-0000-0000-0000-000000000000", profile.Context.Subscription.Id.ToString());
+ Assert.Equal("testCloud", profile.Context.Environment.Name);
+ Assert.Equal("me@contoso.com", profile.Context.Account.Id);
+ Assert.Equal(new byte[] { 1, 2, 3, 4, 5, 6, 8, 9, 0 }, profile.Context.TokenCache);
+ Assert.Equal(path, profile.ProfilePath);
+ }
+ }
+}
diff --git a/src/Common/Commands.Common.Authentication.Test/AzureSMProfileTests.cs b/src/Common/Commands.Common.Authentication.Test/AzureSMProfileTests.cs
new file mode 100644
index 000000000000..663b83eb21db
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/AzureSMProfileTests.cs
@@ -0,0 +1,193 @@
+// ----------------------------------------------------------------------------------
+//
+// 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.Azure.Commands.Common.Authentication;
+using Microsoft.Azure.Commands.Common.Authentication.Models;
+using Microsoft.WindowsAzure.Commands.Common.Test.Mocks;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Xunit;
+
+namespace Common.Authentication.Test
+{
+ public class AzureSMProfileTests
+ {
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ProfileSaveDoesNotSerializeContext()
+ {
+ var dataStore = new MockDataStore();
+ var profilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AzureSession.ProfileFile);
+ var profile = new AzureSMProfile(profilePath);
+ AzureSession.DataStore = dataStore;
+ var tenant = Guid.NewGuid().ToString();
+ var environment = new AzureEnvironment
+ {
+ Name = "testCloud",
+ Endpoints = { { AzureEnvironment.Endpoint.ActiveDirectory, "http://contoso.com" } }
+ };
+ var account = new AzureAccount
+ {
+ Id = "me@contoso.com",
+ Type = AzureAccount.AccountType.User,
+ Properties = { { AzureAccount.Property.Tenants, tenant } }
+ };
+ var sub = new AzureSubscription
+ {
+ Account = account.Id,
+ Environment = environment.Name,
+ Id = new Guid(),
+ Name = "Contoso Test Subscription",
+ Properties = { { AzureSubscription.Property.Tenants, tenant } }
+ };
+
+ profile.Environments[environment.Name] = environment;
+ profile.Accounts[account.Id] = account;
+ profile.Subscriptions[sub.Id] = sub;
+
+ profile.Save();
+
+ var profileFile = profile.ProfilePath;
+ string profileContents = dataStore.ReadFileAsText(profileFile);
+ var readProfile = JsonConvert.DeserializeObject>(profileContents);
+ Assert.False(readProfile.ContainsKey("DefaultContext"));
+ AzureSMProfile parsedProfile = new AzureSMProfile();
+ var serializer = new JsonProfileSerializer();
+ Assert.True(serializer.Deserialize(profileContents, parsedProfile));
+ Assert.NotNull(parsedProfile);
+ Assert.NotNull(parsedProfile.Environments);
+ Assert.True(parsedProfile.Environments.ContainsKey(environment.Name));
+ Assert.NotNull(parsedProfile.Accounts);
+ Assert.True(parsedProfile.Accounts.ContainsKey(account.Id));
+ Assert.NotNull(parsedProfile.Subscriptions);
+ Assert.True(parsedProfile.Subscriptions.ContainsKey(sub.Id));
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void ProfileSerializeDeserializeWorks()
+ {
+ var dataStore = new MockDataStore();
+ var profilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AzureSession.ProfileFile);
+ var profile = new AzureSMProfile(profilePath);
+ AzureSession.DataStore = dataStore;
+ var tenant = Guid.NewGuid().ToString();
+ var environment = new AzureEnvironment
+ {
+ Name = "testCloud",
+ Endpoints = { { AzureEnvironment.Endpoint.ActiveDirectory, "http://contoso.com" } }
+ };
+ var account = new AzureAccount
+ {
+ Id = "me@contoso.com",
+ Type = AzureAccount.AccountType.User,
+ Properties = { { AzureAccount.Property.Tenants, tenant } }
+ };
+ var sub = new AzureSubscription
+ {
+ Account = account.Id,
+ Environment = environment.Name,
+ Id = new Guid(),
+ Name = "Contoso Test Subscription",
+ Properties = { { AzureSubscription.Property.Tenants, tenant } }
+ };
+
+ profile.Environments[environment.Name] = environment;
+ profile.Accounts[account.Id] = account;
+ profile.Subscriptions[sub.Id] = sub;
+
+ AzureSMProfile deserializedProfile;
+ // Round-trip the exception: Serialize and de-serialize with a BinaryFormatter
+ BinaryFormatter bf = new BinaryFormatter();
+ using (MemoryStream ms = new MemoryStream())
+ {
+ // "Save" object state
+ bf.Serialize(ms, profile);
+
+ // Re-use the same stream for de-serialization
+ ms.Seek(0, 0);
+
+ // Replace the original exception with de-serialized one
+ deserializedProfile = (AzureSMProfile)bf.Deserialize(ms);
+ }
+ Assert.NotNull(deserializedProfile);
+ var jCurrentProfile = JsonConvert.SerializeObject(profile);
+ var jDeserializedProfile = JsonConvert.SerializeObject(deserializedProfile);
+ Assert.Equal(jCurrentProfile, jDeserializedProfile);
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void AccountMatchingIgnoresCase()
+ {
+ var profile = new AzureSMProfile();
+ string accountName = "howdy@contoso.com";
+ string accountNameCase = "Howdy@Contoso.com";
+ var subscriptionId = Guid.NewGuid();
+ var tenantId = Guid.NewGuid();
+ var account = new AzureAccount
+ {
+ Id = accountName,
+ Type = AzureAccount.AccountType.User
+ };
+
+ account.SetProperty(AzureAccount.Property.Subscriptions, subscriptionId.ToString());
+ account.SetProperty(AzureAccount.Property.Tenants, tenantId.ToString());
+ var subscription = new AzureSubscription
+ {
+ Id = subscriptionId,
+ Account = accountNameCase,
+ Environment = EnvironmentName.AzureCloud
+ };
+
+ subscription.SetProperty(AzureSubscription.Property.Default, "true");
+ subscription.SetProperty(AzureSubscription.Property.Tenants, tenantId.ToString());
+ profile.Accounts.Add(accountName, account);
+ profile.Subscriptions.Add(subscriptionId, subscription);
+ Assert.NotNull(profile.Context);
+ Assert.NotNull(profile.Context.Account);
+ Assert.NotNull(profile.Context.Environment);
+ Assert.NotNull(profile.Context.Subscription);
+ Assert.Equal(account, profile.Context.Account);
+ Assert.Equal(subscription, profile.Context.Subscription);
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void GetsCorrectContext()
+ {
+ AzureSMProfile profile = new AzureSMProfile();
+ string accountId = "accountId";
+ Guid subscriptionId = Guid.NewGuid();
+ profile.Accounts.Add(accountId, new AzureAccount { Id = accountId, Type = AzureAccount.AccountType.User });
+ profile.Subscriptions.Add(subscriptionId, new AzureSubscription
+ {
+ Account = accountId,
+ Environment = EnvironmentName.AzureChinaCloud,
+ Name = "hello",
+ Id = subscriptionId
+ });
+ profile.DefaultSubscription = profile.Subscriptions[subscriptionId];
+ AzureContext context = profile.Context;
+
+ Assert.Equal(accountId, context.Account.Id);
+ Assert.Equal(subscriptionId, context.Subscription.Id);
+ Assert.Equal(EnvironmentName.AzureChinaCloud, context.Environment.Name);
+ }
+ }
+}
diff --git a/src/Common/Commands.Common.Authentication.Test/ClientFactoryHandlerTests.cs b/src/Common/Commands.Common.Authentication.Test/ClientFactoryHandlerTests.cs
new file mode 100644
index 000000000000..9b838cd9e9e5
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/ClientFactoryHandlerTests.cs
@@ -0,0 +1,78 @@
+// ----------------------------------------------------------------------------------
+//
+// 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.Azure.Commands.Common.Authentication;
+using Microsoft.Azure.Commands.Common.Authentication.Models;
+using Microsoft.WindowsAzure.Management.Storage;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Security;
+using Microsoft.Azure.Commands.Common.Authentication.Factories;
+using Microsoft.WindowsAzure.Commands.Common.Test.Mocks;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Xunit;
+
+namespace Common.Authentication.Test
+{
+ public class ClientFactoryHandlerTests
+ {
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void DelegatingHandlersAreCloned()
+ {
+ string userAccount = "user@contoso.com";
+ Guid subscriptionId = Guid.NewGuid();
+ AzureContext context = new AzureContext
+ (
+ new AzureSubscription()
+ {
+ Account = userAccount,
+ Environment = "AzureCloud",
+ Id = subscriptionId,
+ Properties = new Dictionary() { { AzureSubscription.Property.Tenants, "common" } }
+ },
+ new AzureAccount()
+ {
+ Id = userAccount,
+ Type = AzureAccount.AccountType.User,
+ Properties = new Dictionary() { { AzureAccount.Property.Tenants, "common" } }
+ },
+ AzureEnvironment.PublicEnvironments["AzureCloud"]
+ );
+
+ AzureSession.AuthenticationFactory = new MockTokenAuthenticationFactory(userAccount, Guid.NewGuid().ToString());
+ var mockHandler = new MockDelegatingHandler();
+ var factory = new ClientFactory();
+ factory.AddHandler(mockHandler);
+ var client = factory.CreateClient(context, AzureEnvironment.Endpoint.ServiceManagement);
+ client = factory.CreateClient(context, AzureEnvironment.Endpoint.ServiceManagement);
+ client = factory.CreateClient(context, AzureEnvironment.Endpoint.ServiceManagement);
+ client = factory.CreateClient(context, AzureEnvironment.Endpoint.ServiceManagement);
+ client = factory.CreateClient(context, AzureEnvironment.Endpoint.ServiceManagement);
+ Assert.Equal(5, MockDelegatingHandler.cloneCount);
+ }
+
+ private class MockDelegatingHandler : DelegatingHandler, ICloneable
+ {
+ public static int cloneCount = 0;
+
+ public object Clone()
+ {
+ cloneCount++;
+ return this;
+ }
+ }
+ }
+}
diff --git a/src/Common/Commands.Common.Authentication.Test/ClientFactoryTests.cs b/src/Common/Commands.Common.Authentication.Test/ClientFactoryTests.cs
new file mode 100644
index 000000000000..4ea2bfdeec8f
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/ClientFactoryTests.cs
@@ -0,0 +1,145 @@
+// ----------------------------------------------------------------------------------
+//
+// 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.Azure.Commands.Common.Authentication;
+using Microsoft.Azure.Commands.Common.Authentication.Models;
+using Microsoft.WindowsAzure.Management.Storage;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Security;
+using Microsoft.Azure.Commands.Common.Authentication.Factories;
+using Microsoft.WindowsAzure.Commands.Common.Test.Mocks;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Xunit;
+
+namespace Common.Authentication.Test
+{
+ public class ClientFactoryTests : IDisposable
+ {
+ private string subscriptionId;
+
+ private string userAccount;
+
+ private SecureString password;
+
+ private bool runTest;
+
+ public ClientFactoryTests()
+ {
+ // Example of environment variable: TEST_AZURE_CREDENTIALS=;;"
+ string credsEnvironmentVariable = Environment.GetEnvironmentVariable("TEST_AZURE_CREDENTIALS") ?? "";
+ string[] creds = credsEnvironmentVariable.Split(';');
+
+ if (creds.Length != 3)
+ {
+ // The test is not configured to run.
+ runTest = false;
+ return;
+ }
+
+ subscriptionId = creds[0];
+ userAccount = creds[1];
+ password = new SecureString();
+ foreach (char letter in creds[2])
+ {
+ password.AppendChar(letter);
+ }
+ password = password.Length == 0 ? null : password;
+ runTest = true;
+ }
+
+ ///
+ /// This test run live against Azure to list storage accounts under current subscription.
+ ///
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void VerifyClientFactoryWorks()
+ {
+ if (!runTest)
+ {
+ return;
+ }
+
+ AzureContext context = new AzureContext
+ (
+ new AzureSubscription()
+ {
+ Account = userAccount,
+ Environment = "AzureCloud",
+ Id = Guid.Parse(subscriptionId),
+ Properties = new Dictionary() { { AzureSubscription.Property.Tenants, "common" } }
+ },
+ new AzureAccount()
+ {
+ Id = userAccount,
+ Type = AzureAccount.AccountType.User,
+ Properties = new Dictionary() { { AzureAccount.Property.Tenants, "common" } }
+ },
+ AzureEnvironment.PublicEnvironments["AzureCloud"]
+ );
+
+ // Add registration action to make sure we register for the used provider (if required)
+ // AzureSession.ClientFactory.AddAction(new RPRegistrationAction());
+
+ // Authenticate!
+ AzureSession.AuthenticationFactory.Authenticate(context.Account, context.Environment, "common", password, ShowDialog.Always);
+
+ AzureSession.ClientFactory.AddUserAgent("TestUserAgent", "1.0");
+ // Create the client
+ var client = AzureSession.ClientFactory.CreateClient(context, AzureEnvironment.Endpoint.ServiceManagement);
+
+ // List storage accounts
+ var storageAccounts = client.StorageAccounts.List().StorageAccounts;
+ foreach (var storageAccount in storageAccounts)
+ {
+ Assert.NotNull(storageAccount);
+ }
+ }
+
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void VerifyProductInfoHeaderValueEquality()
+ {
+ ClientFactory factory = new ClientFactory();
+ factory.AddUserAgent("test1", "123");
+ factory.AddUserAgent("test2", "123");
+ factory.AddUserAgent("test1", "123");
+ factory.AddUserAgent("test1", "456");
+ factory.AddUserAgent("test3");
+ factory.AddUserAgent("tesT3");
+
+ Assert.Equal(4, factory.UserAgents.Count);
+ Assert.True(factory.UserAgents.Any(u => u.Product.Name == "test1" && u.Product.Version == "123"));
+ Assert.True(factory.UserAgents.Any(u => u.Product.Name == "test2" && u.Product.Version == "123"));
+ Assert.True(factory.UserAgents.Any(u => u.Product.Name == "test1" && u.Product.Version == "456"));
+ Assert.True(factory.UserAgents.Any(u => u.Product.Name == "test3" && u.Product.Version == null));
+ }
+
+ public virtual void Dispose(bool disposing)
+ {
+ if (disposing && password != null)
+ {
+ password.Dispose();
+ password = null;
+ }
+ }
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/src/Common/Commands.Common.Authentication.Test/Commands.Common.Authentication.Test.csproj b/src/Common/Commands.Common.Authentication.Test/Commands.Common.Authentication.Test.csproj
new file mode 100644
index 000000000000..763ebd8ca5d5
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/Commands.Common.Authentication.Test.csproj
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+ Debug
+ AnyCPU
+ {C2CF99A2-D35E-4AED-AFB9-C26960AF1D0D}
+ Library
+ Properties
+ Microsoft.Azure.Commands.Common.Authentication.Test
+ Microsoft.Azure.Commands.Common.Authentication.Test
+ v4.5
+ 512
+
+ ..\..\
+ true
+ 9fdcb6f4
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+ true
+ false
+
+
+ bin\Release
+ TRACE;SIGN
+ true
+ pdbonly
+ AnyCPU
+ bin\Release\Microsoft.Azure.Commands.Profile.Test.dll.CodeAnalysisLog.xml
+ true
+ GlobalSuppressions.cs
+ prompt
+ MinimumRecommendedRules.ruleset
+ ;$(ProgramFiles)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\Rule Sets
+ ;$(ProgramFiles)\Microsoft Visual Studio 12.0\Team Tools\Static Analysis Tools\FxCop\Rules
+ true
+ MSSharedLibKey.snk
+ true
+ true
+ false
+
+
+
+ ..\..\packages\Hyak.Common.1.0.3\lib\net45\Hyak.Common.dll
+ True
+
+
+ False
+ ..\..\packages\Microsoft.Azure.Common.2.1.0\lib\net45\Microsoft.Azure.Common.dll
+
+
+ False
+ ..\..\packages\Microsoft.Azure.Common.2.1.0\lib\net45\Microsoft.Azure.Common.NetFramework.dll
+
+
+
+ ..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.18.206251556\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll
+ True
+
+
+ ..\..\packages\Microsoft.Rest.ClientRuntime.2.0.1\lib\portable-net45+win+wpa81\Microsoft.Rest.ClientRuntime.dll
+ True
+
+
+ ..\..\packages\Microsoft.Rest.ClientRuntime.Azure.3.0.2\lib\net45\Microsoft.Rest.ClientRuntime.Azure.dll
+ True
+
+
+ ..\..\packages\Microsoft.Rest.ClientRuntime.Azure.Authentication.2.0.1-preview\lib\net45\Microsoft.Rest.ClientRuntime.Azure.Authentication.dll
+ True
+
+
+ ..\..\packages\Microsoft.WindowsAzure.Management.Storage.5.1.1\lib\net40\Microsoft.WindowsAzure.Management.Storage.dll
+ True
+
+
+ ..\..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll
+
+
+ ..\..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll
+
+
+
+
+
+ ..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Extensions.dll
+ True
+
+
+ ..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll
+ True
+
+
+
+
+ ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
+ True
+
+
+ ..\..\packages\xunit.assert.2.1.0\lib\portable-net45+win8+wp8+wpa81\xunit.assert.dll
+ True
+
+
+ ..\..\packages\xunit.extensibility.core.2.1.0\lib\portable-net45+win8+wp8+wpa81\xunit.core.dll
+ True
+
+
+ ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ {d3804b64-c0d3-48f8-82ec-1f632f833c9e}
+ Commands.Common.Authentication
+
+
+ {5ee72c53-1720-4309-b54b-5fb79703195f}
+ Commands.Common
+
+
+ {c1bda476-a5cc-4394-914d-48b0ec31a710}
+ Commands.ScenarioTests.Common
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Common/Commands.Common.Authentication.Test/ConversionUtilitiesTests.cs b/src/Common/Commands.Common.Authentication.Test/ConversionUtilitiesTests.cs
new file mode 100644
index 000000000000..2c18f9d7db82
--- /dev/null
+++ b/src/Common/Commands.Common.Authentication.Test/ConversionUtilitiesTests.cs
@@ -0,0 +1,124 @@
+// ----------------------------------------------------------------------------------
+//
+// 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.Azure.Commands.Common.Authentication;
+using System.Collections.Generic;
+using Microsoft.WindowsAzure.Commands.ScenarioTest;
+using Xunit;
+
+namespace Microsoft.WindowsAzure.Commands.Common.Test
+{
+ public class ConversionUtilitiesTests
+ {
+ [Fact]
+ [Trait(Category.AcceptanceType, Category.CheckIn)]
+ public void DeserializeJsonWorksForSimpleCases()
+ {
+ const string json1 =
+ @"{
+ ""foo1"": ""bar1"",
+ ""foo2"": ""bar2"",
+ ""num"": 25,
+ ""address"":
+ {
+ ""streetAddress"": ""123 Main Str"",
+ ""city"": ""Some City"",
+ },
+ ""list"":
+ [
+ {
+ ""val1"": ""a"",
+ ""val2"": ""b""
+ },
+ {
+ ""val3"": ""c"",
+ ""val4"": ""d""
+ }
+ ]
+ }";
+
+ Dictionary result;
+ result = JsonUtilities.DeserializeJson(json1);
+ Assert.NotNull(result);
+ Assert.Equal(5, result.Count);
+ Assert.Equal(2, ((Dictionary)result["address"]).Count);
+ Assert.Equal(2, ((List