此示例使用计算机池增长功能,以在计划测试后将测试添加到并自动重新分发到目标。
运行此示例前,必须执行以下操作:
设置两个运行相同的 CPU 系列和操作系统的系统,且它们拥有相同的目标或目标集(例如,相同的硬件 ID)。
在其中一个系统上创建项目,添加目标并将大量测试添加到队列。
将第二个系统移动到与第一个系统相同的计算机池(使用 HLK Studio 或以编程方式),然后运行示例。
C#
//-----------------------------------------------------------------------
// <copyright file="MachinePoolGrowthSample.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
[assembly: System.CLSCompliant(true)]
namespace Microsoft.Windows.Kits.Samples
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Windows.Kits.Hardware.ObjectModel;
using Microsoft.Windows.Kits.Hardware.ObjectModel.DBConnection;
/// <summary>
/// This sample for using the Machine Pool Growth feature to add and automatically redistribute tests to targets after
/// a test has been scheduled.
///
/// Before running this sample,
/// 1. Set up two systems running the same CPU family and operating system with the same target or sets of targets on both (e.g. same Hardware Ids).
/// 2. Create a project on one system, add the target(s) and queue up lots of tests.
/// 3. Move the second to the same machine pool (using HLK Studio or programmatically) as the first system and run the sample.
/// </summary>
class MachinePoolGrowthSample
{
/// <summary>
/// Main entry point.
/// </summary>
/// <param name="args">
/// The command line arguments for the application.
/// The first argument is the controller name to connect to.
/// The second argument is the project to redistribute tests for newly added targets.
/// </param>
/// <exception cref="ArgumentException">Thrown if two arguments are not specified.</exception>
static void Main(string[] args)
{
if (args.Length != 2)
{
throw new ArgumentException("args");
}
string serverName = args[0];
string runningProject = args[1];
// get a server name
ProjectManager manager = new DatabaseProjectManager(serverName);
Project project = manager.GetProject( runningProject );
List<Target> addedTargets = new List<Target>();
// walk through each product instance...
foreach (ProductInstance instance in project.GetProductInstances())
{
// get any matching targets from machines in the same pool that are not a part of the current target set
Console.WriteLine("Looking for any targets in Machine Pool {0}{1} that contain similar targets", instance.MachinePool.Path, instance.MachinePool.Name);
// loop through product instance's target family
foreach (TargetFamily targetFamily in instance.GetTargetFamilies())
{
// loop through any targets compatible with the current target family
foreach( TargetData targetData in instance.FindTargetFromDeviceFamily(targetFamily.Family) )
{
if (targetFamily.IsValidTarget(targetData))
{
// create target and add it to the added target set if we can.
addedTargets.Add(targetFamily.CreateTarget(targetData));
}
}
}
}
// nothing to do if there are no targets compatible with the specified project that have not already been added.
if (addedTargets.Count == 0)
{
Console.WriteLine("No targets were added to the project, no tests to redistribute.");
return;
}
IList<TestResult> cancelFailedResults;
IList<TestResult> cancelledResults;
IList<TestResult> reScheduledResults;
IList<Test> rescheduleFailedTests;
// do test redistribution across newly added targets
Target.RedistributeScheduledTests(addedTargets, out cancelFailedResults, out cancelledResults, out reScheduledResults, out rescheduleFailedTests);
// print out results that were successfully rescheduled.
if (reScheduledResults.Count > 0)
{
Console.WriteLine("Test results which were successfully rescheduled:");
foreach (TestResult result in reScheduledResults)
{
LogTestResultData(result);
}
}
// print out tests that could not be successfully rescheduled.
if (rescheduleFailedTests.Count > 0)
{
Console.WriteLine("The following tests could not be rescheduled:");
foreach (Test test in rescheduleFailedTests)
{
Console.WriteLine("Test '{0}' for device {1}'", test.Name, test.GetTestTargets()[0].TargetFamily.Family.Name);
}
}
// print out tests that could not be cancelled, if any
if (cancelFailedResults.Count > 0)
{
Console.WriteLine("Test results which could not be cancelled:");
foreach (TestResult result in cancelFailedResults)
{
LogTestResultData(result);
}
}
// print out results that were successfuly cancelled.
if (cancelledResults.Count > 0)
{
Console.WriteLine("Test results which weres successfully cancelled:");
foreach (TestResult result in cancelledResults)
{
LogTestResultData(result);
}
}
}
/// <summary>
/// Dump out information about the result that was cancelled/rescheduled/failed to reschedule.
/// </summary>
/// <param name="result">The result object to dump name/info for.</param>
static void LogTestResultData(TestResult result)
{
List<Test> tests = new List<Test>();
// Note: Calling IsMultiDevice and GetAllTests on results that have not run or are not capable of running in MultiDevice mode
// will work, but checking if the test is capable of running in MultiDevice mode can make the code run a bit quicker.
if (result.Test.ScheduleOptions.HasFlag(DistributionOption.ConsolidateScheduleAcrossTargets) && result.IsMultiDevice)
{
Console.WriteLine("Test {0} for multiple targets running as a Multi-Device test:", result.Test.Name);
// Get all targets for all tests that were rolled up into the result for MultiDevice tests
foreach (Test test in result.GetAllTests())
{
Console.WriteLine(" {0}", test.GetTestTargets()[0].TargetFamily.Family.Name);
}
}
else
{
// For non-multidevice results, there will always be only one test associated with the results and can result.Test.
Console.WriteLine("Test {0} for target {1}", result.Test.Name, result.Test.GetTestTargets()[0].TargetFamily.Family.Name);
}
}
}
}
PowerShell
Clear-Host;
$ObjectModel = [Reflection.Assembly]::LoadFrom($env:WTTSTDIO + "Microsoft.Windows.Kits.Hardware.objectmodel.dll")
$ObjectModel = [Reflection.Assembly]::LoadFrom($env:WTTSTDIO + "Microsoft.Windows.Kits.Hardware.objectmodel.dbconnection.dll")
$ObjectModel = [Reflection.Assembly]::LoadFrom($env:WTTSTDIO + "Microsoft.Windows.Kits.Hardware.objectmodel.submission.dll")
# Dump out information about a test result
Function LogTestResultData( $testResult )
{
if( ( ($testResult.Test.ScheduleOptions -band [Microsoft.Windows.Kits.Hardware.ObjectModel.DistributionOption]::ConsolidateScheduleAcrossTargets ) -eq [Microsoft.Windows.Kits.Hardware.ObjectModel.DistributionOption]::ConsolidateScheduleAcrossTargets ) -and $testResult.IsMultiDevice )
{
Write-Host "Test $($testResult.Test.Name) for multiple targets running as a Multi-Device test";
foreach( $test in $testResult.GetAllTests() )
{
Write-Host " $($test.GetTestTargets()[0].TargetFamily.Family.Name)";
}
}
else
{
Write-Host "Test $($testResult.Test.Name) for target $($testResult.Test.GetTestTargets()[0].TargetFamily.Family.Name)";
}
}
$connectFileName = $env:WTTSTDIO + "connect.xml"
Write-Host Opening connection file $connectFileName
$connectFile = [xml](Get-Content $connectFileName)
$ControllerName = $connectFile.Connection.GetAttribute("Server")
$DatabaseName = $connectFile.Connection.GetAttribute("Source")
$Manager = new-object -typename Microsoft.Windows.Kits.Hardware.ObjectModel.DBConnection.DatabaseProjectManager -Args $ControllerName, $DatabaseName
$addedTargetList = New-Object -TypeName System.Collections.Generic.List``1[Microsoft.Windows.Kits.Hardware.ObjectModel.Target];
#Load Project
$Project = $Manager.GetProject("Test");
foreach($productInstance in $Project.GetProductInstances())
{
$currentPool = $productInstance.MachinePool;
Write-Host "Looking for any targets in $($currentPool.Path)$($CurrentPool.Name) that are compatible with the current project"
foreach ($targetFamily in $productInstance.GetTargetFamilies())
{
foreach($targetData in $productInstance.FindTargetFromDeviceFamily($targetFamily.Family))
{
if($targetFamily.IsValidTarget($targetData))
{
$addedTargetList.Add($targetFamily.CreateTarget($targetData));
}
}
}
}
# no targets to expand project to -- nothing to do
if($addedTargetList.Count -eq 0 )
{
Write-Host "No compatible targets were found, returning";
return;
}
foreach($addedTarget in $addedTargetList)
{
Write-Host "Added target $($addedTarget.Name) on machine $($addedTarget.Machine.Name)"
}
$cancelFailedResults= New-Object -TypeName System.Collections.Generic.List``1[Microsoft.Windows.Kits.Hardware.ObjectModel.TestResult];
$cancelledResults= New-Object -TypeName System.Collections.Generic.List``1[Microsoft.Windows.Kits.Hardware.ObjectModel.TestResult];
$rescheduledResults= New-Object -TypeName System.Collections.Generic.List``1[Microsoft.Windows.Kits.Hardware.ObjectModel.TestResult];
$rescheduleFailedTests= New-Object -TypeName System.Collections.Generic.List``1[Microsoft.Windows.Kits.Hardware.ObjectModel.Test];
[Microsoft.Windows.Kits.Hardware.ObjectModel.Target]::RedistributeScheduledTests($addedTargetList, [ref]$cancelFailedResults, [ref]$cancelledResults, [ref]$reScheduledResults, [ref]$rescheduleFailedTests);
# display test results which were rescheduled using machine pool growth
if($rescheduledResults.Count -gt 0 )
{
Write-Host
Write-Host "Test results which were successfully rescheduled:";
foreach($rescheduledResult in $rescheduledResults)
{
LogTestResultData( $rescheduledResult );
}
}
# display tests that could not be rescheduled
if( $rescheduleFailedTests.Count -gt 0 )
{
Write-Host
Write-Host "The following tests could not be rescheduled:";
foreach( $test in $rescheduleFailedTests )
{
Write-Host "Test $($test.Name) for device $($test.GetTestTargets()[0].TargetFamily.Family)";
}
}
# display tests that were successfully cancelled after it was rescheduled
if($cancelledResults.Count -gt 0 )
{
Write-Host
Write-Host "Test results which were successfully cancelled";
foreach($cancelledResult in $cancelledResults)
{
LogTestResultData( $cancelledResult );
}
}
# display tests that could not be cancelled after it was rescheduled
if($cancelFailedResults.Count -gt 0 )
{
Write-Host
Write-Host "Test results which could not be cancelled:";
foreach($cancelFailedResult in $cancelFailedResults)
{
LogTestResultData( $cancelFailedResult );
}
}