diff --git a/.gitignore b/.gitignore index b52cf5d..200e2bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,339 @@ -bin -obj -drop +# User-specific files +*.rsuser *.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ +# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true +**/wwwroot/lib/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb # Generated files src/testtools.extendedlogging/Microsoft.Protocols.TestTools.ExtendedLogging.XML diff --git a/InstallPrerequisites/InstallPrerequisites.ps1 b/InstallPrerequisites/InstallPrerequisites.ps1 deleted file mode 100644 index 62dca45..0000000 --- a/InstallPrerequisites/InstallPrerequisites.ps1 +++ /dev/null @@ -1,300 +0,0 @@ -# Copyright (c) Microsoft. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -<# -.SYNOPSIS - Install prerequisite tools -.DESCRIPTION - This Powershell script is used to download and install prerequisite software dependencies for Protocol Test Framework. -.PARAMETER ConfigPath - The ConfigPath is used to specify prerequisites configure file path, default value is ".\PrerequisitesConfig.xml". - -.EXAMPLE - C:\PS>.\InstallPrerequisites.ps1 -ConfigPath ".\PrerequisitesConfig.xml" - The PS script will get all tools defined in PrerequisitesConfig.xml, then download and install these tools. -#> -Param -( - [parameter(Mandatory=$false, ValueFromPipeline=$true, HelpMessage="The ConfigPath is used to specify prerequisites configure file path")] - [String]$ConfigPath -) - -if(-not $ConfigPath) -{ - Write-Host "Use the default value '.\PrerequisitesConfig.xml' as ConfigPath is not set" - $ConfigPath = ".\PrerequisitesConfig.xml" -} - -$Category = "PTF" - -# Check if application is installed on current machine. -Function CheckIfAppInstalled{ - Param ( - [string]$AppName, # Application Name - [string]$Version, # Application Version - [bool]$Compatible # Is support backward compatible - ) - - #check if the required software is installed on current machine - if ([IntPtr]::Size -eq 4) { - $regpath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' - } - else { - $regpath = @( - 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' - 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' - ) - } - - $app = Get-ItemProperty $regpath | .{process{if($_.DisplayName -and $_.UninstallString) { $_ } }} | Where-Object {$_.DisplayName -match $AppName} | Select DisplayName, DisplayVersion -First 1 - - if($app){ - if($Compatible){ - return ([System.Version]$app.DisplayVersion -ge [System.Version]$Version); - }else{ - return ([System.Version]$app.DisplayVersion -eq [System.Version]$Version); - } - }else{ - if($AppName -match "Microsoft Agents for Visual Studio"){ - #If Test Agent was not installed we also need check if Visual Studio installed. - $app = Get-ItemProperty $regpath | .{process{if($_.DisplayName -and $_.UninstallString) { $_ } }} | Where-Object {$_.DisplayName -match "Microsoft Visual Studio \d{4} Devenv"} | Sort-Object -Property DisplayVersion -Descending | Select DisplayName, Version, DisplayVersion -First 1 - if($app){ - return $true; - } - } - return $false; - } -} - -# Mount ISO and return application path searched from ISO -Function MountISOAndGetAppPath{ - Param ( - [string]$AppName, - [string]$ISOPath - ) - # Mount ISO and get drive letter - $iso = Mount-DiskImage -ImagePath $ISOPath -StorageType ISO -PassThru - $driveLetter = ($iso | Get-Volume).DriveLetter - - # Find application in ISO - $driveLetter = $driveLetter + ":" - - $appPath = Get-ChildItem -Path $driveLetter -Filter $AppName -Recurse - if(-not $appPath) - { - $content = $AppName + "cannot be found in ISO" - Write-Host $content -ForegroundColor Red - retun ""; - }else - { - return $appPath.FullName; - } -} - -# Reject app Disk -Function UnmountDisk{ - Param ( - [string]$AppPath - ) - - $DriveLetter = (Get-Item $appPath).PSDrive.Name - $ShellApplication = New-Object -ComObject Shell.Application - Write-Host "Eject DVD Drive: "$DriveLetter - $ShellApplication.Namespace(17).ParseName($DriveLetter+":").InvokeVerb("Eject") -} - -# Get tools to be downloaded from Config file by Category -Function GetDownloadTools{ - Param( - [string]$DpConfigPath, - [string]$ToolCategory - ) - - Write-Host "Reading Prerequisites Configure file..." - [xml]$toolXML = Get-Content -Path $DpConfigPath #".\PrerequisitesConfig.xml" - - # Check if Category exists. - $CategoryItem = $toolXML.Dependency.$ToolCategory.tool; - if(-not ($CategoryItem)) - { - $error = "Category $ToolCategory does not exist"; - throw $error - } - - $tools = New-Object System.Collections.ArrayList; - - Write-Host "Get information of all the Prerequisite tools from Configure file" - foreach($item in $toolXML.Dependency.tools.tool) - { - $tool = '' | select Name,FileName,AppName,Version,URL,Arguments,InstallFileName,NeedRestart,BackwardCompatible - - $tool.Name = $item.name; - $tool.FileName = $item.FileName; - $tool.AppName = $item.AppName; - $tool.Version = $item.version; - $tool.URL = $item.url; - $tool.InstallFileName = $item.InstallFileName; - $tool.NeedRestart = $false - $tool.BackwardCompatible = $true - - if($item.NeedRestart) - { - $tool.NeedRestart = [bool]$item.NeedRestart; - } - if($item.BackwardCompatible) - { - $tool.BackwardCompatible = [bool]$item.BackwardCompatible; - } - $tool.Arguments = $item.arguments; - - $index = $tools.Add($tool) - } - - Write-Host "Get the tools to be downloaded from the specified category" - $downloadList = New-Object System.Collections.ArrayList; - foreach($item in $toolXML.Dependency.$ToolCategory.tool) - { - $ndTool = $tools | Where-Object{$_.Name -eq $item} | Select-Object $_ - $index = $downloadList.Add($ndTool) - } - - $tools.Clear(); - return $downloadList; -} - -# Create a tempoary folder under current folder, which is used to store downloaded files. -Function CreateTemporaryFolder{ - #create temporary folder for downloading tools - $tempPath = (get-location).ToString() + "\" + [system.guid]::newguid().ToString() - Write-Host "Create temporary folder for downloading files" - $outFile = New-Item -ItemType Directory -Path $tempPath - Write-Host "Temporary folder $outFile is created" - - return $outFile.FullName -} - -# Download and install prerequisite tool -Function DownloadAndInstallApplication -{ - param( - [int]$PSVersion, - $AppItem, - [string]$OutputPath - ) - # Check if Powershell version greate than 3.0, if not then use WebClient to download file, otherwise use Invoke-WebRequest. - if($psVersion -ge 3) - { - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - Invoke-WebRequest -Uri $AppItem.URL -OutFile $OutputPath - }else - { - (New-Object System.Net.WebClient).DownloadFile($AppItem.URL, $OutputPath) - } - - $content = "Downloading " + $AppItem.Name + " completed. Path:" + $OutputPath - Write-Host $content - - # Check if the downloaded file is ISO - if($AppItem.FileName.ToLower().EndsWith("iso")) - { - if($psVersion -ge 3) - { - Write-Host "Mounting ISO image"; - $OutputPath = MountISOAndGetAppPath -AppName $AppItem.InstallFileName -ISOPath $OutputPath - Write-Host $OutputPath - } - else - { - $content = "Your system does not support Mount-DiskImage command. Please install " + $AppItem.AppName; - - Write-Host "Your system does not support Mount-DiskImage command. Please mount and install manually"; - } - } - - # start to Install file - $content = "Installing " + $AppItem.Name + ". Please wait..." - Write-Host $content - - $FLAGS = $AppItem.Arguments - - $ExitCode = (Start-Process -FILEPATH $OutputPath $FLAGS -Wait -PassThru).ExitCode - if ($ExitCode -EQ 0) - { - $content = "Application " + $AppItem.Name +" is successfully installed on current machine" - Write-Host $content -ForegroundColor Green - } - else - { - $failedList += $AppItem.Name - $content = "Installing " + $AppItem.Name +" failed, Error Code:" + $ExitCode - Write-Host "ERROR $ExitCode"; - } - - # If the file is ISO, unmount it. - if($AppItem.FileName.ToLower().EndsWith("iso")) - { - UnmountDisk -AppPath $OutputPath - } -} - -# Start get all needed tools from configure file. -$downloadList = GetDownloadTools -DpConfigPath $ConfigPath -ToolCategory $Category -$tempFolder = CreateTemporaryFolder -$failedList = @(); -$IsNeedRestart = $false; - -# Check PowerShell version - -$psVer = [int](Get-Host).Version.ToString().Substring(0,1) - -foreach($item in $downloadList) -{ - $isInstalled = $false; - $isInstalled = CheckIfAppInstalled -AppName $item.AppName -Version $item.version -Compatible $item.BackwardCompatible - if(-not $isInstalled) - { - $content = "Application: " +$item.AppName + " is not installed" - } - - if ($item.Name.ToLower().Equals("vs2017community")) - { - cmd.exe /C "InstallVs2017Community.cmd" - } - else - { - if(-not $IsInstalled) - { - Write-Host $content -ForegroundColor Yellow - - $content = "Downloading file " + $item.Name + ". Please wait..." - Write-Host $content - $outputPath = $tempFolder + "\" + $item.FileName - - try - { - DownloadAndInstallApplication -PSVersion $psVer -AppItem $item -OutputPath $outputPath - } - catch - { - $failedList += $item.Name - $IsInstalled = $false; - $ErrorMessage = $_.Exception.Message - Write-Host $ErrorMessage -ForegroundColor Red - Break; - } - - if($item.NeedRestart) - { - $IsNeedRestart = $true; - } - } - } -} - -if($psVersion -ge 3) -{ - $downloadList.Clear(); -} -else{ - $downloadList = @(); -} diff --git a/InstallPrerequisites/InstallPrerequisitesForPTF.ps1 b/InstallPrerequisites/InstallPrerequisitesForPTF.ps1 new file mode 100644 index 0000000..45be04f --- /dev/null +++ b/InstallPrerequisites/InstallPrerequisitesForPTF.ps1 @@ -0,0 +1,71 @@ +# Copyright (c) Microsoft. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. + +# Download files +Function DownloadFile +{ + param( + $File + ) + + $Uri = $prefix + $File.title + $OutFile = $File.title + try { + Invoke-WebRequest -Uri $Uri -OutFile $OutFile + } + catch + { + try + { + (New-Object System.Net.WebClient).DownloadFile($Uri, $OutFile) + } + catch + { + Write-host "Download $item.Name failed with exception: $_.Exception.Message" + Return + } + } +} + +$ifInstallPrerequisitesExist = Test-Path .\InstallPrerequisites.ps1 +$ifInstallVs2017CommunityExist = Test-Path .\InstallVs2017Community.cmd +$ifPrerequisitesConfigExist = Test-Path .\PrerequisitesConfig.xml +if (!$ifInstallPrerequisitesExist -or + !$ifInstallVs2017CommunityExist -or + !$ifPrerequisitesConfigExist) { + + try { + $prefix = "https://raw.githubusercontent.com/Microsoft/WindowsProtocolTestSuites/staging/InstallPrerequisites/" + $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12' + [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols + $WebResponse = Invoke-WebRequest https://github.com/Microsoft/WindowsProtocolTestSuites/tree/staging/InstallPrerequisites/ -UseBasicParsing + + # Download InstallVs2017Community.cmd + if (!$ifInstallVs2017CommunityExist) { + $CmdFile = $WebResponse.Links |?{$_.href -match "InstallVs2017Community.cmd"} + DownloadFile -File $CmdFile + } + + # Download PrerequisitesConfig.xml + if (!$ifPrerequisitesConfigExist) { + $XmlFile = $WebResponse.Links |?{$_.href -match "PrerequisitesConfig.xml"} + DownloadFile -File $XmlFile + } + + # Download InstallPrerequisites.ps1 + if (!$ifInstallPrerequisitesExist) { + $Ps1File = $WebResponse.Links |?{$_.href -match "InstallPrerequisites.ps1"} + DownloadFile -File $Ps1File + } + } + catch { + Write-Host "Please download the following InstallPrerequisites-related files manually from WindowsProtocolTestSuites Github page https://github.com/Microsoft/WindowsProtocolTestSuites/tree/staging/InstallPrerequisites" + Write-Host "1. InstallPrerequisites.ps1" + Write-Host "2. InstallVs2017Community.cmd" + Write-Host "3. PrerequisitesConfig.xml" + exit + } +} + +# Execute InstallPrerequisites.ps1 +.\InstallPrerequisites.ps1 -Category 'PTF' diff --git a/InstallPrerequisites/InstallVs2017Community.cmd b/InstallPrerequisites/InstallVs2017Community.cmd deleted file mode 100644 index d6dc1b7..0000000 --- a/InstallPrerequisites/InstallVs2017Community.cmd +++ /dev/null @@ -1,17 +0,0 @@ -:: Copyright (c) Microsoft. All rights reserved. -:: Licensed under the MIT license. See LICENSE file in the project root for full license information. - -:: Update vs installer -vs_community.exe --update --quiet --wait - -:: Install vs_community with the following -vs_community.exe --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community" ^ ---add Microsoft.VisualStudio.Workload.NativeDesktop ^ ---add Microsoft.VisualStudio.Workload.ManagedDesktop ^ ---add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ^ ---add Microsoft.Net.Component.4.7.1.TargetingPack ^ ---add Microsoft.Net.ComponentGroup.4.7.1.DeveloperTools ^ ---add Microsoft.VisualStudio.Component.Windows10SDK.16299.Desktop ^ ---add Microsoft.VisualStudio.Component.TestTools.Core ^ ---add Microsoft.Component.MSBuild ^ ---wait --passive --norestart diff --git a/InstallPrerequisites/PrerequisitesConfig.xml b/InstallPrerequisites/PrerequisitesConfig.xml deleted file mode 100644 index e23a0ea..0000000 --- a/InstallPrerequisites/PrerequisitesConfig.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - VS2017Community - Wix311 - SE - - diff --git a/README.md b/README.md index 1b5f5a2..7ffa1ed 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,29 @@ The Protocol Test Framework (PTF) is designed to support Microsoft Protocol Test It implements the fundamentals to support Protocol Test Suite, including logging, checker, configuration and etc. ## Prerequisites + PTF is based on Windows platform. -You should install the following list of software in order to build PTF from source code. -You can use the script in **InstallPrerequisites** folder to automatically download and install these software. +You should install the softwares listed below based on your testing purpose, including their own dependencies. +* [Visual Studio 2017](https://visualstudio.microsoft.com/downloads/) with some individual components required by installing in Visual Studio Installer: + + |Individual Component\Purpose|Run test suites based on Protocol Test Framework (PTF)|Build Protocol Test Framework (PTF) from source code| + |---|---|---| + |.NET Framework 4.7.1 targeting pack|Required|Required| + |Testing tools core features|Required|Required| + |.NET Framework 4.7.1 SDK||Required| + |C# and Visual Basic Roslyn compilers||Required| +* [Spec Explorer 2010 v3.5.3146.0](https://visualstudiogallery.msdn.microsoft.com/271d0904-f178-4ce9-956b-d9bfa4902745/). It is required if you want to build Protocol Test Framework (PTF) from source code. +* [Wix Toolset v3.11](https://github.com/wixtoolset/wix3/releases/tag/wix3111rtm) and [Wix Toolset Visual Studio 2017 Extension](https://marketplace.visualstudio.com/items?itemName=RobMensching.WixToolsetVisualStudio2017Extension). It is required if you want to build Protocol Test Framework (PTF) from source code. -* .Net framework 4.7.1 or higher -* Wix toolset [v3.11](https://github.com/wixtoolset/wix3/releases/tag/wix3111rtm) -* Visual Studio version 2017 -* [Spec Explorer](https://visualstudiogallery.msdn.microsoft.com/271d0904-f178-4ce9-956b-d9bfa4902745/) +You can use the script in **InstallPrerequisites** folder to automatically download and install these software. Tips when using the script in **InstallPrerequisites** folder: * To run the script, open **Windows PowerShell**, and execute the commands below in the **PowerShell Window**: ``` cd ProtocolTestFramework\InstallPrerequisites -.\InstallPrerequisites.ps1 +.\InstallPrerequisitesForPTF.ps1 ``` * If you meet errors about **Execution Policy**, make sure you run **Windows PowerShell** as **Administrator**, and type the following and enter: @@ -34,28 +41,31 @@ You could run the command below to verify if the **Execution Policy** is correct Get-ExecutionPolicy ``` - ## Build After you clone a copy of this repo, change to the ProtocolTestFramework directory: + ``` cd ProtocolTestFramework ``` Change to src directory and run build.cmd: + ``` cd src build.cmd ``` + After the build succeeds, ProtocolTestFrameworkInstaller.msi should be generated in the folder drop\ProtocolTestFramework\installer\. ## Samples + You can find samples of how to develop a protocol test suite using PTF [here](https://github.com/Microsoft/ProtocolTestFramework/tree/master/samples). ## Documentation -* [User Guide](https://github.com/Microsoft/ProtocolTestFramework/tree/master/docs/) describes the features of PTF, and how to use them to develop a new protocol test suite. +* [User Guide](https://github.com/Microsoft/ProtocolTestFramework/tree/master/docs/) describes the features of PTF, and how to use them to develop a new protocol test suite. ## Contribute @@ -66,4 +76,5 @@ You can find contributing guide [here](https://github.com/Microsoft/ProtocolTest PTF is under the [MIT license](https://github.com/Microsoft/ProtocolTestFramework/blob/master/LICENSE.txt). ## Microsoft Open Source Code of Conduct + This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/docs/PTFUserGuide.md b/docs/PTFUserGuide.md index 76d5a51..fe72f1d 100644 --- a/docs/PTFUserGuide.md +++ b/docs/PTFUserGuide.md @@ -141,128 +141,21 @@ ITestSite is disposed in the TestClassBase.Cleanup method call. The user must ca The configuration allows an adapter to be created in various ways: -* Script adapter - - The Script adapter allows users to map interface methods to cmd scripts and use the scripts to perform operations during the test. Users must specify the location of the scripts and have a .cmd script with a name corresponding to each API call in the test suit. Parameters will be output with standard .cmd quoting conventions. When the API is called, the script will be called and its stdout and stderr are recorded in the test log as LogEntryType.Comment. - * Interactive adapter The Interactive adapter pops up a dialog-box to perform manual operations each time one of its methods is called. The dialog-box includes the method name, help text, input parameters, output parameters, and result. Users can confirm the completion of the manual operation by clicking the "Continue" button. If users can’t finish the operation for some reason, they can click the "Abort" button to terminate the test. In this case, the test will be treated as "Inconclusive". -* PowerShell script adapter +* PowerShell adapter - PowerShell script adapter maps interface methods to PowerShell scripts. Users are able to pass objects between their managed test code and PowerShell scripts directly. This avoids the parameter and return value parsing issue. + PowerShell adapter maps interface methods to PowerShell scripts. Users are able to pass objects between their managed test code and PowerShell scripts directly. This avoids the parameter and return value parsing issue. -* Managed adapter - - The managed adapter allows users to use managed code to implement the interface methods. +* Shell adapter -* PowerShell wrapped adapter + The Shell adapter, which leverages Windows Subsystem for Linux (WSL), allows users to map interface methods to shell scripts and use the scripts to perform operations during the test. Users must specify the location of the scripts and have a .sh script with a name corresponding to each API call in the test suit. When the API is called, the script will be invoked and its stdout and stderr are recorded in the test log as LogEntryType.Comment. - PowerShell wrapped adapter allows users to use a single PowerShell ps1 file to implement an adapter interface. - -### Script Adapter - -Users can bind their adapter interfaces to a script adapter by defining them as "script" in the PTF configuration files. The implementation will run the corresponding script file when one of the adapter's methods is called. - -__Benefits__ - -Script adapters are easy to use. For example, they are suitable for service setup/shutdown jobs. Users can write a Start.cmd containing `net start ServiceName`. - -__Limitation__ - -Do not use script using Unicode with Byte Order Mark. - -__Usage__ - -Configure `` section of the ptfconfig file: - -``` - -``` - -Subsequently, users can invoke `IMyScriptAdapter.AMethod(parameters)`. PTF will look up a script named `AMethod.cmd` in the scriptdir directory and execute it with the parameters. - -__Parameters__ - -PTF invokes a cmd script using the following parameters: - - __Parameter name__ | __Value__ - -------------------|---------- -%1% |[PtfAdReturn:;][:[;:]…] -%2% |[:[;:] -%3% |Help text of the method. -%4% |First input parameter. -%5% |Second input parameter. -... | - -__Return values__ - -To pass a return value and out parameters value back to PTF, use the following syntax in a script: (case-sensitive, double quotation mark is required) - -``` -echo [PtfAdReturn="value"][;="value"[;="value"]…] -``` - -To pass a failure message back to PTF, use the following syntax in a script: (case-sensitive, double quotation mark is required) - -``` -echo PtfAdFailureMessage="" -``` - -Use the call keyword to call another script inside the current script, e.g.: - -``` -set foldername=%4 -call another.cmd -echo PtfAdReturn="%foldername%" > log.txt -echo PtfAdFailureMessage="Create folder %foldername% failed?" >log.txt -``` - -Provide the `ToString()` method and the `Parse()` method in a custom type to pass custom type values as parameters to script adapter, e.g.: - -``` -static public String ToString() -static public CustomType.Parse(String str) -``` - -__Exception__ - -If this script execution fails, PTF will raise an `AssertInconclusiveException`. - -__PTF Properties__ - -PTF properties are provided to script adapters by environment variables with ptfprop as prefix. -For example, if a user has the following configuration in the PTFconfig - -``` - - - - - - -``` - -__Examples__ - -1. Command `set ptfprop` can be used in the script to display all properties in the PTFconfig. User will get the outputs like: - -``` -2008-04-07 14:46:20.121 [Comment] STDOUT: ptfpropfeaturename=MS-ATSVC -2008-04-07 14:46:20.121 [Comment] STDOUT: ptfproptestname=ATSVC -2008-04-07 14:46:20.121 [Comment] STDOUT: ptfpropversion=2.0 -2008-04-07 14:46:20.121 [Comment] STDOUT: ptfpropservername=MS-Sever -``` -2. User can get the property value and use it directly in the script via the environment variables with "ptfprop" prefix. - -For example: - -Start an nps service on a server. The name of the server is specified using `servername` property. +* Managed adapter -``` -sc %ptfpropservername% start nps -``` + The managed adapter allows users to use managed code to implement the interface methods. ### Interactive Adapter @@ -412,6 +305,81 @@ public void TestPowerShellAdapter() } ``` +### Shell Adapter + +Shell Adapter leverages bash in Windows Subsystem for Linux (WSL) to run shell scripts. Users can bind their adapter interfaces to a shell adapter by defining them as "shell" in the PTF configuration files. The implementation will run the corresponding shell script file when one of the adapter's methods is called. + +__Benefits__ + +Shell adapters are easy to use. For example, they are suitable for service setup/shutdown jobs. Users can write a Stop.sh to login a Linux machine via SSH and stop a service. + +__Limitation__ + +1. WSL must be running on Windows 10 version 1607 (the Anniversary update) or later. +2. Do not encode the shell script using UTF-8 with Byte Order Mark. + +__Usage__ + +Configure `` section of the ptfconfig file: + +``` + +``` + +Subsequently, users can invoke `IMyScriptAdapter.AMethod(parameters)`. PTF will look up a script named `AMethod.sh` in the scriptdir directory and execute it with the parameters. + +__Parameters__ + +PTF invokes a shell script using the following parameters: + + __Parameter name__ | __Value__ + -------------------|---------- +$1 |First input parameter. +$2 |Second input parameter. +... | + +__Return values__ + +To pass a return value back to PTF, print the return value at the last line of stdout. + +To pass an exception message back to PTF, print the message to stderr and exit the script with a non-zero exit code. + +``` +echo "" >&2 +exit 1 +``` + +Provide the `ToString()` method and the `Parse()` method in a custom type to pass custom type values as parameters to script adapter, e.g.: + +``` +static public String ToString() +static public CustomType.Parse(String str) +``` + +__Exception__ + +If the shell script execution fails, PTF will raise an `InvalidOperationException`. + +If the shell script file is not found, PTF will raise an `AssertInconclusiveException`. + +__PTF Properties__ + +PTF properties are provided to shell adapters by environment variables with PTFProp_ as prefix, and dot in property name replaced by underline(_). +For example, if a user has the following configuration in the PTFconfig + +``` + + + + +``` + +To initiate an SSH connection to the server. You can use the following command in shell script. + +``` +ssh -p $PTFProp_SSH_Port $PTFProp_ServerName +``` + ## Extensive Logging Support PTF provides problem-oriented logging capabilities (begin/end test group, verification pass/failure, requirement capture, debugging). Most of the logging is done automatically so that the test suite developer does not have to write them manually. @@ -1084,38 +1052,27 @@ namespace HelloWorld ### Create script file for script adapter -Create script file Setup.cmd. +Create script file Setup.sh. ``` echo Hello, setting up -echo %CMDcmdLine% - -REM Which command is executing this script (e.g. Setup) -echo arg0: %0 -REM Return type for this script (e.g. Int32) -echo arg1: %1 -REM Types for arguments. First arg is %4 -echo arg2: %2 -REM MethodHelp instructions -- usually good for printing. -echo arg3: %3 -REM First actual argument to the method represented by this script. -echo arg4: %4 - -REM This will show PTFConfig properties as ptfprop....=value -set >con +# First argument of the method +echo arg1: $1 +# Second argument of the method +echo arg2: $2 -echo Method: %0 Help Text: %3 >con -set ptfprop +# Do something... -set ERRORLEVEL=0 -echo PtfAdReturn="%ERRORLEVEL%" +# Set exit code as 0 to indicate success. +# Exit with a non-zero code to indicate failure. +exit 0 ``` Enable the deployment of the script file. * Open Testsettings1.testsettings file from the Solution Explorer. -* Add Setup.cmd file from the Deployment page. (You need to choose "All files" for the file type in the File dialog.) +* Add Setup.sh file from the Deployment page. (You need to choose "All files" for the file type in the File dialog.) ### Use the adapters in test case diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs index 230799b..01e1ddf 100644 --- a/src/SharedAssemblyInfo.cs +++ b/src/SharedAssemblyInfo.cs @@ -5,4 +5,4 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("Protocol Test Framework")] -[assembly: AssemblyVersion("1.0.6000.0")] +[assembly: AssemblyVersion("1.0.6500.0")] diff --git a/src/deploy/Installer/PTFProduct.wxs b/src/deploy/Installer/PTFProduct.wxs index 56a1169..c3d84f3 100644 --- a/src/deploy/Installer/PTFProduct.wxs +++ b/src/deploy/Installer/PTFProduct.wxs @@ -38,25 +38,75 @@ - - - = "#461310")]]> - - - NOT NEWER_VERSION_DETECTED OR Installed - - - - - 0 - - - < $(var.CheckVSPath))]]> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -69,7 +119,7 @@ - + @@ -115,13 +165,13 @@ ConfigurableDirectory="ROOT_DIR"> - + - - + + @@ -146,52 +196,52 @@ - - - - - - - - - - - - - - - - - 1 - - 1 - - 1 - LicenseAccepted = "1" - - 1 - 1 - 1 - - Installed - NOT Installed - - - - - 1 - 1 - NOT Installed - WixUI_InstallMode = "Change" - "Change")]]> - - 1 - - 1 - 1 - 1 - 1 - + + + + + + + + + + + + + + + + + 1 + + 1 + + 1 + LicenseAccepted = "1" + + 1 + 1 + 1 + + Installed + NOT Installed + + + + + 1 + 1 + NOT Installed + WixUI_InstallMode = "Change" + "Change")]]> + + 1 + + 1 + 1 + 1 + 1 + diff --git a/src/deploy/Installer/ProtocolTestFramework.wxl b/src/deploy/Installer/ProtocolTestFramework.wxl index a205ac5..6069278 100644 --- a/src/deploy/Installer/ProtocolTestFramework.wxl +++ b/src/deploy/Installer/ProtocolTestFramework.wxl @@ -2,8 +2,6 @@ The Setup Wizard will install [ProductName] (version [ProductVersion]) on your computer. Click Next to continue or Cancel to exit the Setup Wizard. The Setup Wizard allows you to change the way [ProductName] (version [ProductVersion]) features are installed on your computer or to remove it from your computer. Click Next to continue or Cancel to exit the Setup Wizard. - - Warning: Protocol Test Framework has dependencies on Visual Studio 2017, but Visual Studio is not installed on this machine. - PTF still can be installed but may not function properly. + Warning: The following software are not installed on this machine, the test suite still can be installed but may not function properly. [DOTNET471_NOT_INSTALLED_WARNING_TEXT][VSTEST_AGENT_NOT_INSTALLED_WARNING_TEXT][SE_NOT_INSTALLED_WARNING_TEXT]PTF still can be installed but may not function properly. \ No newline at end of file diff --git a/src/deploy/Installer/ProtocolTestFrameworkSDK.wxs b/src/deploy/Installer/ProtocolTestFrameworkSDK.wxs index 2d179a8..3a89e61 100644 --- a/src/deploy/Installer/ProtocolTestFrameworkSDK.wxs +++ b/src/deploy/Installer/ProtocolTestFrameworkSDK.wxs @@ -19,34 +19,33 @@ xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> - - - - - + - + + + + - VS2017_ROOT_FOLDER + VSTEST2017 - VS2017_ROOT_FOLDER + VSTEST2017 - + @@ -98,12 +97,12 @@ - - + + - - + + @@ -165,7 +164,7 @@ Source="$(var.SRCDIR_VS)\xmldocs\Microsoft.Protocols.TestTools.VSTS.xml" /> - + @@ -231,10 +230,10 @@ - + - + - + - + - VS2017_ROOT_FOLDER + VS2017SEARCH - + parametersDictionary; + private string testResultsDirPath; + /// /// Initializes the Test Logger. /// /// Events which can be registered for. - /// Test Run Directory - public void Initialize(TestLoggerEvents events, string testRunDirectory) + /// Test Results Directory + public void Initialize(TestLoggerEvents events, string testResultsDirPath) { + if (events == null) + { + throw new ArgumentNullException(nameof(events)); + } + + if (string.IsNullOrEmpty(testResultsDirPath)) + { + throw new ArgumentNullException(nameof(testResultsDirPath)); + } + // Register for the events. events.TestRunMessage += TestMessageHandler; events.TestResult += TestResultHandler; events.TestRunComplete += TestRunCompleteHandler; + + this.testResultsDirPath = testResultsDirPath; CreateReportFolder(); } + /// + /// Initializes the Test Logger. + /// + /// Events which can be registered for. + /// Collection of parameters + public void Initialize(TestLoggerEvents events, Dictionary parameters) + { + if (parameters == null) + { + throw new ArgumentNullException(nameof(parameters)); + } + + if (parameters.Count == 0) + { + throw new ArgumentException("No default parameters added", nameof(parameters)); + } + + this.parametersDictionary = parameters; + this.Initialize(events, this.parametersDictionary[DefaultLoggerParameterNames.TestRunDirectory]); + } + #region Implement three events /// /// Called when a test message is received. @@ -154,9 +191,22 @@ private void TestRunCompleteHandler(object sender, TestRunCompleteEventArgs e) /// private void CreateReportFolder() { - reportFolderPath = Path.Combine( - Path.Combine(Directory.GetCurrentDirectory(), rootFolderName), - DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); + if (this.parametersDictionary != null) + { + var isoutputFolderParameterExists = this.parametersDictionary.TryGetValue(outputFolderKey, out string outputFolderValue); + if (isoutputFolderParameterExists && !string.IsNullOrWhiteSpace(outputFolderValue)) + { + reportFolderPath = Path.Combine(testResultsDirPath, outputFolderValue); + } + else + { + reportFolderPath = Path.Combine(testResultsDirPath, DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); + } + } + else + { + reportFolderPath = Path.Combine(testResultsDirPath, DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")); + } Directory.CreateDirectory(reportFolderPath); @@ -191,19 +241,13 @@ private string ConstructDetailObj(string txtFileName) } /// - /// Constructs listObj and summaryObj used in functions.js + /// Constructs listObj used in functions.js /// private string ConstructListAndSummaryObj(TestRunCompleteEventArgs e) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); sb.AppendLine("var listObj = " + txtToJSON.TestCasesString(txtResultFolderPath, captureFolderPath) + ";"); - sb.Append("var summaryObj = " - + txtToJSON.SummaryTable(e.TestRunStatistics.ExecutedTests, - e.TestRunStatistics[TestOutcome.Passed], - e.TestRunStatistics[TestOutcome.Failed], - testRunStartTime, - testRunEndTime) + ";"); // Clean the temp file File.Delete(txtToJSON.CaseCategoryFile); diff --git a/src/htmltestlogger/HtmlTestLogger.csproj b/src/htmltestlogger/HtmlTestLogger.csproj index 8639480..46e635e 100644 --- a/src/htmltestlogger/HtmlTestLogger.csproj +++ b/src/htmltestlogger/HtmlTestLogger.csproj @@ -31,7 +31,7 @@ - $(MSBuildExtensionsPath)\..\Common7\IDE\CommonExtensions\Microsoft\TestWindow\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll + $(MSBuildExtensionsPath)\..\Common7\IDE\Extensions\TestPlatform\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll diff --git a/src/htmltestlogger/Resources/functions.js b/src/htmltestlogger/Resources/functions.js index 223895d..a7ee197 100644 --- a/src/htmltestlogger/Resources/functions.js +++ b/src/htmltestlogger/Resources/functions.js @@ -298,17 +298,20 @@ function FindIndexofClass(cls) // Show summary of the test run function ShowSummary() { + var totalCount = listObj.TestCases.length; + var passedCount = listObj.TestCases.filter(function (tc) { return tc.Result === "Passed" }).length; + var failedCount = listObj.TestCases.filter(function (tc) { return tc.Result === "Failed" }).length; + var inconclusiveCount = listObj.TestCases.filter(function (tc) { return tc.Result === "Inconclusive" }).length; + var passRate = (totalCount === 0 ? 0 : passedCount / totalCount).toFixed(2); + var tbody = document.getElementById("tableid"); var newrow = tbody.insertRow(-1); - CreateText(newrow.insertCell(0), summaryObj.TotalCount); - CreateText(newrow.insertCell(1), summaryObj.PassedCount); - CreateText(newrow.insertCell(2), summaryObj.FailedCount); - CreateText(newrow.insertCell(3), summaryObj.InconclusiveCount); - CreateText(newrow.insertCell(4), summaryObj.PassRate + "%"); - var pt = document.getElementById("time"); - pt.innerHTML = "Start Time: " + summaryObj.StartTime + "
End Time:  " + summaryObj.EndTime - + "
Duration:   " + summaryObj.Duration; - pt.style.fontFamily = "Tahoma"; + + CreateText(newrow.insertCell(0), totalCount); + CreateText(newrow.insertCell(1), passedCount); + CreateText(newrow.insertCell(2), failedCount); + CreateText(newrow.insertCell(3), inconclusiveCount); + CreateText(newrow.insertCell(4), passRate + "%"); } // Used by [casename].html diff --git a/src/htmltestlogger/Resources/index.html b/src/htmltestlogger/Resources/index.html index 44cc767..b248c76 100644 --- a/src/htmltestlogger/Resources/index.html +++ b/src/htmltestlogger/Resources/index.html @@ -137,7 +137,7 @@
     Group By @@ -146,7 +146,6 @@
     Group By