From 23fab961b3e361befe6a39be36b7d89059214fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 1 Apr 2021 10:55:58 -0700 Subject: [PATCH 1/5] Create controller project. --- Simulation.sln | 22 ++++++++++++ src/Qir/Controller/Controller.cs | 21 +++++++++++ src/Qir/Controller/Program.cs | 47 +++++++++++++++++++++++++ src/Qir/Controller/QirController.csproj | 12 +++++++ 4 files changed, 102 insertions(+) create mode 100644 src/Qir/Controller/Controller.cs create mode 100644 src/Qir/Controller/Program.cs create mode 100644 src/Qir/Controller/QirController.csproj diff --git a/Simulation.sln b/Simulation.sln index da0f6964563..4ba93680295 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -103,6 +103,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qir-gen", "src\Qir\Runtime\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tracer-qir", "src\Qir\Runtime\test\QIR-tracer\qsharp\tracer-qir.csproj", "{5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "controller", "controller", "{A25E062D-C685-48DE-99D1-B5BC0DF73F89}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QirController", "src\Qir\Controller\QirController.csproj", "{55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -739,6 +743,22 @@ Global {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|x64.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Debug|x64.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|Any CPU.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|x64.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.Release|x64.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -787,6 +807,8 @@ Global {9DF6FEB7-3111-4244-B4EE-A69C64043967} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} {241693D7-4AA6-47C9-9F27-78F2A1EE0904} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} {5917D4C5-0CD2-4BD1-A859-19B9B97FF8A7} = {3FFDEA49-C6E8-45BB-BCA5-BBC5378F704F} + {A25E062D-C685-48DE-99D1-B5BC0DF73F89} = {C637C9DF-14AA-48CB-95F3-73CE0AC5F9B1} + {55AC2357-5C70-4CAC-9A1F-4146E2D81CE3} = {A25E062D-C685-48DE-99D1-B5BC0DF73F89} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {929C0464-86D8-4F70-8835-0A5EAF930821} diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs new file mode 100644 index 00000000000..f6d7e8659e8 --- /dev/null +++ b/src/Qir/Controller/Controller.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; + +namespace Microsoft.Quantum.Qir +{ + internal static class Controller + { + internal static void Execute( + FileInfo input, + FileInfo output, + FileInfo error) + { + Console.WriteLine(input.FullName); + Console.WriteLine(output.FullName); + Console.WriteLine(error.FullName); + } + } +} diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs new file mode 100644 index 00000000000..7151d891312 --- /dev/null +++ b/src/Qir/Controller/Program.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.CommandLine; +using System.CommandLine.Invocation; +using System.IO; + +namespace Microsoft.Quantum.Qir +{ + class Program + { + static void Main(string[] args) + { + var rootCommand = new RootCommand( + description: "Builds and runs QIR executable."); + + // Create and add options to the root command. + var inputOption = new Option( + aliases: new string[] { "--input", "-i" }) + { + Description = "Path to the file that contains the input.", + Required = true + }; + + rootCommand.AddOption(inputOption); + var outputOption = new Option( + aliases: new string[] { "--output", "-o" }) + { + Description = "Path to the file to which the output will be written.", + Required = true + }; + + rootCommand.AddOption(outputOption); + var errorOption = new Option( + aliases: new string[] { "--error", "-e" }) + { + Description = "Path to the file to which errors will be logged.", + Required = true + }; + + rootCommand.AddOption(errorOption); + // Bind to a handler and invoke. + rootCommand.Handler = CommandHandler.Create(Controller.Execute); + rootCommand.Invoke(args); + } + } +} diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj new file mode 100644 index 00000000000..91fd86cde4b --- /dev/null +++ b/src/Qir/Controller/QirController.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + From c0ceb020439a21a6c7e8f1e9ab4318671bc80671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 1 Apr 2021 19:44:47 -0700 Subject: [PATCH 2/5] Add script to test the QIR controller. --- src/Qir/Controller/Controller.cs | 13 +++++-- src/Qir/Controller/Program.cs | 17 ++++---- src/Qir/Controller/QirController.csproj | 2 +- src/Qir/Controller/test-cases/01.err | 1 + src/Qir/Controller/test-cases/01.in | 1 + src/Qir/Controller/test-cases/01.out | 1 + src/Qir/Controller/test-controller.ps1 | 52 +++++++++++++++++++++++++ 7 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 src/Qir/Controller/test-cases/01.err create mode 100644 src/Qir/Controller/test-cases/01.in create mode 100644 src/Qir/Controller/test-cases/01.out create mode 100644 src/Qir/Controller/test-controller.ps1 diff --git a/src/Qir/Controller/Controller.cs b/src/Qir/Controller/Controller.cs index f6d7e8659e8..0f613d5fc0c 100644 --- a/src/Qir/Controller/Controller.cs +++ b/src/Qir/Controller/Controller.cs @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.IO; +using System.Text; namespace Microsoft.Quantum.Qir { @@ -13,9 +13,14 @@ internal static void Execute( FileInfo output, FileInfo error) { - Console.WriteLine(input.FullName); - Console.WriteLine(output.FullName); - Console.WriteLine(error.FullName); + var outputFileStream = output.Exists ? output.OpenWrite() : output.Create(); + outputFileStream.Write(new UTF8Encoding().GetBytes("output")); + outputFileStream.Flush(); + outputFileStream.Close(); + var errorFileStream = error.Exists ? error.OpenWrite() : error.Create(); + errorFileStream.Write(new UTF8Encoding().GetBytes("error")); + errorFileStream.Flush(); + errorFileStream.Close(); } } } diff --git a/src/Qir/Controller/Program.cs b/src/Qir/Controller/Program.cs index 7151d891312..e7fec1e6fd0 100644 --- a/src/Qir/Controller/Program.cs +++ b/src/Qir/Controller/Program.cs @@ -16,31 +16,32 @@ static void Main(string[] args) // Create and add options to the root command. var inputOption = new Option( - aliases: new string[] { "--input", "-i" }) + aliases: new string[] { "--input"}) { Description = "Path to the file that contains the input.", - Required = true + IsRequired = true }; - + rootCommand.AddOption(inputOption); var outputOption = new Option( - aliases: new string[] { "--output", "-o" }) + aliases: new string[] { "--output"}) { Description = "Path to the file to which the output will be written.", - Required = true + IsRequired = true }; rootCommand.AddOption(outputOption); var errorOption = new Option( - aliases: new string[] { "--error", "-e" }) + aliases: new string[] { "--error",}) { Description = "Path to the file to which errors will be logged.", - Required = true + IsRequired = true }; rootCommand.AddOption(errorOption); + // Bind to a handler and invoke. - rootCommand.Handler = CommandHandler.Create(Controller.Execute); + rootCommand.Handler = CommandHandler.Create((input, output, error) => Controller.Execute(input, output, error)); rootCommand.Invoke(args); } } diff --git a/src/Qir/Controller/QirController.csproj b/src/Qir/Controller/QirController.csproj index 91fd86cde4b..0c21b5914f9 100644 --- a/src/Qir/Controller/QirController.csproj +++ b/src/Qir/Controller/QirController.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/Qir/Controller/test-cases/01.err b/src/Qir/Controller/test-cases/01.err new file mode 100644 index 00000000000..760589cb5d6 --- /dev/null +++ b/src/Qir/Controller/test-cases/01.err @@ -0,0 +1 @@ +error \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/01.in b/src/Qir/Controller/test-cases/01.in new file mode 100644 index 00000000000..760589cb5d6 --- /dev/null +++ b/src/Qir/Controller/test-cases/01.in @@ -0,0 +1 @@ +error \ No newline at end of file diff --git a/src/Qir/Controller/test-cases/01.out b/src/Qir/Controller/test-cases/01.out new file mode 100644 index 00000000000..6caf68aff42 --- /dev/null +++ b/src/Qir/Controller/test-cases/01.out @@ -0,0 +1 @@ +output \ No newline at end of file diff --git a/src/Qir/Controller/test-controller.ps1 b/src/Qir/Controller/test-controller.ps1 new file mode 100644 index 00000000000..c9afa203646 --- /dev/null +++ b/src/Qir/Controller/test-controller.ps1 @@ -0,0 +1,52 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +$all_ok = $True + +Write-Host "##[info]Test QIR Controller" + +$controllerProject = (Join-Path $PSScriptRoot QirController.csproj) +$testCasesFolder = (Join-Path $PSScriptRoot "test-cases") +$testArtifactsFolder = (Join-Path $PSScriptRoot "test-artifacts") +if (!(Test-Path $testArtifactsFolder -PathType Container)) { + New-Item -ItemType Directory -Force -Path $testArtifactsFolder +} +Get-ChildItem -Path $testArtifactsFolder | Remove-Item -Force + +# Go through each input file in the test cases folder. +Get-ChildItem $testCasesFolder -Filter *.in | +Foreach-Object { + # Get the paths to the output and error files to pass to the QIR controller. + $outputFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".out")) + $errorFile = (Join-Path $testArtifactsFolder ($_.BaseName + ".err")) + dotnet run --project $controllerProject -- --input $_.FullName --output $outputFile --error $errorFile + + # Compare the expected content of the output and error files vs the actual content. + $expectedOutputFile = (Join-Path $testCasesFolder ($_.BaseName + ".out")) + $expectedOutput = Get-Content -Path $expectedOutputFile -Raw + $actualOutput = Get-Content -Path $outputFile -Raw + if (-not ($expectedOutput -ceq $actualOutput)) { + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Expected output:" + Write-Host $expectedOutput + Write-Host "##[info]Actual output:" + Write-Host $actualOutput + $script:all_ok = $False + break + } + + $expectedErrorFile = (Join-Path $testCasesFolder ($_.BaseName + ".err")) + $expectedError = Get-Content -Path $expectedErrorFile -Raw + $actualError = Get-Content -Path $errorFile -Raw + if (-not ($expectedError -ceq $actualError)) { + Write-Host "##vso[task.logissue type=error;]Failed QIR Controller test case: $($_.BaseName)" + Write-Host "##[info]Expected error:" + Write-Host $expectedError + Write-Host "##[info]Actual error:" + Write-Host $actualError + $script:all_ok = $False + break + } + + Write-Host "##[info]Test case '$($_.BaseName)' passed" +} From a77f7a2d3a77c4f1235c445ae8b25df4d50c4065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 1 Apr 2021 19:59:19 -0700 Subject: [PATCH 3/5] Test QIR controller as part of the build. --- build/test.ps1 | 6 ++++++ src/Qir/Controller/test-controller.ps1 | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/build/test.ps1 b/build/test.ps1 index b80d5ab936f..55def2d603f 100644 --- a/build/test.ps1 +++ b/build/test.ps1 @@ -43,6 +43,12 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false") { if ($LastExitCode -ne 0) { $script:all_ok = $False } + + $qirController = (Join-Path $PSScriptRoot "../src/Qir/Controller") + & "$qirController/test-controller.ps1" + if ($LastExitCode -ne 0) { + $script:all_ok = $False + } } else { Write-Host "Skipping test of qir runtime because ENABLE_QIRRUNTIME variable is set to: $Env:ENABLE_QIRRUNTIME ` and ENABLE_NATIVE variable is set to: $Env:ENABLE_NATIVE." diff --git a/src/Qir/Controller/test-controller.ps1 b/src/Qir/Controller/test-controller.ps1 index c9afa203646..876626b703a 100644 --- a/src/Qir/Controller/test-controller.ps1 +++ b/src/Qir/Controller/test-controller.ps1 @@ -50,3 +50,7 @@ Foreach-Object { Write-Host "##[info]Test case '$($_.BaseName)' passed" } + +if (-not $all_ok) { + throw "At least one project failed testing. Check the logs." +} From fb05e817ec9ba36537d9b4a40e53c6bae84f2a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Thu, 1 Apr 2021 20:01:40 -0700 Subject: [PATCH 4/5] Renamed test controller script. --- build/test.ps1 | 2 +- .../Controller/{test-controller.ps1 => test-qir-controller.ps1} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Qir/Controller/{test-controller.ps1 => test-qir-controller.ps1} (100%) diff --git a/build/test.ps1 b/build/test.ps1 index 55def2d603f..c4d9e732bf3 100644 --- a/build/test.ps1 +++ b/build/test.ps1 @@ -45,7 +45,7 @@ if ($Env:ENABLE_QIRRUNTIME -ne "false") { } $qirController = (Join-Path $PSScriptRoot "../src/Qir/Controller") - & "$qirController/test-controller.ps1" + & "$qirController/test-qir-controller.ps1" if ($LastExitCode -ne 0) { $script:all_ok = $False } diff --git a/src/Qir/Controller/test-controller.ps1 b/src/Qir/Controller/test-qir-controller.ps1 similarity index 100% rename from src/Qir/Controller/test-controller.ps1 rename to src/Qir/Controller/test-qir-controller.ps1 From e09e97fab6853105513bc0602a054cfec6ab5e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Zaragoza=20Cort=C3=A9s?= Date: Fri, 2 Apr 2021 12:12:51 -0700 Subject: [PATCH 5/5] Update test-case file. --- src/Qir/Controller/test-cases/01.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Qir/Controller/test-cases/01.in b/src/Qir/Controller/test-cases/01.in index 760589cb5d6..770eab4480b 100644 --- a/src/Qir/Controller/test-cases/01.in +++ b/src/Qir/Controller/test-cases/01.in @@ -1 +1 @@ -error \ No newline at end of file +input \ No newline at end of file