Skip to content

Batch first OM based cmdlet #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions src/ResourceManager/Batch/Commands.Batch.Test/BatchTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,23 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

using System.Net;
using Microsoft.Azure.Batch.Protocol;
using Microsoft.Azure.Batch.Protocol.Entities;
using Microsoft.Azure.Management.Batch.Models;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Xunit;

namespace Microsoft.Azure.Commands.Batch.Test
{
public static class BatchTestHelpers
{
/// <summary>
/// Builds an AccountResource object using the specified parameters
/// </summary>
public static AccountResource CreateAccountResource(string accountName, string resourceGroupName, Hashtable[] tags = null)
{
string tenantUrlEnding = "batch-test.windows-int.net";
Expand All @@ -39,9 +47,28 @@ public static AccountResource CreateAccountResource(string accountName, string r
{
resource.Tags = Microsoft.Azure.Commands.Batch.Helpers.CreateTagDictionary(tags, true);
}

return resource;
}

/// <summary>
/// Builds a BatchAccountContext object with the keys set for testing
/// </summary>
public static BatchAccountContext CreateBatchContextWithKeys()
{
AccountResource resource = CreateAccountResource("account", "resourceGroup");
BatchAccountContext context = BatchAccountContext.ConvertAccountResourceToNewAccountContext(resource);
string dummyKey = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
SetProperty(context, "PrimaryAccountKey", dummyKey);
SetProperty(context, "SecondaryAccountKey", dummyKey);

return context;
}


/// <summary>
/// Verifies that two BatchAccountContext objects are equal
/// </summary>
public static void AssertBatchAccountContextsAreEqual(BatchAccountContext context1, BatchAccountContext context2)
{
if (context1 == null)
Expand All @@ -67,5 +94,52 @@ public static void AssertBatchAccountContextsAreEqual(BatchAccountContext contex
Assert.Equal<string>(context1.TagsTable, context2.TagsTable);
Assert.Equal<string>(context1.TaskTenantUrl, context2.TaskTenantUrl);
}

/// <summary>
/// Builds a GetWorkItemResponse object
/// </summary>
public static GetWorkItemResponse CreateGetWorkItemResponse(string workItemName)
{
GetWorkItemResponse response = new GetWorkItemResponse();
SetProperty(response, "StatusCode", HttpStatusCode.OK);

JobExecutionEnvironment jee = new JobExecutionEnvironment();

WorkItem workItem = new WorkItem(workItemName, jee);
SetProperty(response, "WorkItem", workItem);

return response;
}

/// <summary>
/// Builds a ListWorkItemsResponse object
/// </summary>
public static ListWorkItemsResponse CreateListWorkItemsResponse(IEnumerable<string> workItemNames)
{
ListWorkItemsResponse response = new ListWorkItemsResponse();
SetProperty(response, "StatusCode", HttpStatusCode.OK);

List<WorkItem> workItems = new List<WorkItem>();
JobExecutionEnvironment jee = new JobExecutionEnvironment();

foreach (string name in workItemNames)
{
workItems.Add(new WorkItem(name, jee));
}

SetProperty(response, "WorkItems", workItems);

return response;
}

/// <summary>
/// Uses Reflection to set a property value on an object. Can be used to bypass restricted set accessors.
/// </summary>
private static void SetProperty(object obj, string propertyName, object propertyValue)
{
Type t = obj.GetType();
PropertyInfo propInfo = t.GetProperty(propertyName);
propInfo.SetValue(obj, propertyValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>49379715</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -38,6 +39,10 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Azure.Batch, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Azure.Batch.1.1.0\lib\net45\Microsoft.Azure.Batch.dll</HintPath>
</Reference>
<Reference Include="Hyak.Common">
<HintPath>..\..\..\packages\Hyak.Common.1.0.1\lib\portable-net403+win+wpa81\Hyak.Common.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -72,6 +77,12 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Microsoft.Azure.Test.HttpRecorder.1.0.5486.28526-prerelease\lib\net45\Microsoft.Azure.Test.HttpRecorder.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Data.Edm, Version=5.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Data.Edm.5.6.0\lib\net40\Microsoft.Data.Edm.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Data.OData, Version=5.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\Microsoft.Data.OData.5.6.0\lib\net40\Microsoft.Data.OData.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.11.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.11.10918.1222\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
Expand All @@ -80,16 +91,33 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.11.10918.1222\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Configuration">
<HintPath>..\..\..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Storage, Version=2.1.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why such an old version of storage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Batch OM (in the Microsoft.Azure.Batch NuGet package) was built on the older version. There were breaking changes in the newest version of the storage library, so the owners of the Batch OM opted to stay on the older version for the time being.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh. There should be an issue filed to address the breaking changes there and move to something more current.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worse than this - I don't believe we can accept this without the OM upgrading to staorage 4.0. There will be confliucts with the other resources modules and too much possibility for regression

<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\WindowsAzure.Storage.2.1.0.4\lib\net40\Microsoft.WindowsAzure.Storage.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Testing, Version=1.0.5417.13285, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Hydra.SpecTestSupport.1.0.5417.13285-prerelease\lib\net45\Microsoft.WindowsAzure.Testing.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Microsoft.WindowsAzure.Management.4.0.1\lib\net40\Microsoft.WindowsAzure.Management.dll</HintPath>
</Reference>
<Reference Include="Moq">
<HintPath>..\..\..\packages\Moq.4.2.1402.2112\lib\net40\Moq.dll</HintPath>
</Reference>
<Reference Include="xunit, Version=1.9.2.1705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Data.Services.Client" />
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>D:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll</HintPath>
Expand All @@ -105,9 +133,11 @@
<HintPath>..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="xunit">
<HintPath>..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
<Reference Include="System.Spatial, Version=5.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\System.Spatial.5.6.0\lib\net40\System.Spatial.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Newtonsoft.Json">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
Expand All @@ -125,6 +155,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ScenarioTests\BatchAccountTests.cs" />
<Compile Include="ScenarioTests\BatchController.cs" />
<Compile Include="WorkItems\GetBatchWorkItemCommandTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="MSSharedLibKey.snk" />
Expand Down Expand Up @@ -180,6 +211,9 @@
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Content Include="about.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
using Microsoft.Azure.Management.Resources;
using Microsoft.Azure.Test;
using Microsoft.WindowsAzure.Commands.ScenarioTest;
using Microsoft.WindowsAzure.Commands.Utilities.Common;
using Microsoft.Azure.Test;
using System;
using System.Linq;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// ----------------------------------------------------------------------------------
//
// 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.Batch;
using Microsoft.Azure.Batch.Protocol;
using Microsoft.Azure.Batch.Protocol.Entities;
using Microsoft.Azure.Commands.Batch.Models;
using Microsoft.WindowsAzure.Commands.ScenarioTest;
using Moq;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.Azure.Commands.Batch.Test.WorkItems
{
public class GetBatchWorkItemCommandTests
{
private GetBatchWorkItemCommand cmdlet;
private Mock<BatchClient> batchClientMock;
private Mock<ICommandRuntime> commandRuntimeMock;

public GetBatchWorkItemCommandTests()
{
batchClientMock = new Mock<BatchClient>();
commandRuntimeMock = new Mock<ICommandRuntime>();
cmdlet = new GetBatchWorkItemCommand()
{
CommandRuntime = commandRuntimeMock.Object,
BatchClient = batchClientMock.Object,
};
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void GetBatchWorkItemTest()
{
// Setup cmdlet to get a WorkItem by name
BatchAccountContext context = BatchTestHelpers.CreateBatchContextWithKeys();
cmdlet.BatchContext = context;
cmdlet.Name = "testWorkItem";
cmdlet.Filter = null;

// Build a WorkItem instead of querying the service on a GetWorkItem call
YieldInjectionInterceptor interceptor = new YieldInjectionInterceptor((opContext, request) =>
{
if (request is GetWorkItemRequest)
{
GetWorkItemResponse response = BatchTestHelpers.CreateGetWorkItemResponse(cmdlet.Name);
Task<object> task = Task<object>.Factory.StartNew(() => { return response; });
return task;
}
return null;
});
cmdlet.AdditionalBehaviors = new List<BatchClientBehavior>() { interceptor };

// Setup the cmdlet to write pipeline output to a list that can be examined later
List<PSCloudWorkItem> pipeline = new List<PSCloudWorkItem>();
commandRuntimeMock.Setup(r => r.WriteObject(It.IsAny<PSCloudWorkItem>())).Callback<object>(w => pipeline.Add((PSCloudWorkItem)w));

cmdlet.ExecuteCmdlet();

// Verify that the cmdlet wrote the WorkItem returned from the OM to the pipeline
Assert.Equal(1, pipeline.Count);
Assert.Equal(cmdlet.Name, pipeline[0].Name);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void ListBatchWorkItemByODataFilterTest()
{
// Setup cmdlet to list WorkItems using an OData filter
BatchAccountContext context = BatchTestHelpers.CreateBatchContextWithKeys();
cmdlet.BatchContext = context;
cmdlet.Name = null;
cmdlet.Filter = "startswith(name,'test')";

string[] namesOfConstructedWorkItems = new[] {"test1", "test2"};

// Build some WorkItems instead of querying the service on a ListWorkItems call
YieldInjectionInterceptor interceptor = new YieldInjectionInterceptor((opContext, request) =>
{
if (request is ListWorkItemsRequest)
{
ListWorkItemsResponse response = BatchTestHelpers.CreateListWorkItemsResponse(namesOfConstructedWorkItems);
Task<object> task = Task<object>.Factory.StartNew(() => { return response; });
return task;
}
return null;
});
cmdlet.AdditionalBehaviors = new List<BatchClientBehavior>() { interceptor };

// Setup the cmdlet to write pipeline output to a list that can be examined later
List<PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>> pipeline = new List<PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>>();
commandRuntimeMock.Setup(r =>
r.WriteObject(It.IsAny<PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>>()))
.Callback<object>(w => pipeline.Add((PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>)w));

cmdlet.ExecuteCmdlet();

// Verify that the cmdlet wrote the enumerator to the pipeline and that it contains the constructed WorkItems
Assert.Equal(1, pipeline.Count);
int workItemCount = 0;
foreach (PSCloudWorkItem w in pipeline[0])
{
Assert.True(namesOfConstructedWorkItems.Contains(w.Name));
workItemCount++;
}
Assert.Equal(namesOfConstructedWorkItems.Length, workItemCount);
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void ListBatchWorkItemWithoutFiltersTest()
{
// Setup cmdlet to list WorkItems without filters
BatchAccountContext context = BatchTestHelpers.CreateBatchContextWithKeys();
cmdlet.BatchContext = context;
cmdlet.Name = null;
cmdlet.Filter = null;

string[] namesOfConstructedWorkItems = new[] { "name1", "name2", "name3" };

// Build some WorkItems instead of querying the service on a ListWorkItems call
YieldInjectionInterceptor interceptor = new YieldInjectionInterceptor((opContext, request) =>
{
if (request is ListWorkItemsRequest)
{
ListWorkItemsResponse response = BatchTestHelpers.CreateListWorkItemsResponse(namesOfConstructedWorkItems);
Task<object> task = Task<object>.Factory.StartNew(() => { return response; });
return task;
}
return null;
});
cmdlet.AdditionalBehaviors = new List<BatchClientBehavior>() { interceptor };

// Setup the cmdlet to write pipeline output to a list that can be examined later
List<PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>> pipeline = new List<PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>>();
commandRuntimeMock.Setup(r =>
r.WriteObject(It.IsAny<PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>>()))
.Callback<object>(w => pipeline.Add((PSAsyncEnumerable<PSCloudWorkItem, ICloudWorkItem>)w));

cmdlet.ExecuteCmdlet();

// Verify that the cmdlet wrote the enumerator to the pipeline and that it contains the constructed WorkItems
Assert.Equal(1, pipeline.Count);
int workItemCount = 0;
foreach (PSCloudWorkItem w in pipeline[0])
{
Assert.True(namesOfConstructedWorkItems.Contains(w.Name));
workItemCount++;
}
Assert.Equal(namesOfConstructedWorkItems.Length, workItemCount);
}
}
}
Loading