diff --git a/.travis.yml b/.travis.yml index 0dad93ea..4400307a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ sudo: required -dist: trusty +dist: xenial os: - linux @@ -7,7 +7,8 @@ os: # - osx mono: none -dotnet: 2.2.100-preview3-009430 +dotnet: 2.2 +# was dotnet: 2.2.100-preview3-009430 # safelist branches: @@ -37,5 +38,4 @@ script: - dotnet build src/Microsoft.SqlTools.ServiceLayer - dotnet test test/Microsoft.SqlTools.ServiceLayer.UnitTests - dotnet build src/Microsoft.SqlTools.CoreServices - - dotnet test test/Microsoft.SqlTools.Hosting.UnitTests - + - dotnet test test/Microsoft.SqlTools.Hosting.UnitTests \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index a2a26a86..fa51456a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,4 +30,4 @@ after_test: - cmd: packages\coveralls.io.1.3.4\tools\coveralls.net.exe --opencover coverage.xml cache: -- '%USERPROFILE%\.nuget\packages' +- '%USERPROFILE%\.nuget\packages' \ No newline at end of file diff --git a/sqltoolsservice.sln b/sqltoolsservice.sln index c796919a..4943615d 100644 --- a/sqltoolsservice.sln +++ b/sqltoolsservice.sln @@ -93,6 +93,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ManagedBatchParser", "src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj", "{3F82F298-700A-48DF-8A69-D048DFBA782C}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ManagedBatchParser.IntegrationTests", "test\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj", "{D3696EFA-FB1E-4848-A726-FF7B168AFB96}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -220,6 +222,12 @@ Global {3F82F298-700A-48DF-8A69-D048DFBA782C}.Integration|Any CPU.Build.0 = Debug|Any CPU {3F82F298-700A-48DF-8A69-D048DFBA782C}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F82F298-700A-48DF-8A69-D048DFBA782C}.Release|Any CPU.Build.0 = Release|Any CPU + {D3696EFA-FB1E-4848-A726-FF7B168AFB96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3696EFA-FB1E-4848-A726-FF7B168AFB96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3696EFA-FB1E-4848-A726-FF7B168AFB96}.Integration|Any CPU.ActiveCfg = Debug|Any CPU + {D3696EFA-FB1E-4848-A726-FF7B168AFB96}.Integration|Any CPU.Build.0 = Debug|Any CPU + {D3696EFA-FB1E-4848-A726-FF7B168AFB96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3696EFA-FB1E-4848-A726-FF7B168AFB96}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -247,6 +255,7 @@ Global {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {EF02F89F-417E-4A40-B7E6-B102EE2DF24D} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {3F82F298-700A-48DF-8A69-D048DFBA782C} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {D3696EFA-FB1E-4848-A726-FF7B168AFB96} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8} diff --git a/src/Microsoft.SqlTools.ManagedBatchParser/BatchParser/Parser.cs b/src/Microsoft.SqlTools.ManagedBatchParser/BatchParser/Parser.cs index f3e09dc9..e1a87ed4 100644 --- a/src/Microsoft.SqlTools.ManagedBatchParser/BatchParser/Parser.cs +++ b/src/Microsoft.SqlTools.ManagedBatchParser/BatchParser/Parser.cs @@ -238,6 +238,14 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser if (LookaheadTokenType == LexerTokenType.Text) { string text = ResolveVariables(LookaheadToken, 0, null); + // This statement originally placed after the for loop, But it moved here, the reason is: + // When passing the long number like 999999999999999999999999, instead of throwing error + // it accept and iterate the loop + bool result = Int32.TryParse(text, out repeatCount); + if (result == false) + { + RaiseError(ErrorCode.InvalidNumber); + } for (int i = 0; i < text.Length; i++) { if (Char.IsDigit(text[i]) == false) @@ -245,11 +253,6 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser RaiseError(ErrorCode.InvalidNumber); } } - bool result = Int32.TryParse(text, out repeatCount); - if (result == false) - { - RaiseError(ErrorCode.InvalidNumber); - } Accept(LexerTokenType.Text); AcceptWhitespaceOrComment(); } diff --git a/src/Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj b/src/Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj index b3239405..a28e0c10 100644 --- a/src/Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj +++ b/src/Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj @@ -4,6 +4,7 @@ netstandard2.0 false false + portable diff --git a/src/Microsoft.SqlTools.ManagedBatchParser/Properties/AssemblyInfo.cs b/src/Microsoft.SqlTools.ManagedBatchParser/Properties/AssemblyInfo.cs index 4cf13ee7..40d80bb0 100644 --- a/src/Microsoft.SqlTools.ManagedBatchParser/Properties/AssemblyInfo.cs +++ b/src/Microsoft.SqlTools.ManagedBatchParser/Properties/AssemblyInfo.cs @@ -40,4 +40,4 @@ using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.IntegrationTests")] [assembly: InternalsVisibleTo("Microsoft.SqlTools.ServiceLayer.Test.Common")] [assembly: InternalsVisibleTo("MicrosoftSqlToolsServiceLayer")] -[assembly: InternalsVisibleTo("Microsoft.SqlTools.ManagedBatchParser.UnitTests")] \ No newline at end of file +[assembly: InternalsVisibleTo("Microsoft.SqlTools.ManagedBatchParser.IntegrationTests")] \ No newline at end of file diff --git a/test/CodeCoverage/codecoverage.bat b/test/CodeCoverage/codecoverage.bat index ea57a404..3e696fa3 100644 --- a/test/CodeCoverage/codecoverage.bat +++ b/test/CodeCoverage/codecoverage.bat @@ -11,6 +11,7 @@ REM Setup repo base path REM backup current CSPROJ files COPY /Y %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj.BAK +COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj.BAK @@ -20,6 +21,7 @@ REM switch PDB type to Full since that is required by OpenCover for now REM we should remove this step on OpenCover supports portable PDB cscript /nologo ReplaceText.vbs %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj portable full cscript /nologo ReplaceText.vbs %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj portable full +cscript /nologo ReplaceText.vbs %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj portable full cscript /nologo ReplaceText.vbs %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj portable full cscript /nologo ReplaceText.vbs %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj portable full cscript /nologo ReplaceText.vbs %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj portable full @@ -29,7 +31,9 @@ REM rebuild the SqlToolsService project dotnet restore %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj dotnet build %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj %DOTNETCONFIG% dotnet restore %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj -dotnet build %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj %DOTNETCONFIG% +dotnet build %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj %DOTNETCONFIG% +dotnet restore %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj +dotnet build %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj %DOTNETCONFIG% -r win7-x64 dotnet restore %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj dotnet build %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj %DOTNETCONFIG% -r win7-x64 dotnet restore %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj @@ -50,6 +54,8 @@ dotnet restore %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.IntegrationTests\ dotnet build %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.IntegrationTests\Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj %DOTNETCONFIG% dotnet restore %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.csproj dotnet build %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.csproj %DOTNETCONFIG% +dotnet restore %REPOROOT%\test\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj +dotnet build %REPOROOT%\test\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj %DOTNETCONFIG% SET TEST_SERVER=localhost SET SQLTOOLSSERVICE_EXE=%REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\bin\Integration\netcoreapp2.2\win7-x64\MicrosoftSqlToolsServiceLayer.exe @@ -61,23 +67,27 @@ REM dotnet.exe test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.T SET SERVICECODECOVERAGE=FALSE -%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[Microsoft.SqlTools.ServiceLayer.*Test*] -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\bin\Debug\netcoreapp2.2 +%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[Microsoft.SqlTools.ServiceLayer.*Test*]* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\bin\Debug\netcoreapp2.2 -%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.UnitTests\Microsoft.SqlTools.ServiceLayer.UnitTests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.*Test*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.UnitTests\bin\Debug\netcoreapp2.2 +%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.UnitTests\Microsoft.SqlTools.ServiceLayer.UnitTests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[Microsoft.SqlTools.ServiceLayer.*Test*]* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.UnitTests\bin\Debug\netcoreapp2.2 -%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.IntegrationTests\Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* [Microsoft.SqlTools.*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[Microsoft.SqlTools.ServiceLayer.*Test*]* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.IntegrationTests\bin\Debug\netcoreapp2.2 +%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.IntegrationTests\Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[Microsoft.SqlTools.ServiceLayer.*Test*]* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ServiceLayer.IntegrationTests\bin\Debug\netcoreapp2.2 + +%CODECOVERAGETOOL% -mergeoutput -register:user -target:dotnet.exe -targetargs:"test %REPOROOT%\test\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj %DOTNETCONFIG%" -oldstyle -filter:"+[Microsoft.SqlTools.*]* +[MicrosoftSqlToolsServiceLayer*]* +[MicrosoftSqlToolsCredentials*]* -[xunit*]* -[Microsoft.SqlTools.ServiceLayer.Test*]* -[Microsoft.SqlTools.ServiceLayer.*Test*]* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Agent.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.DisasterRecovery.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Profiler.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Admin.* -[MicrosoftSqlToolsServiceLayer]Microsoft.SqlTools.ServiceLayer.Management.*" -output:coverage.xml -hideskipped:All -searchdirs:%REPOROOT%\test\Microsoft.SqlTools.ManagedBatchParser.IntegrationTests\bin\Debug\netcoreapp2.2 REM Generate the report -"%WORKINGDIR%packages\OpenCoverToCoberturaConverter.0.2.4.0\tools\OpenCoverToCoberturaConverter.exe" -input:coverage.xml -output:outputCobertura.xml -sources:%REPOROOT%\src\Microsoft.SqlTools.ServiceLayer -"%WORKINGDIR%packages\ReportGenerator.2.4.5.0\tools\ReportGenerator.exe" "-reports:coverage.xml" "-targetdir:%WORKINGDIR%\reports" +"%WORKINGDIR%packages\OpenCoverToCoberturaConverter.0.2.4.0\tools\OpenCoverToCoberturaConverter.exe" -input:coverage.xml -output:outputCobertura.xml -sources:%REPOROOT%\src\Microsoft.SqlTools.ServiceLayer +"%WORKINGDIR%packages\ReportGenerator.2.4.5.0\tools\ReportGenerator.exe" "-reports:coverage.xml" "-targetdir:%WORKINGDIR%\reports" REM restore original project.json -COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj -DEL %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj DEL %REPOROOT%\src\Microsoft.SqlTools.Credentials\Microsoft.SqlTools.Credentials.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj DEL %REPOROOT%\src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj.BAK +COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj +DEL %REPOROOT%\src\Microsoft.SqlTools.ManagedBatchParser\Microsoft.SqlTools.ManagedBatchParser.csproj.BAK +COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj +DEL %REPOROOT%\src\Microsoft.SqlTools.ServiceLayer\Microsoft.SqlTools.ServiceLayer.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj DEL %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider\Microsoft.SqlTools.ResourceProvider.csproj.BAK COPY /Y %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj.BAK %REPOROOT%\src\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/App.config b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/App.config new file mode 100644 index 00000000..92035273 --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/App.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/AssemblyInfo.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/AssemblyInfo.cs new file mode 100644 index 00000000..8f639b84 --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Xunit; + +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserMockEventHandler.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserMockEventHandler.cs similarity index 99% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserMockEventHandler.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserMockEventHandler.cs index 0c10f725..5b30ddb6 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserMockEventHandler.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserMockEventHandler.cs @@ -43,10 +43,10 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser public void OnBatchResultSetFinished(object sender, EventArgs args) { } /// - /// fired when the batch recieved cancel request BEFORE it + /// fired when the batch recieved cancel request BEFORE it /// initiates cancel operation. Note that it is fired from a /// different thread then the one used to kick off execution /// public void OnBatchCancelling(object sender, EventArgs args) { } } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserSqlCmdTests.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserSqlCmdTests.cs similarity index 99% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserSqlCmdTests.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserSqlCmdTests.cs index 6bf8f75e..76073b9d 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserSqlCmdTests.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserSqlCmdTests.cs @@ -7,7 +7,6 @@ using System; using System.IO; using Microsoft.SqlTools.ServiceLayer.BatchParser; using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; -using Moq; using Xunit; namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser @@ -16,6 +15,7 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser { private BatchParserSqlCmd bpcmd; private PositionStruct testPOS; + public BatchParserSqlCmdTests() { bpcmd = new BatchParserSqlCmd(); @@ -85,7 +85,6 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser string outString = "out"; var result = bpcmd.Include(null, out textReader, out outString); Assert.Equal(result, BatchParserAction.Abort); - } [Fact] @@ -113,6 +112,5 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser var result = bpcmd.GetVariable(testPOS, "variable1"); Assert.Null(result); } - } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserTests.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserTests.cs new file mode 100644 index 00000000..ba3ba929 --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserTests.cs @@ -0,0 +1,557 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Data.SqlClient; +using System.Globalization; +using System.IO; +using System.Text; +using Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.TSQLExecutionEngine; +using Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.Utility; +using Microsoft.SqlTools.ServiceLayer.BatchParser; +using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Microsoft.SqlTools.ServiceLayer.Test.Common.Baselined; +using Xunit; + +namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser +{ + public class BatchParserTests : BaselinedTest + { + private bool testFailed = false; + private static ScriptExecutionResult executionResult = ScriptExecutionResult.All; + private const string CONNECTION_STRING = "Data Source=.;Initial Catalog=master;Integrated Security=True"; + + public BatchParserTests() + { + InitializeTest(); + } + + public void InitializeTest() + { + CategoryName = "BatchParser"; + this.TraceOutputDirectory = RunEnvironmentInfo.GetTraceOutputLocation(); + TestInitialize(); + } + + [Fact] + public void VerifyThrowOnUnresolvedVariable() + { + string script = "print '$(NotDefined)'"; + StringBuilder output = new StringBuilder(); + + TestCommandHandler handler = new TestCommandHandler(output); + IVariableResolver resolver = new TestVariableResolver(new StringBuilder()); + using (Parser p = new Parser( + handler, + resolver, + new StringReader(script), + "test")) + { + p.ThrowOnUnresolvedVariable = true; + handler.SetParser(p); + + Assert.Throws(() => p.Parse()); + } + } + + /// + /// Variable parameter in powershell: Specifies, as a string array, a sqlcmd scripting variable + /// for use in the sqlcmd script, and sets a value for the variable. + /// + [Fact] + public void VerifyVariableResolverUsingVaribleParameter() + { + string query = @" Invoke-Sqlcmd -Query ""SELECT `$(calcOne)"" -Variable ""calcOne = 10 + 20"" "; + + TestCommandHandler handler = new TestCommandHandler(new StringBuilder()); + IVariableResolver resolver = new TestVariableResolver(new StringBuilder()); + using (Parser p = new Parser( + handler, + resolver, + new StringReader(query), + "test")) + { + p.ThrowOnUnresolvedVariable = true; + handler.SetParser(p); + Assert.Throws(() => p.Parse()); + } + } + + // Verify the starting identifier of Both parameter and variable are same. + [Fact] + public void VerifyVariableResolverIsStartIdentifierChar() + { + // instead of using variable calcOne, I purposely used In-variable 0alcOne + string query = @" Invoke-Sqlcmd -Query ""SELECT `$(0alcOne)"" -Variable ""calcOne1 = 1"" "; + + TestCommandHandler handler = new TestCommandHandler(new StringBuilder()); + IVariableResolver resolver = new TestVariableResolver(new StringBuilder()); + using (Parser p = new Parser( + handler, + resolver, + new StringReader(query), + "test")) + { + p.ThrowOnUnresolvedVariable = true; + handler.SetParser(p); + Assert.Throws(() => p.Parse()); + } + } + + // Verify all the characters inside variable are valid Identifier. + [Fact] + public void VerifyVariableResolverIsIdentifierChar() + { + // instead of using variable calcOne, I purposely used In-variable 0alcOne + string query = @" Invoke-Sqlcmd -Query ""SELECT `$(ca@lcOne)"" -Variable ""calcOne = 1"" "; + + TestCommandHandler handler = new TestCommandHandler(new StringBuilder()); + IVariableResolver resolver = new TestVariableResolver(new StringBuilder()); + using (Parser p = new Parser( + handler, + resolver, + new StringReader(query), + "test")) + { + p.ThrowOnUnresolvedVariable = true; + handler.SetParser(p); + Assert.Throws(() => p.Parse()); + } + } + + + // Verify the execution by passing long value , Except a exception. + [Fact] + public void VerifyInvalidNumber() + { + string query = @" SELECT 1+1 + GO 999999999999999999999999999999999999999"; + + TestCommandHandler handler = new TestCommandHandler(new StringBuilder()); + IVariableResolver resolver = new TestVariableResolver(new StringBuilder()); + using (Parser p = new Parser( + handler, + resolver, + new StringReader(query), + "test")) + { + p.ThrowOnUnresolvedVariable = true; + handler.SetParser(p); + // This test will fail because we are passing invalid number. + // Exception will be raised from ParseGo() + Assert.Throws(() => p.Parse()); + } + } + + // Verify the Batch execution is executed successfully. + [Fact] + public void VerifyExecute() + { + Batch batch = new Batch(sqlText: "SELECT 1+1", isResultExpected: true, execTimeout: 15); + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + if (con.State.ToString().ToLower() == "open") + { + executionResult = batch.Execute(con, ShowPlanType.AllShowPlan); + } + } + Assert.Equal(ScriptExecutionResult.Success, executionResult); + } + + // Verify the exeception is handled by passing invalid keyword. + [Fact] + public void VerifyHandleExceptionMessage() + { + Batch batch = new Batch(sqlText: "SEL@ECT 1+1", isResultExpected: true, execTimeout: 15); + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + if (con.State.ToString().ToLower() == "open") + { + ScriptExecutionResult result = batch.Execute(con, ShowPlanType.AllShowPlan); + } + } + ScriptExecutionResult finalResult = (batch.RowsAffected > 0) ? ScriptExecutionResult.Success : ScriptExecutionResult.Failure; + + Assert.Equal(finalResult, ScriptExecutionResult.Failure); + } + + // Verify the passing query has valid text. + [Fact] + public void VerifyHasValidText() + { + Batch batch = new Batch(sqlText: null, isResultExpected: true, execTimeout: 15); + ScriptExecutionResult finalResult = ScriptExecutionResult.All; + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + if (con.State.ToString().ToLower() == "open") + { + ScriptExecutionResult result = batch.Execute(con, ShowPlanType.AllShowPlan); + } + } + finalResult = (batch.RowsAffected > 0) ? ScriptExecutionResult.Success : ScriptExecutionResult.Failure; + + Assert.Equal(finalResult, ScriptExecutionResult.Failure); + } + + // Verify the cancel functionality is working fine. + [Fact] + public void VerifyCancel() + { + ScriptExecutionResult result = ScriptExecutionResult.All; + Batch batch = new Batch(sqlText: "SELECT 1+1", isResultExpected: true, execTimeout: 15); + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + if (con.State.ToString().ToLower() == "open") + { + batch.Cancel(); + result = batch.Execute(con, ShowPlanType.AllShowPlan); + } + } + Assert.Equal(result, ScriptExecutionResult.Cancel); + } + + // verify weather lexer can consume token for SqlCmd variable + [Fact] + public void VerifyLexerSetState() + { + try + { + + string query = ":SETVAR a 10"; + var inputStream = GenerateStreamFromString(query); + using (Lexer lexer = new Lexer(new StreamReader(inputStream), "Test.sql")) + { + lexer.ConsumeToken(); + } + executionResult = ScriptExecutionResult.Success; + } + catch (Exception ex) + { + + executionResult = ScriptExecutionResult.Failure; + + } + // we doesn't expect any exception or testCase failures + Assert.Equal(ScriptExecutionResult.Success, executionResult); + + } + + // Verify the custom exception functionality by raising user defined error. + [Fact] + public void VerifyCustomBatchParserException() + { + string message = "This is userDefined Error"; + + Token token = new Token(LexerTokenType.Text, new PositionStruct(), new PositionStruct(), message, "test"); + + BatchParserException batchParserException = new BatchParserException(ErrorCode.VariableNotDefined, token, message); + try + { + throw new BatchParserException(ErrorCode.UnrecognizedToken, token, "test"); + } + catch (Exception ex) + { + Assert.Equal(batchParserException.ErrorCode.ToString(), ErrorCode.VariableNotDefined.ToString()); + Assert.Equal(message, batchParserException.Text); + Assert.Equal(LexerTokenType.Text.ToString(), batchParserException.TokenType.ToString()); + Assert.IsType(ex); + } + } + + // Verify whether the executionEngine execute script + [Fact] + public void VerifyExecuteScript() + { + using (ExecutionEngine executionEngine = new ExecutionEngine()) + { + string query = @"SELECT 1+2 + Go 2"; + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + TestExecutor testExecutor = new TestExecutor(query, con, new ExecutionEngineConditions()); + testExecutor.Run(); + + ScriptExecutionResult result = (testExecutor.ExecutionResult == ScriptExecutionResult.Success) ? ScriptExecutionResult.Success : ScriptExecutionResult.Failure; + + Assert.Equal(ScriptExecutionResult.Success, result); + } + } + } + + // Verify whether the batchParser execute SqlCmd. + //[Fact] // This Testcase should execute and pass, But it is failing now. + public void VerifyIsSqlCmd() + { + using (ExecutionEngine executionEngine = new ExecutionEngine()) + { + string query = @"sqlcmd -Q ""select 1 + 2 as col"" "; + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + TestExecutor testExecutor = new TestExecutor(query, con, new ExecutionEngineConditions()); + testExecutor.Run(); + Assert.True(testExecutor.ResultCountQueue.Count >= 1); + + } + } + } + + // Verify whether the executionEngine execute Batch + [Fact] + public void VerifyExecuteBatch() + { + using (ExecutionEngine executionEngine = new ExecutionEngine()) + { + string query = "SELECT 1+2"; + using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) + { + con.Open(); + + executionEngine.BatchParserExecutionFinished += OnBatchParserExecutionFinished; + executionEngine.ExecuteBatch(new ScriptExecutionArgs(query, con, 15, new ExecutionEngineConditions(), new BatchParserMockEventHandler())); + Assert.Equal(ScriptExecutionResult.Success, executionResult); + + } + } + } + // Capture the event once batch finish execution. + private void OnBatchParserExecutionFinished(object sender, BatchParserExecutionFinishedEventArgs e) + { + executionResult = e.ExecutionResult; + } + + [Fact] + public void CanceltheBatch() + { + Batch batch = new Batch(); + batch.Cancel(); + } + + private static Stream GenerateStreamFromString(string s) + { + MemoryStream stream = new MemoryStream(); + StreamWriter writer = new StreamWriter(stream); + writer.Write(s); + writer.Flush(); + stream.Position = 0; + return stream; + } + + public void TokenizeWithLexer(string filename, StringBuilder output) + { + // Create a new file by changing CRLFs to LFs and generate a new steam + // or the tokens generated by the lexer will always have off by one errors + string input = File.ReadAllText(filename).Replace("\r\n", "\n"); + var inputStream = GenerateStreamFromString(input); + using (Lexer lexer = new Lexer(new StreamReader(inputStream), filename)) + { + string inputText = File.ReadAllText(filename); + inputText = inputText.Replace("\r\n", "\n"); + StringBuilder roundtripTextBuilder = new StringBuilder(); + StringBuilder outputBuilder = new StringBuilder(); + StringBuilder tokenizedInput = new StringBuilder(); + bool lexerError = false; + + Token token = null; + try + { + do + { + lexer.ConsumeToken(); + token = lexer.CurrentToken; + roundtripTextBuilder.Append(token.Text.Replace("\r\n", "\n")); + outputBuilder.AppendLine(GetTokenString(token)); + tokenizedInput.Append('[').Append(GetTokenCode(token.TokenType)).Append(':').Append(token.Text.Replace("\r\n", "\n")).Append(']'); + } while (token.TokenType != LexerTokenType.Eof); + } + catch (BatchParserException ex) + { + lexerError = true; + outputBuilder.AppendLine(string.Format(CultureInfo.CurrentCulture, "[ERROR: code {0} at {1} - {2} in {3}, message: {4}]", ex.ErrorCode, GetPositionString(ex.Begin), GetPositionString(ex.End), GetFilenameOnly(ex.Begin.Filename), ex.Message)); + } + output.AppendLine("Lexer tokenized input:"); + output.AppendLine("======================"); + output.AppendLine(tokenizedInput.ToString()); + output.AppendLine("Tokens:"); + output.AppendLine("======="); + output.AppendLine(outputBuilder.ToString()); + + if (lexerError == false) + { + // Verify that all text from tokens can be recombined into original string + Assert.Equal(inputText, roundtripTextBuilder.ToString()); + } + } + } + + private string GetTokenCode(LexerTokenType lexerTokenType) + { + switch (lexerTokenType) + { + case LexerTokenType.Text: + return "T"; + + case LexerTokenType.Whitespace: + return "WS"; + + case LexerTokenType.NewLine: + return "NL"; + + case LexerTokenType.Comment: + return "C"; + + default: + return lexerTokenType.ToString(); + } + } + + private static void CopyToOutput(string sourceDirectory, string filename) + { + File.Copy(Path.Combine(sourceDirectory, filename), filename, true); + FileUtilities.SetFileReadWrite(filename); + } + + // [Fact] + public void BatchParserTest() + { + CopyToOutput(FilesLocation, "TS-err-cycle1.txt"); + CopyToOutput(FilesLocation, "cycle2.txt"); + Start("err-blockComment"); + Start("err-blockComment2"); + Start("err-varDefinition"); + Start("err-varDefinition2"); + Start("err-varDefinition3"); + Start("err-varDefinition4"); + Start("err-varDefinition5"); + Start("err-varDefinition6"); + Start("err-varDefinition7"); + Start("err-varDefinition8"); + Start("err-varDefinition9"); + Start("err-variableRef"); + Start("err-variableRef2"); + Start("err-variableRef3"); + Start("err-variableRef4"); + Start("err-cycle1"); + Start("input"); + Start("input2"); + Start("pass-blockComment"); + Start("pass-lineComment"); + Start("pass-lineComment2"); + Start("pass-noBlockComments"); + Start("pass-noLineComments"); + Start("pass-varDefinition"); + Start("pass-varDefinition2"); + Start("pass-varDefinition3"); + Start("pass-varDefinition4"); + Start("pass-command-and-comment"); + Assert.False(testFailed, "At least one of test cases failed. Check output for details."); + } + + public void TestParser(string filename, StringBuilder output) + { + try + { + // Create a new file by changing CRLFs to LFs and generate a new steam + // or the tokens generated by the lexer will always have off by one errors + TestCommandHandler commandHandler = new TestCommandHandler(output); + string input = File.ReadAllText(filename).Replace("\r\n", "\n"); + var inputStream = GenerateStreamFromString(input); + StreamReader streamReader = new StreamReader(inputStream); + + using (Parser parser = new Parser( + commandHandler, + new TestVariableResolver(output), + streamReader, + filename)) + { + commandHandler.SetParser(parser); + parser.Parse(); + } + } + catch (BatchParserException ex) + { + output.AppendLine(string.Format(CultureInfo.CurrentCulture, "[PARSER ERROR: code {0} at {1} - {2} in {3}, token text: {4}, message: {5}]", ex.ErrorCode, GetPositionString(ex.Begin), GetPositionString(ex.End), GetFilenameOnly(ex.Begin.Filename), ex.Text, ex.Message)); + } + } + + private string GetPositionString(PositionStruct pos) + { + return string.Format(CultureInfo.InvariantCulture, "{0}:{1} [{2}]", pos.Line, pos.Column, pos.Offset); + } + + private string GetTokenString(Token token) + { + if (token == null) + { + return "(null)"; + } + else + { + string tokenText = token.Text; + if (tokenText != null) + { + tokenText = tokenText.Replace("\r\n", "\\n").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t"); + } + string tokenFilename = token.Filename; + tokenFilename = GetFilenameOnly(tokenFilename); + return string.Format(CultureInfo.CurrentCulture, "[Token {0} at {1}({2}:{3} [{4}] - {5}:{6} [{7}]): '{8}']", + token.TokenType, + tokenFilename, + token.Begin.Line, token.Begin.Column, token.Begin.Offset, + token.End.Line, token.End.Column, token.End.Offset, + tokenText); + } + } + + internal static string GetFilenameOnly(string fullPath) + { + return fullPath != null ? Path.GetFileName(fullPath) : null; + } + + public override void Run() + { + string inputFilename = GetTestscriptFilePath(CurrentTestName); + StringBuilder output = new StringBuilder(); + + TokenizeWithLexer(inputFilename, output); + TestParser(inputFilename, output); + + string baselineFilename = GetBaselineFilePath(CurrentTestName); + string baseline; + + try + { + baseline = GetFileContent(baselineFilename).Replace("\r\n", "\n"); + } + catch (FileNotFoundException) + { + baseline = string.Empty; + } + + string outputString = output.ToString().Replace("\r\n", "\n"); + + //Console.WriteLine(baselineFilename); + + if (string.Compare(baseline, outputString, StringComparison.Ordinal) != 0) + { + DumpToTrace(CurrentTestName, outputString); + string outputFilename = Path.Combine(TraceFilePath, GetBaselineFileName(CurrentTestName)); + Console.WriteLine(":: Output does not match the baseline!"); + Console.WriteLine("code --diff \"" + baselineFilename + "\" \"" + outputFilename + "\""); + Console.WriteLine(); + Console.WriteLine(":: To update the baseline:"); + Console.WriteLine("copy \"" + outputFilename + "\" \"" + baselineFilename + "\""); + Console.WriteLine(); + testFailed = true; + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserWrapperTests.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserWrapperTests.cs similarity index 80% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserWrapperTests.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserWrapperTests.cs index b6448140..4dccbf96 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserWrapperTests.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/BatchParserWrapperTests.cs @@ -30,6 +30,24 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser } } + [Fact] + public void CheckSimpleMultipleQLBatchStatement() + { + using (BatchParserWrapper parserWrapper = new BatchParserWrapper()) + { + string sqlScript = @"SELECT 'FirstLine'; + GO + SELECT 'MiddleLine_1'; + GO + SELECT 'MiddleLine_1' + GO + SELECT 'LastLine'"; + var batches = parserWrapper.GetBatches(sqlScript); + // Each select statement is one batch , so we are expecting 4 batches. + Assert.Equal(4, batches.Count); + } + } + [Fact] public void CheckSQLBatchStatementWithRepeatExecution() { diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/TestCommandHandler.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/TestCommandHandler.cs similarity index 96% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/TestCommandHandler.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/TestCommandHandler.cs index 9979b0fa..d8267b70 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/TestCommandHandler.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/TestCommandHandler.cs @@ -4,9 +4,9 @@ // using System; +using System.Globalization; using System.IO; using System.Text; -using System.Globalization; using Microsoft.SqlTools.ServiceLayer.BatchParser; namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser @@ -36,7 +36,7 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser batch.GetText(true, out textWithVariablesResolved, out lineInfoVarsResolved); batch.GetText(false, out textWithVariablesUnresolved, out lineInfoVarsUnresolved); outputString.AppendFormat(CultureInfo.InvariantCulture, "*** Execute batch ({0})\n", repeatCount); - + if (string.Compare(textWithVariablesUnresolved, textWithVariablesResolved, StringComparison.Ordinal) != 0) { outputString.AppendLine("Text with variables not resolved:"); @@ -49,10 +49,10 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser { PositionStruct pos = lineInfoVarsResolved.GetStreamPositionForOffset(i); string character = i < textWithVariablesResolved.Length ? ("" + textWithVariablesResolved[i]).Replace("\n", @"\n").Replace("\r", @"\r") : "EOF"; - outputString.AppendFormat(CultureInfo.InvariantCulture, "Pos [{0}] {1}:{2} \"{3}\"", - i, - BatchParserTests.GetFilenameOnly(pos.Filename), - pos.Offset, + outputString.AppendFormat(CultureInfo.InvariantCulture, "Pos [{0}] {1}:{2} \"{3}\"", + i, + BatchParserTests.GetFilenameOnly(pos.Filename), + pos.Offset, character); outputString.AppendLine(); i++; @@ -89,4 +89,4 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser return BatchParserAction.Continue; } } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/TestVariableResolver.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/TestVariableResolver.cs similarity index 64% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/TestVariableResolver.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/TestVariableResolver.cs index c4b116bd..2be34803 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/TestVariableResolver.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/BatchParser/TestVariableResolver.cs @@ -7,42 +7,30 @@ using System; using System.Collections.Generic; using System.Text; using Microsoft.SqlTools.ServiceLayer.BatchParser; +using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser { internal sealed class TestVariableResolver : IVariableResolver { - Dictionary variables = new Dictionary(StringComparer.OrdinalIgnoreCase); private StringBuilder outputString; + private BatchParserSqlCmd batchParserSqlCmd; public TestVariableResolver(StringBuilder outputString) { this.outputString = outputString; + batchParserSqlCmd = new BatchParserSqlCmd(); } public string GetVariable(PositionStruct pos, string name) { - if (variables.ContainsKey(name)) - { - return variables[name]; - } - else - { - return null; - } + return batchParserSqlCmd.GetVariable(pos, name); } public void SetVariable(PositionStruct pos, string name, string value) { outputString.AppendFormat("Setting variable {0} to [{1}]\n", name, value); - if (value == null) - { - variables.Remove(name); - } - else - { - variables[name] = value; - } + batchParserSqlCmd.SetVariable(pos, name, value); } } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj new file mode 100644 index 00000000..2c473b5b --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.csproj @@ -0,0 +1,46 @@ + + + + netcoreapp2.2 + false + portable + Microsoft.SqlTools.ManagedBatchParser.IntegrationTests + Microsoft.SqlTools.ManagedBatchParser.IntegrationTests + true + $(DefineConstants);TRACE + + + + + + + ../../bin/ref/Newtonsoft.Json.dll + + + ../../bin/ref/Moq.dll + + + ../../bin/ref/Castle.Core.dll + + + + + + + + + + + + + + + + + + + + + $(DefineConstants);WINDOWS_ONLY_BUILD + + diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Properties/AssemblyInfo.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5d1e1a0d --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.SqlTools.ManagedBatchParser.IntegrationTests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Microsoft.SqlTools.ManagedBatchParser.IntegrationTests")] +[assembly: AssemblyCopyright("Copyright � 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("340E4742-BF01-4EF8-B2A5-9CEC1075A842")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/BatchEventHandler.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/BatchEventHandler.cs similarity index 84% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/BatchEventHandler.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/BatchEventHandler.cs index 57c24465..29b57b7a 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/BatchEventHandler.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/BatchEventHandler.cs @@ -5,22 +5,22 @@ using System; using System.Collections.Generic; -using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; using System.Data.SqlClient; +using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; - -namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine +namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.TSQLExecutionEngine { - internal class BatchEventHandler: IBatchEventsHandler + internal class BatchEventHandler : IBatchEventsHandler { - List resultCounts = new List(); - List sqlMessages = new List(); - List errorMessage = new List(); - int batchfinishedEventCounter = 0; - SqlDataReader dr = null; - bool cancelEventFired = false; + private List resultCounts = new List(); + private List sqlMessages = new List(); + private List errorMessage = new List(); + private int batchfinishedEventCounter = 0; + private SqlDataReader dr = null; + private bool cancelEventFired = false; #region Public properties + public List ResultCounts { get @@ -52,6 +52,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine return batchfinishedEventCounter; } } + public bool CancelFired { get @@ -59,9 +60,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine return cancelEventFired; } } - #endregion + + #endregion Public properties #region IBatchEventHandlers Members + public void OnBatchCancelling(object sender, EventArgs args) { Console.WriteLine("\tOnBatchCancelling:"); @@ -103,9 +106,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine } public void OnBatchResultSetProcessing(object sender, BatchResultSetEventArgs args) - { + { lock (this) - { + { Console.WriteLine("\tOnBatchResultProcessing..."); dr = args.DataReader as SqlDataReader; int count = 0; @@ -118,6 +121,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine } } - #endregion + #endregion IBatchEventHandlers Members } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/ExecutionEngineTest.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/ExecutionEngineTest.cs similarity index 97% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/ExecutionEngineTest.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/ExecutionEngineTest.cs index 59dd6a0b..22204bde 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/ExecutionEngineTest.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/ExecutionEngineTest.cs @@ -3,26 +3,24 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // - using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; using Microsoft.SqlTools.ServiceLayer.Connection; -using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.Test.Common; -using Moq; using Xunit; -using System.Threading.Tasks; -namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine +namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.TSQLExecutionEngine { /// ///This is a test class for Microsoft.Data.Tools.Schema.Common.ExecutionEngine.ExecutionEngine and is intended ///to contain all Microsoft.Data.Tools.Schema.Common.ExecutionEngine.ExecutionEngine Unit Tests /// - + public class ExecutionEngineTest : IDisposable { private SqlConnection connection; @@ -73,11 +71,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine //Task.Run(() => SqlTestDb.DropDatabase(connection.Database)); CloseConnection(connection); connection = null; - } + } - #endregion + #endregion Test Initialize And Cleanup #region Valid scripts + /// ///A test for a simple SQL script /// @@ -91,7 +90,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine conditions.IsParseOnly = false; conditions.IsHaltOnError = false; - TestExecutor executor = new TestExecutor(sqlStatement, connection, conditions); + TestExecutor executor = new TestExecutor(sqlStatement, connection, conditions); executor.Run(); //Get the expected values @@ -171,9 +170,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine Assert.Equal(ScriptExecutionResult.Success, executor.ExecutionResult); Assert.True(CompareTwoIntLists(executor.ResultCountQueue, expResultCounts)); } - #endregion + + #endregion Valid scripts #region Invalid Scripts + /// /// Test with a invalid query using the default execution condition /// @@ -191,7 +192,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine List batchScripts = executor.BatchScripts; ExecuteSqlBatch(batchScripts, connection); - Assert.Equal( ScriptExecutionResult.Success | ScriptExecutionResult.Failure, executor.ExecutionResult); + Assert.Equal(ScriptExecutionResult.Success | ScriptExecutionResult.Failure, executor.ExecutionResult); Assert.True(!executor.ParserExecutionError); Assert.True(CompareTwoStringLists(executor.ErrorMessageQueue, expErrorMessage)); Assert.True(CompareTwoIntLists(executor.ResultCountQueue, expResultCounts)); @@ -235,10 +236,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine conditions.IsTransactionWrapped = true; conditions.IsParseOnly = false; conditions.IsHaltOnError = false; - + TestExecutor executor = new TestExecutor(sqlStatement, connection, conditions); executor.Run(); - + //Get the expected values List batchScripts = executor.BatchScripts; ExecuteSqlBatch(batchScripts, connection); @@ -306,11 +307,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine { ExecutionEngine engine = new ExecutionEngine(); Assert.True(ConnectionDiscardWrapper(engine)); - } - #endregion + + #endregion Invalid Scripts #region Different execution conditions + /// /// Test HaltOnError execution condition /// @@ -334,7 +336,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine Assert.True(CompareTwoStringLists(executor.ErrorMessageQueue, expErrorMessage)); Assert.True(CompareTwoIntLists(executor.ResultCountQueue, expResultCounts)); Assert.True(executor.ResultCountQueue.Count == 0); - } /// @@ -361,7 +362,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine Assert.True(CompareTwoIntLists(executor.ResultCountQueue, expResultCounts)); Assert.True(executor.ResultCountQueue.Count == 0); Assert.Equal(0, executor.BatchFinshedEventCounter); - } /// @@ -462,9 +462,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine TestExecutor executor = new TestExecutor(sqlStatement, connection, conditions); executor.Run(); - // Note: this used to also return Halted at some point in the distant past. + // Note: this used to also return Halted at some point in the distant past. // However since that gets mapped to Failure anyhow, consider "Failure" as acceptable here - Assert.True(executor.ExecutionResult.HasFlag(ScriptExecutionResult.Failure), "Expected failure when invalid connection is present" ); + Assert.True(executor.ExecutionResult.HasFlag(ScriptExecutionResult.Failure), "Expected failure when invalid connection is present"); } /// @@ -489,16 +489,18 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine Assert.Equal(ScriptExecutionResult.Success, executor.ExecutionResult); Assert.True(CompareTwoIntLists(executor.ResultCountQueue, expResultCounts)); } - #endregion + + #endregion Different execution conditions #region SQL Commands + /// /// Test with SQL commands /// [Fact] public void ExecutionEngineTest_SQLCmds() { - string[] sqlStatements = { + string[] sqlStatements = { "select $(INVALIDVAR) from sysobjects", ":help", "exit", @@ -517,7 +519,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine ":perftrace STDOUT", "exit (Select count(*) from sysobjects)" }; - + ExecutionEngineConditions conditions = new ExecutionEngineConditions(); foreach (string stmt in sqlStatements) @@ -526,11 +528,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine executor.Run(); Assert.True(executor.ResultCountQueue.Count == 0); } - } - #endregion + + #endregion SQL Commands #region Threading + /// /// Test synchronous cancel /// @@ -547,11 +550,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine TestExecutor executor = new TestExecutor(sqlStatement, connection, conditions, true); executor.CancelTimeOut = 3000; executor.Run(); - + Assert.NotNull(executor.ScriptExecuteThread); Assert.Equal(ScriptExecutionResult.Cancel, executor.ExecutionResult); Assert.True(executor.CancelEventFired); - } /// @@ -582,13 +584,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine /// /// Test sync cancel when the execution is done /// - /// - /// Disabled test, has race condition where Sql statement will finish + /// + /// Disabled test, has race condition where Sql statement will finish /// before harness has an opportunity to cancel. //TEST_DOESNOTWORK[TestMethod()] public void ExecutionEngineTest_SyncCancelAfterExecutionDone() { - string sqlStatement = "select 1" ; + string sqlStatement = "select 1"; ExecutionEngineConditions conditions = new ExecutionEngineConditions(); conditions.IsTransactionWrapped = true; @@ -603,7 +605,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine if (executor.ScriptExecuteThread != null) Assert.True(!executor.ScriptExecuteThread.IsAlive); Assert.Equal(ScriptExecutionResult.Success | ScriptExecutionResult.Cancel, executor.ExecutionResult); - } /// @@ -612,7 +613,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine [Fact] public void ExecutionEngineTest_ASyncCancelAfterExecutionDone() { - string sqlStatement ="select 1"; + string sqlStatement = "select 1"; ExecutionEngineConditions conditions = new ExecutionEngineConditions(); conditions.IsTransactionWrapped = true; @@ -688,7 +689,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine await SqlTestDb.DropDatabase(connection3.Database); } - #endregion + #endregion Threading #region Get/Set Methods @@ -751,9 +752,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine Assert.Equal(conditions.BatchSeparator, "GO"); } - #endregion + #endregion Get/Set Methods #region Private methods + /// /// Connection to a database /// @@ -774,7 +776,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine { foreach (string script in sqlBatch) { - ExecuteSqlCommand(script, connection); + ExecuteSqlCommand(script, connection); } } @@ -788,7 +790,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine SqlCommand cmd = new SqlCommand(sqlCmdTxt, connection); SqlTransaction transaction = connection.BeginTransaction(); cmd.Transaction = transaction; - + try { using (SqlDataReader dr = cmd.ExecuteReader()) @@ -806,7 +808,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine transaction.Commit(); } catch (Exception e) - { + { Console.WriteLine("Executing command throws exception: " + e.Message); expErrorMessage.Add(e.Message); try @@ -830,7 +832,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine private bool CompareTwoStringLists(List l1, List l2) { bool isSame = true; - if(l1.Count != l2.Count) + if (l1.Count != l2.Count) { isSame = false; Console.WriteLine("The count of elements in two lists are not the same"); @@ -893,6 +895,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine engine.Close(false, true, true); return true; } - #endregion + + #endregion Private methods } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/TestExecutor.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/TestExecutor.cs similarity index 82% rename from test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/TestExecutor.cs rename to test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/TestExecutor.cs index e29d38af..319495c6 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/TSQLExecutionEngine/TestExecutor.cs +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/TSQLExecutionEngine/TestExecutor.cs @@ -10,36 +10,40 @@ using System.Threading; using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; using Microsoft.SqlTools.Utility; -namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine +namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.TSQLExecutionEngine { - class TestExecutor : IDisposable + internal class TestExecutor : IDisposable { #region Private variables - string sqlStatement; - ExecutionEngineConditions conditions = new ExecutionEngineConditions(); - BatchEventHandler eventHandler = new BatchEventHandler(); - SqlConnection connection = null; - static Thread _executionThread; - bool _syncCancel = true; - bool _isFinished = false; - bool _cancel = false; - int _cancelTimeout = 500; - int exeTimeOut = 0; + + private string sqlStatement; + private ExecutionEngineConditions conditions = new ExecutionEngineConditions(); + private BatchEventHandler eventHandler = new BatchEventHandler(); + private SqlConnection connection = null; + private static Thread _executionThread; + private bool _syncCancel = true; + private bool _isFinished = false; + private bool _cancel = false; + private int _cancelTimeout = 500; + private int exeTimeOut = 0; //For verification - List resultCounts = new List(); - List sqlMessages = new List(); - List errorMessage = new List(); - List batchFinished = new List(); - static ScriptExecutionResult execResult = ScriptExecutionResult.All; - static List batchScripts = new List(); - static Thread exeThread = null; - static bool parserExecutionError = false; - #endregion + private List resultCounts = new List(); + + private List sqlMessages = new List(); + private List errorMessage = new List(); + private List batchFinished = new List(); + private static ScriptExecutionResult execResult = ScriptExecutionResult.All; + private static List batchScripts = new List(); + private static Thread exeThread = null; + private static bool parserExecutionError = false; + + #endregion Private variables #region private methods + /// - /// Execut the script + /// Execute the script /// /// Execution Engine /// SQL connection @@ -47,7 +51,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine /// Execution condition /// Batch event handler /// time out value - static void ExecuteScript(ExecutionEngine exec, SqlConnection connection, string script, ExecutionEngineConditions conditions, IBatchEventsHandler batchHandler, int timeout) + private static void ExecuteScript(ExecutionEngine exec, SqlConnection connection, string script, ExecutionEngineConditions conditions, IBatchEventsHandler batchHandler, int timeout) { Validate.IsNotNull(nameof(exec), exec); Validate.IsNotNull(nameof(connection), connection); @@ -70,7 +74,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine /// Execution Engine /// Cancel the execution synchronously or not /// sycn canceo timeout - static void Cancel(ExecutionEngine exec, bool isSynchronous, int millisecondsTimeOut) + private static void Cancel(ExecutionEngine exec, bool isSynchronous, int millisecondsTimeOut) { //exec.BeginCancellingExecution(isSynchronous, timeout); @@ -109,9 +113,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine } Thread.Sleep(5000); } - #endregion + + #endregion private methods #region Public properties + public bool SyncCancel { get @@ -207,10 +213,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine return parserExecutionError; } } - #endregion + + #endregion Public properties #region Constructors - public TestExecutor(string batch, SqlConnection conn, ExecutionEngineConditions exeCondition): this(batch, conn, exeCondition, false) + + public TestExecutor(string batch, SqlConnection conn, ExecutionEngineConditions exeCondition) : this(batch, conn, exeCondition, false) { } @@ -219,9 +227,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine sqlStatement = batch; conditions.IsHaltOnError = exeCondition.IsHaltOnError; conditions.IsParseOnly = exeCondition.IsParseOnly; - conditions.IsTransactionWrapped = exeCondition.IsTransactionWrapped; - conditions.IsNoExec = exeCondition.IsNoExec; - conditions.IsStatisticsIO = exeCondition.IsStatisticsIO; + conditions.IsTransactionWrapped = exeCondition.IsTransactionWrapped; + conditions.IsNoExec = exeCondition.IsNoExec; + conditions.IsStatisticsIO = exeCondition.IsStatisticsIO; conditions.IsStatisticsTime = exeCondition.IsStatisticsTime; _cancel = cancelExecution; @@ -232,16 +240,18 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine batchScripts = new List(); exeThread = null; parserExecutionError = false; - } + public TestExecutor(string batch, SqlConnection conn, ExecutionEngineConditions exeCondition, int timeOut) : this(batch, conn, exeCondition, false) { exeTimeOut = timeOut; } - #endregion + + #endregion Constructors #region public methods + /// /// Execute the test engine /// @@ -282,15 +292,17 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine } } } - #endregion + + #endregion public methods #region ParserEvent + /// /// Called when batch is called /// /// /// - static void OnBatchParserExecutionStart(object sender, BatchParserExecutionStartEventArgs e) + private static void OnBatchParserExecutionStart(object sender, BatchParserExecutionStartEventArgs e) { Console.WriteLine("****************"); Console.WriteLine(e.Batch.Text); @@ -306,7 +318,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine /// /// /// - static void OnBatchParserExecutionFinished(object sender, BatchParserExecutionFinishedEventArgs e) + private static void OnBatchParserExecutionFinished(object sender, BatchParserExecutionFinishedEventArgs e) { Console.WriteLine("ON_BATCH_PARSER_EXECUTION_FINISHED : Done executing batch \n\t{0}\n\t with result... {1} ", e.Batch.Text, e.ExecutionResult); if (execResult == ScriptExecutionResult.All) @@ -320,12 +332,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine /// /// /// - static void OnBatchParserExecutionError(object sender, BatchParserExecutionErrorEventArgs e) - { + private static void OnBatchParserExecutionError(object sender, BatchParserExecutionErrorEventArgs e) + { Console.WriteLine("ON_BATCH_PARSER_EXECUTION_ERROR : {0} found... at line {1}: {2}", e.MessageType.ToString(), e.Line.ToString(), e.Message); Console.WriteLine("\t Error Description: " + e.Description); parserExecutionError = true; - } /// @@ -341,18 +352,21 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine if (execResult == ScriptExecutionResult.All) execResult = e.ExecutionResult; else - execResult = execResult|e.ExecutionResult; + execResult = execResult | e.ExecutionResult; resultCounts = eventHandler.ResultCounts; sqlMessages = eventHandler.SqlMessages; errorMessage = eventHandler.ErrorMessages; } - #endregion + + #endregion ParserEvent #region IDisposable Members + public void Dispose() { } - #endregion + + #endregion IDisposable Members } -} +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Utility/FileUtilities.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Utility/FileUtilities.cs new file mode 100644 index 00000000..f99b25bf --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Utility/FileUtilities.cs @@ -0,0 +1,20 @@ +using System.IO; + +namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.Utility +{ + internal class FileUtilities + { + /// + /// Turns off the read-only attribute for this file + /// + /// + internal static void SetFileReadWrite(string fullFilePath) + { + if (!string.IsNullOrEmpty(fullFilePath) && + File.Exists(fullFilePath)) + { + File.SetAttributes(fullFilePath, FileAttributes.Normal); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Utility/LiveConnectionHelper.cs b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Utility/LiveConnectionHelper.cs new file mode 100644 index 00000000..a905c153 --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/Utility/LiveConnectionHelper.cs @@ -0,0 +1,149 @@ +using System; +using System.Data.SqlClient; +using System.IO; +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; +using Xunit; + +namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.Utility +{ + public class LiveConnectionHelper + { + public static string GetTestSqlFile(string fileName = null) + { + string filePath = null; + if (string.IsNullOrEmpty(fileName)) + { + filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "sqltest.sql"); + } + else + { + filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), fileName + ".sql"); + } + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + File.WriteAllText(filePath, "SELECT * FROM sys.objects\n"); + return filePath; + } + + public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null, string ownerUri = null) + { + ScriptFile scriptFile = null; + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); + if (string.IsNullOrEmpty(ownerUri)) + { + ownerUri = GetTestSqlFile(); + scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri); + ownerUri = scriptFile.ClientFilePath; + } + var connectionService = GetLiveTestConnectionService(); + var connectionResult = + connectionService + .Connect(new ConnectParams + { + OwnerUri = ownerUri, + Connection = connectParams.Connection + }); + + connectionResult.Wait(); + + ConnectionInfo connInfo = null; + connectionService.TryFindConnection(ownerUri, out connInfo); + return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile }; + } + + public static async Task InitLiveConnectionInfoAsync(string databaseName = null, string ownerUri = null, + string connectionType = ServiceLayer.Connection.ConnectionType.Default) + { + ScriptFile scriptFile = null; + if (string.IsNullOrEmpty(ownerUri)) + { + ownerUri = GetTestSqlFile(); + scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri); + ownerUri = scriptFile.ClientFilePath; + } + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); + + var connectionService = GetLiveTestConnectionService(); + var connectionResult = + await connectionService + .Connect(new ConnectParams + { + OwnerUri = ownerUri, + Connection = connectParams.Connection, + Type = connectionType + }); + if (!string.IsNullOrEmpty(connectionResult.ErrorMessage)) + { + Console.WriteLine(connectionResult.ErrorMessage); + } + + ConnectionInfo connInfo = null; + connectionService.TryFindConnection(ownerUri, out connInfo); + return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile }; + } + + public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null) + { + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) + { + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); + string ownerUri = queryTempFile.FilePath; + var connectionService = GetLiveTestConnectionService(); + var connectionResult = + connectionService + .Connect(new ConnectParams + { + OwnerUri = ownerUri, + Connection = connectParams.Connection + }); + + connectionResult.Wait(); + + ConnectionInfo connInfo = null; + connectionService.TryFindConnection(ownerUri, out connInfo); + + Assert.NotNull(connInfo); + return connInfo; + } + } + + public static ServerConnection InitLiveServerConnectionForDefinition(ConnectionInfo connInfo) + { + SqlConnection sqlConn = new SqlConnection(ConnectionService.BuildConnectionString(connInfo.ConnectionDetails)); + return new ServerConnection(sqlConn); + } + + /// + /// Creates a test sql connection factory instance + /// + public static ISqlConnectionFactory GetLiveTestSqlConnectionFactory() + { + // connect to a real server instance + return ConnectionService.Instance.ConnectionFactory; + } + + public static ConnectionService GetLiveTestConnectionService() + { + // connect to a real server instance + return ConnectionService.Instance; + } + + public class TestConnectionResult + { + public ConnectionInfo ConnectionInfo { get; set; } + + public ScriptFile ScriptFile { get; set; } + + public TextDocumentPosition TextDocumentPosition { get; set; } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/packages.config b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/packages.config new file mode 100644 index 00000000..d01e8969 --- /dev/null +++ b/test/Microsoft.SqlTools.ManagedBatchParser.IntegrationTests/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs deleted file mode 100644 index 6580ec67..00000000 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs +++ /dev/null @@ -1,292 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.Globalization; -using System.IO; -using System.Text; -using Microsoft.SqlTools.ServiceLayer.BatchParser; -using Microsoft.SqlTools.ServiceLayer.Test.Common; -using Microsoft.SqlTools.ServiceLayer.Test.Common.Baselined; -using Xunit; -using Microsoft.SqlTools.ServiceLayer.Utility; -using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; -using Microsoft.SqlTools.ServiceLayer.IntegrationTests.TSQLExecutionEngine; - -namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser -{ - public class BatchParserTests : BaselinedTest - { - private bool testFailed = false; - - public BatchParserTests() - { - InitializeTest(); - } - - public void InitializeTest() - { - CategoryName = "BatchParser"; - this.TraceOutputDirectory = RunEnvironmentInfo.GetTraceOutputLocation(); - TestInitialize(); - } - - [Fact] - public void VerifyThrowOnUnresolvedVariable() - { - string script = "print '$(NotDefined)'"; - StringBuilder output = new StringBuilder(); - - TestCommandHandler handler = new TestCommandHandler(output); - IVariableResolver resolver = new TestVariableResolver(new StringBuilder()); - using (Parser p = new Parser( - handler, - resolver, - new StringReader(script), - "test")) - { - p.ThrowOnUnresolvedVariable = true; - handler.SetParser(p); - - Assert.Throws(() => p.Parse()); - } - } - - [Fact] - public void VerifyExecuteScript() - { - string query = "select @@version"; - ExecutionEngineTest executionEngineTest = new ExecutionEngineTest(); - executionEngineTest.TestInitialize(); - using (ExecutionEngine engine = new ExecutionEngine()) - { - engine.ExecuteScript(query); - } - } - - [Fact] - public void CanceltheBatch() - { - Batch batch = new Batch(); - batch.Cancel(); - } - - private static Stream GenerateStreamFromString(string s) - { - MemoryStream stream = new MemoryStream(); - StreamWriter writer = new StreamWriter(stream); - writer.Write(s); - writer.Flush(); - stream.Position = 0; - return stream; - } - - public void TokenizeWithLexer(string filename, StringBuilder output) - { - // Create a new file by changing CRLFs to LFs and generate a new steam - // or the tokens generated by the lexer will always have off by one errors - string input = File.ReadAllText(filename).Replace("\r\n", "\n"); - var inputStream = GenerateStreamFromString(input); - using (Lexer lexer = new Lexer(new StreamReader(inputStream), filename)) - { - - string inputText = File.ReadAllText(filename); - inputText = inputText.Replace("\r\n", "\n"); - StringBuilder roundtripTextBuilder = new StringBuilder(); - StringBuilder outputBuilder = new StringBuilder(); - StringBuilder tokenizedInput = new StringBuilder(); - bool lexerError = false; - - Token token = null; - try - { - do - { - lexer.ConsumeToken(); - token = lexer.CurrentToken; - roundtripTextBuilder.Append(token.Text.Replace("\r\n", "\n")); - outputBuilder.AppendLine(GetTokenString(token)); - tokenizedInput.Append('[').Append(GetTokenCode(token.TokenType)).Append(':').Append(token.Text.Replace("\r\n", "\n")).Append(']'); - } while (token.TokenType != LexerTokenType.Eof); - } - catch (BatchParserException ex) - { - lexerError = true; - outputBuilder.AppendLine(string.Format(CultureInfo.CurrentCulture, "[ERROR: code {0} at {1} - {2} in {3}, message: {4}]", ex.ErrorCode, GetPositionString(ex.Begin), GetPositionString(ex.End), GetFilenameOnly(ex.Begin.Filename), ex.Message)); - } - output.AppendLine("Lexer tokenized input:"); - output.AppendLine("======================"); - output.AppendLine(tokenizedInput.ToString()); - output.AppendLine("Tokens:"); - output.AppendLine("======="); - output.AppendLine(outputBuilder.ToString()); - - if (lexerError == false) - { - // Verify that all text from tokens can be recombined into original string - Assert.Equal(inputText, roundtripTextBuilder.ToString()); - } - } - } - - private string GetTokenCode(LexerTokenType lexerTokenType) - { - switch (lexerTokenType) - { - case LexerTokenType.Text: - return "T"; - case LexerTokenType.Whitespace: - return "WS"; - case LexerTokenType.NewLine: - return "NL"; - case LexerTokenType.Comment: - return "C"; - default: - return lexerTokenType.ToString(); - } - } - - private static void CopyToOutput(string sourceDirectory, string filename) - { - File.Copy(Path.Combine(sourceDirectory, filename), filename, true); - FileUtilities.SetFileReadWrite(filename); - } - - // [Fact] - public void BatchParserTest() - { - CopyToOutput(FilesLocation, "TS-err-cycle1.txt"); - CopyToOutput(FilesLocation, "cycle2.txt"); - Start("err-blockComment"); - Start("err-blockComment2"); - Start("err-varDefinition"); - Start("err-varDefinition2"); - Start("err-varDefinition3"); - Start("err-varDefinition4"); - Start("err-varDefinition5"); - Start("err-varDefinition6"); - Start("err-varDefinition7"); - Start("err-varDefinition8"); - Start("err-varDefinition9"); - Start("err-variableRef"); - Start("err-variableRef2"); - Start("err-variableRef3"); - Start("err-variableRef4"); - Start("err-cycle1"); - Start("input"); - Start("input2"); - Start("pass-blockComment"); - Start("pass-lineComment"); - Start("pass-lineComment2"); - Start("pass-noBlockComments"); - Start("pass-noLineComments"); - Start("pass-varDefinition"); - Start("pass-varDefinition2"); - Start("pass-varDefinition3"); - Start("pass-varDefinition4"); - Start("pass-command-and-comment"); - Assert.False(testFailed, "At least one of test cases failed. Check output for details."); - } - - public void TestParser(string filename, StringBuilder output) - { - try - { - // Create a new file by changing CRLFs to LFs and generate a new steam - // or the tokens generated by the lexer will always have off by one errors - TestCommandHandler commandHandler = new TestCommandHandler(output); - string input = File.ReadAllText(filename).Replace("\r\n", "\n"); - var inputStream = GenerateStreamFromString(input); - StreamReader streamReader = new StreamReader(inputStream); - - using (Parser parser = new Parser( - commandHandler, - new TestVariableResolver(output), - streamReader, - filename)) - { - commandHandler.SetParser(parser); - parser.Parse(); - } - } - catch (BatchParserException ex) - { - output.AppendLine(string.Format(CultureInfo.CurrentCulture, "[PARSER ERROR: code {0} at {1} - {2} in {3}, token text: {4}, message: {5}]", ex.ErrorCode, GetPositionString(ex.Begin), GetPositionString(ex.End), GetFilenameOnly(ex.Begin.Filename), ex.Text, ex.Message)); - } - } - - private string GetPositionString(PositionStruct pos) - { - return string.Format(CultureInfo.InvariantCulture, "{0}:{1} [{2}]", pos.Line, pos.Column, pos.Offset); - } - - private string GetTokenString(Token token) - { - if (token == null) - { - return "(null)"; - } - else - { - string tokenText = token.Text; - if (tokenText != null) - { - tokenText = tokenText.Replace("\r\n", "\\n").Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t"); - } - string tokenFilename = token.Filename; - tokenFilename = GetFilenameOnly(tokenFilename); - return string.Format(CultureInfo.CurrentCulture, "[Token {0} at {1}({2}:{3} [{4}] - {5}:{6} [{7}]): '{8}']", - token.TokenType, - tokenFilename, - token.Begin.Line, token.Begin.Column, token.Begin.Offset, - token.End.Line, token.End.Column, token.End.Offset, - tokenText); - } - } - - internal static string GetFilenameOnly(string fullPath) - { - return fullPath != null ? Path.GetFileName(fullPath) : null; - } - - public override void Run() - { - string inputFilename = GetTestscriptFilePath(CurrentTestName); - StringBuilder output = new StringBuilder(); - - TokenizeWithLexer(inputFilename, output); - TestParser(inputFilename, output); - - string baselineFilename = GetBaselineFilePath(CurrentTestName); - string baseline; - - try - { - baseline = GetFileContent(baselineFilename).Replace("\r\n", "\n"); - } - catch (FileNotFoundException) - { - baseline = string.Empty; - } - - string outputString = output.ToString().Replace("\r\n", "\n"); - - //Console.WriteLine(baselineFilename); - - if (string.Compare(baseline, outputString, StringComparison.Ordinal) != 0) - { - DumpToTrace(CurrentTestName, outputString); - string outputFilename = Path.Combine(TraceFilePath, GetBaselineFileName(CurrentTestName)); - Console.WriteLine(":: Output does not match the baseline!"); - Console.WriteLine("code --diff \"" + baselineFilename + "\" \"" + outputFilename + "\""); - Console.WriteLine(); - Console.WriteLine(":: To update the baseline:"); - Console.WriteLine("copy \"" + outputFilename + "\" \"" + baselineFilename + "\""); - Console.WriteLine(); - testFailed = true; - } - } - } -}