diff --git a/packages.config b/packages.config index b54a7653b29..1c13c60c937 100644 --- a/packages.config +++ b/packages.config @@ -3,4 +3,6 @@ + + \ No newline at end of file diff --git a/src/fsharp.sln b/src/fsharp.sln index 0e9eb059b59..2d535cee41d 100644 --- a/src/fsharp.sln +++ b/src/fsharp.sln @@ -32,6 +32,9 @@ EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsiAnyCPU", "fsharp\fsiAnyCpu\FsiAnyCPU.fsproj", "{8B3E283D-B5FE-4055-9D80-7E3A32F3967B}" EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Unittests", "fsharp\FSharp.Compiler.Unittests\FSharp.Compiler.Unittests.fsproj", "{A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E49B77EA-64DE-451A-A5E6-A6632FC1F03C}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Tests", "..\tests\fsharp\FSharp.Tests.fsproj", "{C163E892-5BF7-4B59-AA99-B0E8079C67C4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -81,8 +84,16 @@ Global {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU {A8D9641A-9170-4CF4-8FE0-6DB8C134E1B5}.Release|Any CPU.Build.0 = Release|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C163E892-5BF7-4B59-AA99-B0E8079C67C4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {88E2D422-6852-46E3-A740-83E391DC7973} = {E49B77EA-64DE-451A-A5E6-A6632FC1F03C} + {C163E892-5BF7-4B59-AA99-B0E8079C67C4} = {E49B77EA-64DE-451A-A5E6-A6632FC1F03C} + EndGlobalSection EndGlobal diff --git a/src/update.fs b/src/update.fs new file mode 100644 index 00000000000..9ba090f5bc9 --- /dev/null +++ b/src/update.fs @@ -0,0 +1,186 @@ + +module UpdateCmd + +open System.IO +open NUnit.Framework +open Microsoft.Win32 + +open PlatformHelpers +open FSharpTestSuiteTypes + +type Configuration = + | DEBUG + | RELEASE + override this.ToString() = + match this with + | DEBUG -> "Debug" + | RELEASE -> "Release" + +type updateCmdArgs = + { Configuration : Configuration + Ngen : bool } + +let private regQuery = WindowsPlatform.regQuery + +let private checkResult result = + match result with + | CmdResult.ErrorLevel err -> let x = err, (sprintf "ERRORLEVEL %d" err) in Failure (RunError.ProcessExecError x) + | CmdResult.Success -> Success () + +let updateCmd envVars args = processor { + // @echo off + // setlocal + ignore "useless" + + // if /i "%1" == "debug" goto :ok + // if /i "%1" == "release" goto :ok + ignore "already validated input" + + // echo GACs built binaries, adds required strong name verification skipping, and optionally NGens built binaries + // echo Usage: + // echo update.cmd debug [-ngen] + // echo update.cmd release [-ngen] + // exit /b 1 + ignore "useless help" + + //:ok + let env k () = match envVars |> Map.tryFind k with None -> Failure (sprintf "environment variable '%s' not found" k) | Some x -> Success x + let ``~dp0`` = __SOURCE_DIRECTORY__ + let exec exe args = + log "%s %s" exe args + use toLog = redirectToLog () + Process.exec { RedirectError = Some toLog.Post; RedirectOutput = Some toLog.Post; RedirectInput = None } ``~dp0`` envVars exe args + + // set BINDIR=%~dp0..\%1\net40\bin + let! binDir = env "FSCBINPATH" + + // if /i "%PROCESSOR_ARCHITECTURE%"=="x86" set X86_PROGRAMFILES=%ProgramFiles% + // if /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" set X86_PROGRAMFILES=%ProgramFiles(x86)% + let processorArchitecture = WindowsPlatform.processorArchitecture envVars + let x86_ProgramFiles = WindowsPlatform.x86ProgramFilesDirectory envVars processorArchitecture + + let! windir = env "windir" + + let REGEXE32BIT path value = + let hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) + match hklm32 |> regQuery path value with + | Some (:? string as d) -> Some d + | Some _ | None -> None + + let allWINSDKNETFXTOOLS = seq { + // FOR /F "tokens=2* delims= " %%A IN ('%REGEXE32BIT% QUERY "HKLM\Software\Microsoft\Microsoft SDKs\NETFXSDK\4.6\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET WINSDKNETFXTOOLS=%%B + yield REGEXE32BIT @"Software\Microsoft\Microsoft SDKs\NETFXSDK\4.6\WinSDK-NetFx40Tools" "InstallationFolder" + // if "%WINSDKNETFXTOOLS%"=="" FOR /F "tokens=2* delims= " %%A IN ('%REGEXE32BIT% QUERY "HKLM\Software\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET WINSDKNETFXTOOLS=%%B + yield REGEXE32BIT @"Software\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools" "InstallationFolder" + // if "%WINSDKNETFXTOOLS%"=="" FOR /F "tokens=2* delims= " %%A IN ('%REGEXE32BIT% QUERY "HKLM\Software\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET WINSDKNETFXTOOLS=%%B + yield REGEXE32BIT @"Software\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools" "InstallationFolder" + // if "%WINSDKNETFXTOOLS%"=="" FOR /F "tokens=2* delims= " %%A IN ('%REGEXE32BIT% QUERY "HKLM\Software\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET WINSDKNETFXTOOLS=%%B + yield REGEXE32BIT @"Software\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools" "InstallationFolder" + // if "%WINSDKNETFXTOOLS%"=="" FOR /F "tokens=2* delims= " %%A IN ('%REGEXE32BIT% QUERY "HKLM\Software\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET WINSDKNETFXTOOLS=%%B + yield REGEXE32BIT @"Software\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools" "InstallationFolder" + } + + let WINSDKNETFXTOOLS = match allWINSDKNETFXTOOLS |> Seq.tryPick id with Some sdk -> sdk | None -> "" + + // set GACUTIL="%WINSDKNETFXTOOLS%gacutil.exe" + let GACUTIL = WINSDKNETFXTOOLS/"gacutil.exe" + // set SN32="%WINSDKNETFXTOOLS%sn.exe" + let SN32 = WINSDKNETFXTOOLS/"sn.exe" + // set SN64="%WINSDKNETFXTOOLS%x64\sn.exe" + let SN64 = WINSDKNETFXTOOLS/"x64"/"sn.exe" + // set NGEN32=%windir%\Microsoft.NET\Framework\v4.0.30319\ngen.exe + let NGEN32 = windir/"Microsoft.NET"/"Framework"/"v4.0.30319"/"ngen.exe" + // set NGEN64=%windir%\Microsoft.NET\Framework64\v4.0.30319\ngen.exe + let NGEN64 = windir/"Microsoft.NET"/"Framework64"/"v4.0.30319"/"ngen.exe" + + let checkResult = function CmdResult.ErrorLevel err -> Failure (sprintf "ERRORLEVEL %d" err) | CmdResult.Success -> Success () + + let gacutil flags = Commands.gacutil exec GACUTIL flags >> checkResult + let ngen32 = Commands.ngen exec NGEN32 >> checkResult + let ngen64 = Commands.ngen exec NGEN64 >> checkResult + let sn32 = exec SN32 >> checkResult + let sn64 = exec SN32 >> checkResult + + // rem Disable strong-name validation for F# binaries built from open source that are signed with the microsoft key + // %SN32% -Vr FSharp.Core,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.Build,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.Compiler.Interactive.Settings,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.Compiler.Hosted,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.Compiler,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.Compiler.Server.Shared,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.Editor,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.LanguageService,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.LanguageService.Base,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.LanguageService.Compiler,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.ProjectSystem.Base,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.ProjectSystem.FSharp,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.ProjectSystem.PropertyPages,b03f5f7f11d50a3a + // %SN32% -Vr FSharp.VS.FSI,b03f5f7f11d50a3a + // %SN32% -Vr Unittests,b03f5f7f11d50a3a + // %SN32% -Vr Salsa,b03f5f7f11d50a3a + + let strongName (snExe: string -> Result<_,_>) = processor { + let all = + [ "FSharp.Core"; + "FSharp.Build"; + "FSharp.Compiler.Interactive.Settings";"FSharp.Compiler.Hosted"; + "FSharp.Compiler";"FSharp.Compiler.Server.Shared"; + "FSharp.Editor"; + "FSharp.LanguageService";"FSharp.LanguageService.Base";"FSharp.LanguageService.Compiler"; + "FSharp.ProjectSystem.Base";"FSharp.ProjectSystem.FSharp";"FSharp.ProjectSystem.PropertyPages"; + "FSharp.VS.FSI"; + "Unittests"; + "Salsa" ] + for a in all do + do! snExe (sprintf " -Vr %s,b03f5f7f11d50a3a" a) + } + + do! strongName sn32 + + //if /i "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( + do! if processorArchitecture = AMD64 then + // %SN64% -Vr FSharp.Core,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.Build,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.Compiler.Interactive.Settings,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.Compiler.Hosted,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.Compiler,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.Compiler.Server.Shared,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.Editor,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.LanguageService,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.LanguageService.Base,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.LanguageService.Compiler,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.ProjectSystem.Base,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.ProjectSystem.FSharp,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.ProjectSystem.PropertyPages,b03f5f7f11d50a3a + // %SN64% -Vr FSharp.VS.FSI,b03f5f7f11d50a3a + // %SN64% -Vr Unittests,b03f5f7f11d50a3a + // %SN64% -Vr Salsa,b03f5f7f11d50a3a + strongName sn64 + else + (fun () -> Success ()) + //) + + // rem Only GACing FSharp.Core for now + // %GACUTIL% /if %BINDIR%\FSharp.Core.dll + do! gacutil "/if" (binDir/"FSharp.Core.dll") + + // rem NGen fsc, fsi, fsiAnyCpu, and FSharp.Build.dll + // if /i not "%2"=="-ngen" goto :donengen + + if args.Ngen then + // "%NGEN32%" install "%BINDIR%\fsc.exe" /queue:1 + // "%NGEN32%" install "%BINDIR%\fsi.exe" /queue:1 + // "%NGEN32%" install "%BINDIR%\FSharp.Build.dll" /queue:1 + // "%NGEN32%" executeQueuedItems 1 + do! ngen32 [binDir/"fsc.exe"; binDir/"fsi.exe"; binDir/"FSharp.Build.dll"] + + // if /i "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( + if processorArchitecture = AMD64 then + // "%NGEN64%" install "%BINDIR%\fsiAnyCpu.exe" /queue:1 + // "%NGEN64%" install "%BINDIR%\FSharp.Build.dll" /queue:1 + // "%NGEN64%" executeQueuedItems 1 + do! ngen64 [binDir/"fsiAnyCpu.exe"; binDir/"FSharp.Build.dll"] + // ) + //:donengen + + } diff --git a/tests/RunTests.cmd b/tests/RunTests.cmd index f098c3abc7f..d2ffda1675a 100644 --- a/tests/RunTests.cmd +++ b/tests/RunTests.cmd @@ -20,21 +20,35 @@ if not exist "%~dp0%..\packages\NUnit.Runners.2.6.4\tools\" ( rem "ttags" indicates what test areas will be run, based on the tags in the test.lst files set TTAGS_ARG= +SET TTAGS= set _tmp=%3 -if not '%_tmp%' == '' set TTAGS_ARG=-ttags:%_tmp:"=% +if not '%_tmp%' == '' ( + set TTAGS_ARG=-ttags:%_tmp:"=% + set TTAGS=%_tmp:"=% +) rem "nottags" indicates which test areas/test cases will NOT be run, based on the tags in the test.lst and env.lst files set NO_TTAGS_ARG=-nottags:ReqPP,NOOPEN +set NO_TTAGS=ReqPP,NOOPEN set _tmp=%4 -if not '%_tmp%' == '' set NO_TTAGS_ARG=-nottags:ReqPP,NOOPEN,%_tmp:"=% +if not '%_tmp%' == '' ( + set NO_TTAGS_ARG=-nottags:ReqPP,NOOPEN,%_tmp:"=% + set NO_TTAGS=ReqPP,NOOPEN,%_tmp:"=% +) -if /I "%APPVEYOR_CI%" == "1" (set NO_TTAGS_ARG=%NO_TTAGS_ARG%,NO_CI) +if /I "%APPVEYOR_CI%" == "1" ( + set NO_TTAGS_ARG=%NO_TTAGS_ARG%,NO_CI + set NO_TTAGS=%NO_TTAGS%,NO_CI +) set PARALLEL_ARG=-procs:%NUMBER_OF_PROCESSORS% rem This can be set to 1 to reduce the number of permutations used and avoid some of the extra-time-consuming tests -set REDUCED_RUNTIME=1 -if "%REDUCED_RUNTIME%" == "1" set NO_TTAGS_ARG=%NO_TTAGS_ARG%,Expensive +set REDUCED_RUNTIME=0 +if "%REDUCED_RUNTIME%" == "1" ( + set NO_TTAGS_ARG=%NO_TTAGS_ARG%,Expensive + set NO_TTAGS=%NO_TTAGS%,Expensive +) rem Set this to 1 in order to use an external compiler host process rem This only has an effect when running the FSHARPQA tests, but can @@ -89,6 +103,10 @@ exit /b 1 :FSHARP +if not '%FSHARP_TEST_SUITE_USE_NUNIT_RUNNER%' == '' ( + goto :FSHARP_NUNIT +) + set RESULTFILE=FSharp_Results.log set FAILFILE=FSharp_Failures.log set FAILENV=FSharp_Failures @@ -107,6 +125,32 @@ echo perl %~dp0\fsharpqa\testenv\bin\runall.pl -resultsroot %RESULTSDIR% -result goto :EOF +:FSHARP_NUNIT + +set FSHARP_TEST_SUITE_CONFIGURATION=%FLAVOR% + +set XMLFILE=%RESULTSDIR%\FSharpNunit_Xml.xml +set OUTPUTFILE=%RESULTSDIR%\FSharpNunit_Output.log +set ERRORFILE=%RESULTSDIR%\FSharpNunit_Error.log + +setlocal EnableDelayedExpansion + +set TTAGS_NUNIT_ARG= +if not '!TTAGS!' == '' (set TTAGS_NUNIT_ARG=--include="!TTAGS!") + +set NO_TTAGS_NUNIT_ARG= +if not '!NO_TTAGS!' == '' (set NO_TTAGS_NUNIT_ARG=--exclude="!NO_TTAGS!") + +SET NUNIT3_CONSOLE=%~dp0%..\packages\NUnit.Console.3.0.0-beta-3\tools\nunit-console.exe + +echo "%NUNIT3_CONSOLE%" "%FSCBINPATH%\..\..\net40\bin\FSharp.Tests.FSharp.dll" --framework:V4.0 !TTAGS_NUNIT_ARG! !NO_TTAGS_NUNIT_ARG! --work="%RESULTSDIR%" --output="%OUTPUTFILE%" --err="%ERRORFILE%" --result="%XMLFILE%" + +"%NUNIT3_CONSOLE%" "%FSCBINPATH%\..\..\net40\bin\FSharp.Tests.FSharp.dll" --framework:V4.0 !TTAGS_NUNIT_ARG! !NO_TTAGS_NUNIT_ARG! --work="%RESULTSDIR%" --output="%OUTPUTFILE%" --err="%ERRORFILE%" --result="%XMLFILE%" + + +goto :EOF + + :FSHARPQA set OSARCH=%PROCESSOR_ARCHITECTURE% diff --git a/tests/config.fs b/tests/config.fs new file mode 100644 index 00000000000..b606e677652 --- /dev/null +++ b/tests/config.fs @@ -0,0 +1,586 @@ +module TestConfig + +open System +open System.IO +open System.Collections.Generic +open Microsoft.Win32 + +open PlatformHelpers +open FSharpTestSuiteTypes + +let private fileExists = Commands.fileExists __SOURCE_DIRECTORY__ >> Option.isSome +let private directoryExists = Commands.directoryExists __SOURCE_DIRECTORY__ >> Option.isSome + +let private regQuery = WindowsPlatform.regQuery + +type private FSLibPaths = + { FSCOREDLLPATH : string + FSCOREDLL20PATH : string + FSCOREDLLPORTABLEPATH : string + FSCOREDLLNETCOREPATH : string + FSCOREDLLNETCORE78PATH : string + FSCOREDLLNETCORE259PATH : string + FSDATATPPATH : string + FSCOREDLLVPREVPATH : string } + + +let private checkResult result = + match result with + | CmdResult.ErrorLevel err -> let x = err, (sprintf "ERRORLEVEL %d" err) in Failure (RunError.ProcessExecError x) + | CmdResult.Success -> Success () + +// REM === +// REM === Find paths to shipped F# libraries referenced by clients +// REM === +let private GetFSLibPaths env osArch fscBinPath = + // REM == Find out OS architecture, no matter what cmd prompt + // SET OSARCH=%PROCESSOR_ARCHITECTURE% + // IF NOT "%PROCESSOR_ARCHITEW6432%"=="" SET OSARCH=%PROCESSOR_ARCHITEW6432% + ignore (osArch, "param") + + // REM == Find out path to native 'Program Files 32bit', no matter what + // REM == architecture we are running on and no matter what command + // REM == prompt we came from. + // IF /I "%OSARCH%"=="x86" set X86_PROGRAMFILES=%ProgramFiles% + // IF /I "%OSARCH%"=="IA64" set X86_PROGRAMFILES=%ProgramFiles(x86)% + // IF /I "%OSARCH%"=="AMD64" set X86_PROGRAMFILES=%ProgramFiles(x86)% + let X86_PROGRAMFILES = WindowsPlatform.x86ProgramFilesDirectory env osArch + + // REM == Default VS install locations + // set FSCOREDLLPATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.4.0.0 + let mutable FSCOREDLLPATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETFramework"/"v4.0"/"4.4.0.0" + // set FSCOREDLL20PATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETFramework\v2.0\2.3.0.0 + let mutable FSCOREDLL20PATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETFramework"/"v2.0"/"2.3.0.0" + // set FSCOREDLLPORTABLEPATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETPortable\3.47.4.0 + let mutable FSCOREDLLPORTABLEPATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETPortable"/"3.47.4.0" + // set FSCOREDLLNETCOREPATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETCore\3.7.4.0 + let mutable FSCOREDLLNETCOREPATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETCore"/"3.7.4.0" + // set FSCOREDLLNETCORE78PATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETCore\3.78.4.0 + let mutable FSCOREDLLNETCORE78PATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETCore"/"3.78.4.0" + // set FSCOREDLLNETCORE259PATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETCore\3.259.4.0 + let mutable FSCOREDLLNETCORE259PATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETCore"/"3.259.4.0" + // set FSDATATPPATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.3.0.0\Type Providers + let mutable FSDATATPPATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETFramework"/"v4.0"/"4.3.0.0"/"Type Providers" + // set FSCOREDLLVPREVPATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.3.1.0 + let mutable FSCOREDLLVPREVPATH = X86_PROGRAMFILES/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETFramework"/"v4.0"/"4.3.1.0" + + // REM == Check if using open build instead + + // IF EXIST "%FSCBinPath%\FSharp.Core.dll" set FSCOREDLLPATH=%FSCBinPath% + match fscBinPath with + | Some d when fileExists (d/"FSharp.Core.dll") -> FSCOREDLLPATH <- d + | Some _ | None -> () + + // IF EXIST "%FSCBinPath%\..\..\net20\bin\FSharp.Core.dll" set FSCOREDLL20PATH=%FSCBinPath%\..\..\net20\bin + match fscBinPath |> Option.map (fun d -> d/".."/".."/"net20"/"bin") with + | Some d when fileExists (d/"FSharp.Core.dll") -> FSCOREDLL20PATH <- d + | Some _ | None -> () + + // IF EXIST "%FSCBinPath%\..\..\portable47\bin\FSharp.Core.dll" set FSCOREDLLPORTABLEPATH=%FSCBinPath%\..\..\portable47\bin + match fscBinPath |> Option.map (fun d -> d/".."/".."/"portable47"/"bin") with + | Some d when fileExists (d/"FSharp.Core.dll") -> FSCOREDLLPORTABLEPATH <- d + | Some _ | None -> () + + // IF EXIST "%FSCBinPath%\..\..\portable7\bin\FSharp.Core.dll" set FSCOREDLLNETCOREPATH=%FSCBinPath%\..\..\portable7\bin + match fscBinPath |> Option.map (fun d -> d/".."/".."/"portable7"/"bin") with + | Some d when fileExists (d/"FSharp.Core.dll") -> FSCOREDLLNETCOREPATH <- d + | Some _ | None -> () + + // IF EXIST "%FSCBinPath%\..\..\portable78\bin\FSharp.Core.dll" set FSCOREDLLNETCORE78PATH=%FSCBinPath%\..\..\portable78\bin + match fscBinPath |> Option.map (fun d -> d/".."/".."/"portable78"/"bin") with + | Some d when fileExists (d/"FSharp.Core.dll") -> FSCOREDLLNETCORE78PATH <- d + | Some _ | None -> () + + // IF EXIST "%FSCBinPath%\..\..\portable259\bin\FSharp.Core.dll" set FSCOREDLLNETCORE259PATH=%FSCBinPath%\..\..\portable259\bin + match fscBinPath |> Option.map (fun d -> d/".."/".."/"portable259"/"bin") with + | Some d when fileExists (d/"FSharp.Core.dll") -> FSCOREDLLNETCORE259PATH <- d + | Some _ | None -> () + + // IF EXIST "%FSCBinPath%\FSharp.Data.TypeProviders.dll" set FSDATATPPATH=%FSCBinPath% + match fscBinPath with + | Some d when fileExists (d/"FSharp.Data.TypeProviders.dll") -> FSDATATPPATH <- d + | Some _ | None -> () + + // set FSCOREDLLPATH=%FSCOREDLLPATH%\FSharp.Core.dll + FSCOREDLLPATH <- FSCOREDLLPATH/"FSharp.Core.dll" + // set FSCOREDLL20PATH=%FSCOREDLL20PATH%\FSharp.Core.dll + FSCOREDLL20PATH <- FSCOREDLL20PATH/"FSharp.Core.dll" + // set FSCOREDLLPORTABLEPATH=%FSCOREDLLPORTABLEPATH%\FSharp.Core.dll + FSCOREDLLPORTABLEPATH <- FSCOREDLLPORTABLEPATH/"FSharp.Core.dll" + // set FSCOREDLLNETCOREPATH=%FSCOREDLLNETCOREPATH%\FSharp.Core.dll + FSCOREDLLNETCOREPATH <- FSCOREDLLNETCOREPATH/"FSharp.Core.dll" + // set FSCOREDLLNETCORE78PATH=%FSCOREDLLNETCORE78PATH%\FSharp.Core.dll + FSCOREDLLNETCORE78PATH <- FSCOREDLLNETCORE78PATH/"FSharp.Core.dll" + // set FSCOREDLLNETCORE259PATH=%FSCOREDLLNETCORE259PATH%\FSharp.Core.dll + FSCOREDLLNETCORE259PATH <- FSCOREDLLNETCORE259PATH/"FSharp.Core.dll" + // set FSDATATPPATH=%FSDATATPPATH%\FSharp.Data.TypeProviders.dll + FSDATATPPATH <- FSDATATPPATH/"FSharp.Data.TypeProviders.dll" + // set FSCOREDLLVPREVPATH=%FSCOREDLLVPREVPATH%\FSharp.Core.dll + FSCOREDLLVPREVPATH <- FSCOREDLLVPREVPATH/"FSharp.Core.dll" + + X86_PROGRAMFILES, { + FSCOREDLLPATH = FSCOREDLLPATH; + FSCOREDLL20PATH = FSCOREDLL20PATH; + FSCOREDLLPORTABLEPATH = FSCOREDLLPORTABLEPATH; + FSCOREDLLNETCOREPATH = FSCOREDLLNETCOREPATH; + FSCOREDLLNETCORE78PATH = FSCOREDLLNETCORE78PATH; + FSCOREDLLNETCORE259PATH = FSCOREDLLNETCORE259PATH; + FSDATATPPATH = FSDATATPPATH; + FSCOREDLLVPREVPATH = FSCOREDLLVPREVPATH } + +// REM === +// REM === Find path to FSC/FSI looking up the registry +// REM === Will set the FSCBinPath env variable. +// REM === This if for Dev11+/NDP4.5 +// REM === Works on both XP and Vista and hopefully everything else +// REM === Works on 32bit and 64 bit, no matter what cmd prompt it is invoked from +// REM === +let private SetFSCBinPath45 () = + // FOR /F "tokens=1-2*" %%a IN ('reg query "%REG_SOFTWARE%\Microsoft\FSharp\4.0\Runtime\v4.0" /ve') DO set FSCBinPath=%%c + // FOR /F "tokens=1-3*" %%a IN ('reg query "%REG_SOFTWARE%\Microsoft\FSharp\4.0\Runtime\v4.0" /ve') DO set FSCBinPath=%%d + // IF EXIST "%FSCBinPath%" goto :EOF + let hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) + match hklm32 |> regQuery @"SOFTWARE\Microsoft\FSharp\4.0\Runtime\v4.0" "" with + | Some (:? string as d) when directoryExists d -> Some d + | Some _ | None -> None + +let private attendedLog envVars x86_ProgramFiles corDir corDir40 = + let getMsbuildPath = + // rem first see if we have got msbuild installed + let mutable MSBuildToolsPath = envVars |> Map.tryFind "MSBuildToolsPath" + + // if exist "%X86_PROGRAMFILES%\MSBuild\14.0\Bin\MSBuild.exe" SET MSBuildToolsPath=%X86_PROGRAMFILES%\MSBuild\14.0\Bin\ + if x86_ProgramFiles/"MSBuild"/"14.0"/"Bin"/"MSBuild.exe" |> fileExists + then MSBuildToolsPath <- Some (x86_ProgramFiles/"MSBuild"/"14.0"/"Bin" |> Commands.pathAddBackslash) + // if not "%MSBuildToolsPath%" == "" goto done_MsBuildToolsPath + match MSBuildToolsPath with + | Some x -> Some x + | None -> + let mutable MSBuildToolsPath = None + // IF NOT "%CORDIR%"=="" IF EXIST "%CORDIR%\msbuild.exe" SET MSBuildToolsPath=%CORDIR% + if not (corDir = "") then + if corDir/"msbuild.exe" |> fileExists + then MSBuildToolsPath <- Some corDir + // IF "%CORDIR40%"=="" IF NOT "%CORDIR%"=="" IF EXIST "%CORDIR%\..\V3.5\msbuild.exe" SET MSBuildToolsPath="%CORDIR%\..\V3.5\" + if (corDir40 |> Option.isNone) then + if (not (corDir = "")) then + if corDir/".."/"V3.5"/"msbuild.exe" |> fileExists + then MSBuildToolsPath <- Some (corDir/".."/"V3.5") + + // IF NOT "%CORDIR%"=="" FOR /f %%j IN ("%MSBuildToolsPath%") do SET MSBuildToolsPath=%%~fj + if (not (corDir = "")) + then MSBuildToolsPath <- (MSBuildToolsPath |> Option.map Path.GetFullPath) + MSBuildToolsPath + // :done_MsBuildToolsPath + + // exit /b 0 + getMsbuildPath, (WindowsPlatform.visualStudioVersion ()) + + +let config envVars = + // set _SCRIPT_DRIVE=%~d0 + ignore "unused" + // set _SCRIPT_PATH=%~p0 + ignore "unused" + // set SCRIPT_ROOT=%_SCRIPT_DRIVE%%_SCRIPT_PATH% + let SCRIPT_ROOT = __SOURCE_DIRECTORY__ |> Path.GetFullPath + + let env key = envVars |> Map.tryFind key + let envOrDefault key def = env key |> Option.fold (fun s t -> t) def + let envOrFail key = env key |> function Some x -> x | None -> failwithf "environment variable '%s' required " key + let where = Commands.where envVars + + let PROCESSOR_ARCHITECTURE = WindowsPlatform.processorArchitecture envVars + // set REG_SOFTWARE=HKLM\SOFTWARE + // IF /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" (set REG_SOFTWARE=%REG_SOFTWARE%\Wow6432Node) + ignore "unused, using .net bcl to query RegistryView.Registry32" + + // if not defined FSHARP_HOME set FSHARP_HOME=%SCRIPT_ROOT%..\.. + // for /f %%i in ("%FSHARP_HOME%") do set FSHARP_HOME=%%~fi + let FSHARP_HOME = + envOrDefault "FSHARP_HOME" (SCRIPT_ROOT/".."/"..") + |> Path.GetFullPath + + // REM Do we know where fsc.exe is? + // IF DEFINED FSCBinPath goto :FSCBinPathFound + // FOR /F "delims=" %%i IN ('where fsc.exe') DO SET FSCBinPath=%%~dpi + // :FSCBinPathFound + let mutable FSCBinPath = + match env "FSCBINPATH" with + | Some p -> Some p + | None -> where "fsc.exe" |> Option.map Path.GetDirectoryName + + // SET CLIFLAVOUR=cli\4.5 + let CLIFLAVOUR = @"cli\4.5" + + // if not exist "%FSCBinPath%\fsc.exe" call :SetFSCBinPath45 + if not (FSCBinPath |> Option.map (fun dir -> dir/"fsc.exe") |> Option.exists fileExists) + then FSCBinPath <- SetFSCBinPath45 () + + // if not exist "%FSCBinPath%\fsc.exe" echo %FSCBinPath%\fsc.exe still not found. Assume that user has added it to path somewhere + ignore "smoke test check fsc.exe" + + // REM add %FSCBinPath% to path only if not already there. Otherwise, the path keeps growing. + // echo %path%; | find /i "%FSCBinPath%;" > NUL + // if ERRORLEVEL 1 set PATH=%PATH%;%FSCBinPath% + //REVIEW add it? or better use only env var? + + // if "%FSDIFF%"=="" set FSDIFF=%SCRIPT_ROOT%fsharpqa\testenv\bin\diff.exe + let FSDIFF = envOrDefault "FSDIFF" (SCRIPT_ROOT/"fsharpqa"/"testenv"/"bin"/"diff.exe") + // if not exist "%FSDIFF%" echo FSDIFF not found at expected path of %fsdiff% && exit /b 1 + ignore "check exists diff.exe" + + // rem check if we're already configured, if not use the configuration from the last line of the config file + // if "%fsc%"=="" ( + // set csc_flags=/nologo + // set fsiroot=fsi + // ) + let mutable FSC = env "fsc" + let csc_flags = + match FSC with None -> "/nologo" | Some _ -> (envOrDefault "csc_flags" "/nologo") + let mutable fsiroot = + match FSC with None -> Some "fsi" | Some _ -> (env "fsiroot") + + // if not defined ALINK set ALINK=al.exe + let mutable ALINK = (envOrDefault "ALINK" "al.exe") + // if not defined CSC set CSC=csc.exe %csc_flags% + let CSC = envOrDefault "CSC" "csc.exe" + + // REM SDK Dependencires. + // if not defined ILDASM set ILDASM=ildasm.exe + let mutable ILDASM = envOrDefault "ILDASM" "ildasm.exe" + // if not defined GACUTIL set GACUTIL=gacutil.exe + let mutable GACUTIL = envOrDefault "GACUTIL" "gacutil.exe" + // if not defined PEVERIFY set PEVERIFY=peverify.exe + let mutable PEVERIFY = envOrDefault "PEVERIFY" "peverify.exe" + // if not defined RESGEN set RESGEN=resgen.exe + let mutable RESGEN = envOrDefault "RESGEN" "resgen.exe" + + // if "%fsiroot%" == "" ( set fsiroot=fsi) + if fsiroot |> Option.isNone + then fsiroot <- Some "fsi" + + // REM == Test strategy: if we are on a 32bit OS => use fsi.exe + // REM == if we are on a 64bit OS => use fsiAnyCPU.exe + // REM == This way we get coverage of both binaries without having to + // REM == double the test matrix. Note that our nightly automation + // REM == always cover x86 and x64... so we won't miss much. There + // REM == is an implicit assumption that the CLR will do it's job + // REM == to make an FSIAnyCPU.exe behave as FSI.exe on a 32bit OS. + // REM == On 64 bit machines ensure that we run the 64 bit versions of tests too. + + // SET OSARCH=%PROCESSOR_ARCHITECTURE% + // IF NOT "%PROCESSOR_ARCHITEW6432%"=="" SET OSARCH=%PROCESSOR_ARCHITEW6432% + let OSARCH = WindowsPlatform.osArch envVars + + // IF "%fsiroot%"=="fsi" IF NOT "%OSARCH%"=="x86" ( + // SET fsiroot=fsiAnyCPU + // set FSC_BASIC_64=FSC_BASIC_64 + // ) + let mutable FSC_BASIC_64 = env "FSC_BASIC_64" + match fsiroot, OSARCH with + | Some "fsi", X86 -> () + | Some "fsi", arc -> + fsiroot <- Some "fsiAnyCPU" + FSC_BASIC_64 <- Some "FSC_BASIC_64" + | _ -> () + + + // REM --------------------------------------------------------------- + // REM If we set a "--cli-version" flag anywhere in the flags then assume its v1.x + // REM and generate a config file, so we end up running the test on the right version + // REM of the CLR. Also modify the CORSDK used. + // REM + // REM Use CLR 1.1 at a minimum since 1.0 is not installed on most of my machines + // REM otherwise assume v2.0 + // REM TODO: we need to update this to be v2.0 or v3.5 and nothing else. + + // set fsc_flags=%fsc_flags% + let mutable fsc_flags = env "fsc_flags" + + // set CLR_SUPPORTS_GENERICS=true + let CLR_SUPPORTS_GENERICS = true + // set ILDASM=%ILDASM% + ignore "env var not needed, ildasm is invoked with Commands.ildasm" + // set GACUTIL=%GACUTIL% + ignore "env var not needed, gacutil is invoked with Commads.gacutil" + // set CLR_SUPPORTS_WINFORMS=true + let CLR_SUPPORTS_WINFORMS = true + // set CLR_SUPPORTS_SYSTEM_WEB=true + let CLR_SUPPORTS_SYSTEM_WEB = true + + // REM == + // REM == F# v1.0 targets NetFx3.5 (i.e. NDP2.0) + // REM == It is ok to hardcode the location, since this is not going to + // REM == change ever. Well, if/when we target a different runtime we'll have + // REM == to come and update this, but for now we MUST make sure we use the 2.0 stuff. + // REM == + // REM == If we run on a 64bit machine (from a 64bit command prompt!), we use the 64bit + // REM == CLR, but tweaking 'Framework' to 'Framework64'. + // REM == + // set CORDIR=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\ + let SystemRoot = envOrFail "SystemRoot" + let mutable CORDIR = SystemRoot/"Microsoft.NET"/"Framework"/"v2.0.50727" |> Commands.pathAddBackslash + // set CORDIR40= + // FOR /D %%i IN (%windir%\Microsoft.NET\Framework\v4.0.?????) do set CORDIR40=%%i + let windir = envOrFail "windir" + let CORDIR40 = + match Directory.EnumerateDirectories (windir/"Microsoft.NET"/"Framework", "v4.0.?????") |> List.ofSeq |> List.rev with + | x :: _ -> Some x + | [] -> None + // IF NOT "%CORDIR40%"=="" set CORDIR=%CORDIR40% + match CORDIR40 with + | None -> () + | Some d -> CORDIR <- d + + // REM == Use the same runtime as our architecture + // REM == ASSUMPTION: This could be a good or bad thing. + // IF /I NOT "%PROCESSOR_ARCHITECTURE%"=="x86" set CORDIR=%CORDIR:Framework=Framework64% + match PROCESSOR_ARCHITECTURE with + | X86 -> () + | _ -> CORDIR <- CORDIR.Replace("Framework", "Framework64") + + + + let regQueryREG_SOFTWARE path value = + let hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) + match hklm32 |> regQuery path value with + | Some (:? string as d) -> Some d + | Some _ | None -> None + + let allSDK = seq { + // FOR /F "tokens=2* delims= " %%A IN ('reg QUERY "%REG_SOFTWARE%\Microsoft\Microsoft SDKs\NETFXSDK\4.6\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET CORSDK=%%B + yield regQueryREG_SOFTWARE @"Software\Microsoft\Microsoft SDKs\NETFXSDK\4.6\WinSDK-NetFx40Tools" "InstallationFolder"; + // if "%CORSDK%"=="" FOR /F "tokens=2* delims= " %%A IN ('reg QUERY "%REG_SOFTWARE%\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET CORSDK=%%B + yield regQueryREG_SOFTWARE @"Software\Microsoft\Microsoft SDKs\Windows\v8.1A\WinSDK-NetFx40Tools" "InstallationFolder"; + // if "%CORSDK%"=="" FOR /F "tokens=2* delims= " %%A IN ('reg QUERY "%REG_SOFTWARE%\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET CORSDK=%%B + yield regQueryREG_SOFTWARE @"Software\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools" "InstallationFolder"; + // if "%CORSDK%"=="" FOR /F "tokens=2* delims= " %%A IN ('reg QUERY "%REG_SOFTWARE%\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET CORSDK=%%B + yield regQueryREG_SOFTWARE @"Software\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools" "InstallationFolder"; + // if "%CORSDK%"=="" FOR /F "tokens=2* delims= " %%A IN ('reg QUERY "%REG_SOFTWARE%\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools" /v InstallationFolder') DO SET CORSDK=%%B + yield regQueryREG_SOFTWARE @"Software\Microsoft\Microsoft SDKs\Windows\v7.0A\WinSDK-NetFx40Tools" "InstallationFolder"; + } + + let mutable CORSDK = allSDK |> Seq.tryPick id + + // REM == Fix up CORSDK for 64bit platforms... + // IF /I "%PROCESSOR_ARCHITECTURE%"=="AMD64" SET CORSDK=%CORSDK%\x64 + // IF /I "%PROCESSOR_ARCHITECTURE%"=="IA64" SET CORSDK=%CORSDK%\IA64 + match PROCESSOR_ARCHITECTURE with + | AMD64 -> CORSDK <- CORSDK |> Option.map (fun dir -> dir/"x64") + | IA64 -> CORSDK <- CORSDK |> Option.map (fun dir -> dir/"IA64") + | _ -> () + + // REM add powerpack to flags only if not already there. Otherwise, the variable can keep growing. + // echo %fsc_flags% | find /i "powerpack" + // if ERRORLEVEL 1 set fsc_flags=%fsc_flags% -r:System.Core.dll --nowarn:20 + if fsc_flags |> Option.exists (fun flags -> flags.ToLower().Contains("powerpack")) then () + else fsc_flags <- Some (sprintf "%s -r:System.Core.dll --nowarn:20" (fsc_flags |> Option.fold (fun s t -> t) "")) + + // if not defined fsi_flags set fsi_flags=%fsc_flags:--define:COMPILED=% --define:INTERACTIVE --maxerrors:1 --abortonerror + let mutable fsi_flags = env "fsi_flags" + if fsi_flags |> Option.isNone then ( + let fsc_flags_no_compiled = fsc_flags |> Option.fold (fun s flags -> flags.Replace("--define:COMPILED", "")) "" + fsi_flags <- Some (sprintf "%s --define:INTERACTIVE --maxerrors:1 --abortonerror" fsc_flags_no_compiled) + ) + + // echo %fsc_flags%; | find "--define:COMPILED" > NUL || ( + // set fsc_flags=%fsc_flags% --define:COMPILED + // ) + if not (fsc_flags |> Option.exists (fun flags -> flags.Contains("--define:COMPILED"))) + then fsc_flags <- Some (sprintf "%s --define:COMPILED" (fsc_flags |> Option.fold (fun s t -> t) "")) + + // if NOT "%fsc_flags:generate-config-file=X%"=="%fsc_flags%" ( + // if NOT "%fsc_flags:clr-root=X%"=="%fsc_flags%" ( + // set fsc_flags=%fsc_flags% --clr-root:%CORDIR% + // ) + // ) + // --clr-root non e' un flag valido di fsc + // if not <| (fsc_flags |> Option.exists (fun flags -> flags.Contains("generate-config-file"))) then + // if not <| (fsc_flags |> Option.exists (fun flags -> flags.Contains("clr-root"))) then + // fsc_flags <- Some (sprintf "%s --clr-root:%s" (fsc_flags |> Option.fold (fun s t -> t) "") (!CORDIR)) + + // if "%CORDIR%"=="unknown" set CORDIR= + if CORDIR = "unknown" then CORDIR <- "" + + // REM use short names in the path so you don't have to deal with the space in things like "Program Files" + // for /f "delims=" %%I in ("%CORSDK%") do set CORSDK=%%~dfsI% + CORSDK <- CORSDK |> Option.map Commands.convertToShortPath + + // for /f "delims=" %%I in ("%CORDIR%") do set CORDIR=%%~dfsI% + CORDIR <- Commands.convertToShortPath CORDIR + + + // set NGEN= + let mutable NGEN = None + + // REM == + // REM == Set path to C# compiler. If we are NOT on NetFx4.0, try we prefer C# 3.5 to C# 2.0 + // REM == This is because we have tests that reference System.Core.dll from C# code! + // REM == (e.g. fsharp\core\fsfromcs) + // REM == + // IF NOT "%CORDIR%"=="" IF EXIST "%CORDIR%\csc.exe" SET CSC="%CORDIR%\csc.exe" %csc_flags% + let mutable CSC = None + if not (CORDIR = "") then + if CORDIR/"csc.exe" |> fileExists + then CSC <- Some (CORDIR/"csc.exe") + + // IF "%CORDIR40%"=="" IF NOT "%CORDIR%"=="" IF EXIST "%CORDIR%\..\V3.5\csc.exe" SET CSC="%CORDIR%\..\v3.5\csc.exe" %csc_flags% + if CORDIR40 |> Option.isNone then + if not (CORDIR = "") then + if CORDIR/".."/"V3.5"/"csc.exe" |> fileExists + then CSC <- Some (CORDIR/".."/"V3.5"/"csc.exe") + + // IF NOT "%CORDIR%"=="" IF EXIST "%CORDIR%\ngen.exe" SET NGEN=%CORDIR%\ngen.exe + if not (CORDIR = "") then + if CORDIR/"ngen.exe" |> fileExists + then NGEN <- Some (CORDIR/"ngen.exe") + + // IF NOT "%CORDIR%"=="" IF EXIST "%CORDIR%\al.exe" SET ALINK=%CORDIR%\al.exe + if not (CORDIR = "") then + if CORDIR/"al.exe" |> fileExists + then ALINK <- CORDIR/"al.exe" + + // REM == + // REM == The logic here is: pick the latest msbuild + // REM == If we are testing against NDP4.0, then don't try msbuild 3.5 + // REM == + + // IF NOT "%CORSDK%"=="" IF EXIST "%CORSDK%\ildasm.exe" SET ILDASM=%CORSDK%\ildasm.exe + match CORSDK |> Option.map (fun d -> d/"ildasm.exe") with + | Some p when fileExists p -> ILDASM <- p + | Some _ | None -> () + + // IF NOT "%CORSDK%"=="" IF EXIST "%CORSDK%\gacutil.exe" SET GACUTIL=%CORSDK%\gacutil.exe + match CORSDK |> Option.map (fun d -> d/"gacutil.exe") with + | Some p when fileExists p -> GACUTIL <- p + | Some _ | None -> () + + // IF NOT "%CORSDK%"=="" IF EXIST "%CORSDK%\peverify.exe" SET PEVERIFY=%CORSDK%\peverify.exe + match CORSDK |> Option.map (fun d -> d/"peverify.exe") with + | Some p when fileExists p -> PEVERIFY <- p + | Some _ | None -> () + + // IF NOT "%CORSDK%"=="" IF EXIST "%CORSDK%\resgen.exe" SET RESGEN=%CORSDK%\resgen.exe + // IF NOT "%CORSDK%"=="" IF NOT EXIST "%RESGEN%" IF EXIST "%CORSDK%\..\resgen.exe" SET RESGEN=%CORSDK%\..\resgen.exe + match CORSDK with + | Some sdk -> + if sdk/"resgen.exe" |> fileExists + then RESGEN <- sdk/"resgen.exe" + elif sdk/".."/"resgen.exe" |> fileExists + then RESGEN <- sdk/".."/"resgen.exe" + | None -> () + + // IF NOT "%CORSDK%"=="" IF EXIST "%CORSDK%\al.exe" SET ALINK=%CORSDK%\al.exe + match CORSDK |> Option.map (fun d -> d/"al.exe") with + | Some p when fileExists p -> ALINK <- p + | Some _ | None -> () + + // IF NOT DEFINED FSC SET FSC=fsc.exe + let mutable FSC = envOrDefault "FSC" "fsc.exe" + // IF NOT DEFINED FSI SET FSI=%fsiroot%.exe + let mutable FSI = envOrDefault "FSI" (fsiroot |> Option.fold (+) ".exe") + + // IF DEFINED FSCBinPath IF EXIST "%FSCBinPath%\fsc.exe" SET FSC=%FSCBinPath%\fsc.exe + match FSCBinPath |> Option.map (fun d -> d/"fsc.exe") with + | Some fscExe when fileExists fscExe -> FSC <- fscExe + | Some _ | None -> () + + // IF DEFINED FSCBinPath IF EXIST "%FSCBinPath%\%fsiroot%.exe" SET FSI=%FSCBinPath%\%fsiroot%.exe + match FSCBinPath, fsiroot with + | Some dir, Some fsiExe when fileExists (dir/(fsiExe+".exe")) -> FSI <- dir/(fsiExe+".exe") + | _ -> () + + // REM == Located F# library DLLs in either open or Visual Studio contexts + // call :GetFSLibPaths + let X86_PROGRAMFILES, libs = GetFSLibPaths envVars OSARCH FSCBinPath + + // REM == Set standard flags for invoking powershell scripts + // IF NOT DEFINED PSH_FLAGS SET PSH_FLAGS=-nologo -noprofile -executionpolicy bypass + let PSH_FLAGS = envOrDefault "PSH_FLAGS" "-nologo -noprofile -executionpolicy bypass" + ignore "unused, cross platform requirement and powershell is not used in tests" + + //add to environment variables, only if needed (an example is ILDASM, cfg.ILDASM should be used instead inside tests) + let environment = + envVars + |> Map.add "CLR_SUPPORTS_GENERICS" (sprintf "%A" CLR_SUPPORTS_GENERICS) + |> Map.add "CLR_SUPPORTS_WINFORMS" (sprintf "%A" CLR_SUPPORTS_WINFORMS) + |> Map.add "CLR_SUPPORTS_SYSTEM_WEB" (sprintf "%A" CLR_SUPPORTS_SYSTEM_WEB) + + let orBlank = Option.fold (fun _ x -> x) "" + + let cfg = { + EnvironmentVariables = environment; + ALINK = ALINK; + CORDIR = CORDIR |> Commands.pathAddBackslash; + CORSDK = CORSDK |> orBlank |> Commands.pathAddBackslash; + FSCBinPath = FSCBinPath |> orBlank |> Commands.pathAddBackslash; + FSCOREDLL20PATH = libs.FSCOREDLL20PATH; + FSCOREDLLPATH = libs.FSCOREDLLPATH; + FSCOREDLLPORTABLEPATH = libs.FSCOREDLLPORTABLEPATH; + FSCOREDLLNETCOREPATH = libs.FSCOREDLLNETCOREPATH; + FSCOREDLLNETCORE78PATH = libs.FSCOREDLLNETCORE78PATH; + FSCOREDLLNETCORE259PATH = libs.FSCOREDLLNETCORE259PATH; + FSDATATPPATH = libs.FSDATATPPATH; + FSCOREDLLVPREVPATH = libs.FSCOREDLLVPREVPATH; + FSDIFF = FSDIFF; + GACUTIL = GACUTIL; + ILDASM = ILDASM; + INSTALL_SKU = None; + MSBUILDTOOLSPATH = None; + MSBUILD = None; + NGEN = NGEN |> orBlank; + PEVERIFY = PEVERIFY; + RESGEN = RESGEN; + CSC = CSC |> orBlank; + FSC = FSC; + FSI = FSI; + csc_flags = csc_flags; + fsc_flags = fsc_flags |> orBlank; + fsi_flags = fsi_flags |> orBlank; + } + + // if DEFINED _UNATTENDEDLOG exit /b 0 + match env "_UNATTENDEDLOG" with + | Some _ -> cfg + | None -> + let msbuildToolsPath, installSku = attendedLog envVars X86_PROGRAMFILES CORDIR CORDIR40 + { cfg with + MSBUILDTOOLSPATH = msbuildToolsPath |> Option.map (Commands.pathAddBackslash); + MSBUILD = msbuildToolsPath |> Option.map (fun d -> d/"msbuild.exe"); + INSTALL_SKU = installSku } + + + +let logConfig (cfg: TestConfig) = + log "---------------------------------------------------------------" + log "Executables" + log "" + log "ALINK =%s" cfg.ALINK + log "CORDIR =%s" cfg.CORDIR + log "CORSDK =%s" cfg.CORSDK + log "CSC =%s" cfg.CSC + log "csc_flags =%s" cfg.csc_flags + log "FSC =%s" cfg.FSC + log "fsc_flags =%s" cfg.fsc_flags + log "FSCBINPATH =%s" cfg.FSCBinPath + log "FSCOREDLL20PATH =%s" cfg.FSCOREDLL20PATH + log "FSCOREDLLPATH =%s" cfg.FSCOREDLLPATH + log "FSCOREDLLPORTABLEPATH =%s" cfg.FSCOREDLLPORTABLEPATH + log "FSCOREDLLNETCOREPATH=%s" cfg.FSCOREDLLNETCOREPATH + log "FSCOREDLLNETCORE78PATH=%s" cfg.FSCOREDLLNETCORE78PATH + log "FSCOREDLLNETCORE259PATH=%s" cfg.FSCOREDLLNETCORE259PATH + log "FSCOREDLLVPREVPATH=%s" cfg.FSCOREDLLVPREVPATH + log "FSDATATPPATH =%s" cfg.FSDATATPPATH + log "FSDIFF =%s" cfg.FSDIFF + log "FSI =%s" cfg.FSI + log "fsi_flags =%s" cfg.fsi_flags + log "GACUTIL =%s" cfg.GACUTIL + log "ILDASM =%s" cfg.ILDASM + log "INSTALL_SKU =%A" cfg.INSTALL_SKU + log "MSBUILDTOOLSPATH =%A" cfg.MSBUILDTOOLSPATH + log "MSBUILD =%A" cfg.MSBUILD + log "NGEN =%s" cfg.NGEN + log "PEVERIFY =%s" cfg.PEVERIFY + log "RESGEN =%s" cfg.RESGEN + log "---------------------------------------------------------------" diff --git a/tests/fsharp/Commands.fs b/tests/fsharp/Commands.fs new file mode 100644 index 00000000000..6cd77821bd0 --- /dev/null +++ b/tests/fsharp/Commands.fs @@ -0,0 +1,160 @@ +[] +module Commands + +open System +open System.IO + +open PlatformHelpers + +let getfullpath workDir path = + let rooted = + if Path.IsPathRooted(path) then path + else Path.Combine(workDir, path) + rooted |> Path.GetFullPath + +let fileExists workDir path = + if path |> getfullpath workDir |> File.Exists then Some path else None + +let directoryExists workDir path = + if path |> getfullpath workDir |> Directory.Exists then Some path else None + +/// copy /y %source1% tmptest2.ml +let copy_y workDir source to' = + log "copy /y %s %s" source to' + File.Copy( source |> getfullpath workDir, to' |> getfullpath workDir, true) + CmdResult.Success + +/// mkdir orig +let mkdir_p workDir dir = + log "mkdir %s" dir + Directory.CreateDirectory ( Path.Combine(workDir, dir) ) |> ignore + +/// del test.txt +let rm dir path = + log "rm %s" path + let p = path |> getfullpath dir + if File.Exists(p) then File.Delete(p) + +let pathAddBackslash (p: FilePath) = + if String.IsNullOrWhiteSpace (p) + then p + else + p.TrimEnd ([| Path.DirectorySeparatorChar; Path.AltDirectorySeparatorChar |]) + + Path.DirectorySeparatorChar.ToString() + +// echo. > build.ok +let ``echo._tofile`` workDir text p = + log "echo.%s> %s" text p + let to' = p |> getfullpath workDir in File.WriteAllText(to', text + Environment.NewLine) + +/// echo // empty file > tmptest2.mli +let echo_tofile workDir text p = + log "echo %s> %s" text p + let to' = p |> getfullpath workDir in File.WriteAllText(to', text + Environment.NewLine) + +/// echo // empty file >> tmptest2.mli +let echo_append_tofile workDir text p = + log "echo %s> %s" text p + let to' = p |> getfullpath workDir in File.AppendAllText(to', text + Environment.NewLine) + +/// type %source1% >> tmptest3.ml +let type_append_tofile workDir source p = + log "type %s >> %s" source p + let from = source |> getfullpath workDir + let to' = p |> getfullpath workDir + let contents = File.ReadAllText(from) + File.AppendAllText(to', contents) + +// %GACUTIL% /if %BINDIR%\FSharp.Core.dll +let gacutil exec exeName flags assembly = + exec exeName (sprintf """%s "%s" """ flags assembly) + +// "%NGEN32%" install "%BINDIR%\fsc.exe" /queue:1 +// "%NGEN32%" install "%BINDIR%\fsi.exe" /queue:1 +// "%NGEN32%" install "%BINDIR%\FSharp.Build.dll" /queue:1 +// "%NGEN32%" executeQueuedItems 1 +let ngen exec (ngenExe: FilePath) assemblies = + let queue = assemblies |> List.map (fun a -> (sprintf "install \"%s\" /queue:1" a)) + + List.concat [ queue; ["executeQueuedItems 1"] ] + |> Seq.ofList + |> Seq.map (fun args -> exec ngenExe args) + |> Seq.takeWhile (function ErrorLevel _ -> false | Ok -> true) + |> Seq.last + +let fsc exec (fscExe: FilePath) flags srcFiles = + // "%FSC%" %fsc_flags% --define:COMPILING_WITH_EMPTY_SIGNATURE -o:tmptest2.exe tmptest2.mli tmptest2.ml + exec fscExe (sprintf "%s %s" flags (srcFiles |> Seq.ofList |> String.concat " ")) + +let csc exec cscExe flags srcFiles = + exec cscExe (sprintf "%s %s" flags (srcFiles |> Seq.ofList |> String.concat " ")) + +let fsi exec fsiExe flags sources = + exec fsiExe (sprintf "%s %s" flags (sources |> Seq.ofList |> String.concat " ")) + +// "%MSBUILDTOOLSPATH%\msbuild.exe" PCL.fsproj +let msbuild exec msbuildExe flags srcFiles = + exec msbuildExe (sprintf "%s %s" flags (srcFiles |> Seq.ofList |> String.concat " ")) + +// "%RESGEN%" /compile Resources.resx +let resgen exec resgenExe flags sources = + exec resgenExe (sprintf "%s %s" flags (sources |> Seq.ofList |> String.concat " ")) + +let internal quotepath (p: FilePath) = + let quote = '"'.ToString() + if p.Contains(" ") + then (sprintf "%s%s%s" quote p quote) + else p + +let ildasm exec ildasmExe flags assembly = + exec ildasmExe (sprintf "%s %s" flags (quotepath assembly)) + +let peverify exec peverifyExe path = + exec peverifyExe path + +let createTempDir () = + let path = Path.GetTempFileName () + File.Delete path + Directory.CreateDirectory path |> ignore + path + +let convertToShortPath path = + log "convert to short path %s" path + let result = ref None + let lastLine = function null -> () | l -> result := Some l + + let cmdArgs = { RedirectOutput = Some lastLine; RedirectError = None; RedirectInput = None } + + let args = sprintf """/c for /f "delims=" %%I in ("%s") do echo %%~dfsI""" path + + match Process.exec cmdArgs (Path.GetTempPath()) Map.empty "cmd.exe" args with + | ErrorLevel _ -> path + | Ok -> match !result with None -> path | Some p -> p + +let where envVars cmd = + log "where %s" cmd + let result = ref None + let lastLine = function null -> () | l -> result := Some l + + let cmdArgs = { RedirectOutput = Some lastLine; RedirectError = None; RedirectInput = None; } + + match Process.exec cmdArgs (Path.GetTempPath()) envVars "cmd.exe" (sprintf "/c where %s" cmd) with + | ErrorLevel _ -> None + | CmdResult.Success -> !result + +let fsdiff exec fsdiffExe ignoreWhiteSpaceChanges file1 file2 = + // %FSDIFF% %testname%.err %testname%.bsl + exec fsdiffExe (sprintf "%s%s %s" (if ignoreWhiteSpaceChanges then "-dew " else "") file1 file2) + +let ``for /f`` path = + // FOR /F processing of a text file consists of reading the file, one line of text at a time and then breaking the line up into individual + // items of data called 'tokens'. The DO command is then executed with the parameter(s) set to the token(s) found. + // By default, /F breaks up the line at each blank space " ", and any blank lines are skipped, this default parsing behavior can be changed + // by applying one or more of the "options" parameters. The option(s) must be contained within "a pair of quotes" + let splitLines lines = + lines + |> Array.filter (fun l -> not <| String.IsNullOrWhiteSpace(l)) + |> Array.collect (fun l -> l.Split([| ' ' |], StringSplitOptions.RemoveEmptyEntries)) + |> List.ofArray + + File.ReadAllLines (path) |> splitLines diff --git a/tests/fsharp/FSharp.Tests.fsproj b/tests/fsharp/FSharp.Tests.fsproj new file mode 100644 index 00000000000..ddc781d051c --- /dev/null +++ b/tests/fsharp/FSharp.Tests.fsproj @@ -0,0 +1,1108 @@ + + + + ..\..\src + {C163E892-5BF7-4B59-AA99-B0E8079C67C4} + + + + Debug + AnyCPU + 2.0 + true + true + Library + FSharp.Tests.FSharp + SystematicUnitTests + + false + false + + + $(DefineConstants);EXTENSIONTYPING + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 3 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 3 + + + + + {DED3BBD7-53F4-428A-8C9F-27968E768605} + FSharp.Core + + + + ..\..\packages\NUnit.3.0.0-beta-3\lib\net45\nunit.framework.dll + True + + + + + + + + + + windowsPlatform.fs + + + config.fs + + + update.fs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/fsharp/FSharpTestSuiteTypes.fs b/tests/fsharp/FSharpTestSuiteTypes.fs new file mode 100644 index 00000000000..6596a928daf --- /dev/null +++ b/tests/fsharp/FSharpTestSuiteTypes.fs @@ -0,0 +1,69 @@ +module FSharpTestSuiteTypes + +open PlatformHelpers + +type RunError = + | GenericError of string + | ProcessExecError of (int * string) + | Skipped of string + +type Permutation = + | FSI_FILE + | FSI_STDIN + | FSI_STDIN_OPT + | FSI_STDIN_GUI + | FSC_BASIC + | FSC_BASIC_64 + | FSC_HW + | FSC_O3 + | GENERATED_SIGNATURE + | EMPTY_SIGNATURE + | EMPTY_SIGNATURE_OPT + | FSC_OPT_MINUS_DEBUG + | FSC_OPT_PLUS_DEBUG + | FRENCH + | SPANISH + | AS_DLL + | WRAPPER_NAMESPACE + | WRAPPER_NAMESPACE_OPT + override this.ToString() = (sprintf "%A" this) + +type TestConfig = + { EnvironmentVariables : Map + ALINK : string + CORDIR : string + CORSDK : string + CSC : string + csc_flags : string + FSC : string + fsc_flags : string + FSCBinPath : string + FSCOREDLL20PATH : string + FSCOREDLLPATH : string + FSCOREDLLPORTABLEPATH : string + FSCOREDLLNETCOREPATH : string + FSCOREDLLNETCORE78PATH : string + FSCOREDLLNETCORE259PATH : string + FSDATATPPATH : string + FSCOREDLLVPREVPATH : string + FSDIFF : string + FSI : string + fsi_flags : string + GACUTIL : string + ILDASM : string + INSTALL_SKU : INSTALL_SKU option + MSBUILDTOOLSPATH : string option + NGEN : string + PEVERIFY : string + RESGEN : string + MSBUILD : string option } + +and INSTALL_SKU = + | Clean + | DesktopExpress + | WebExpress + | Ultimate + +type TestRunContext = + { Directory: string; + Config: TestConfig } diff --git a/tests/fsharp/PickPermutations.ps1 b/tests/fsharp/PickPermutations.ps1 index b31532a0864..1e35c113969 100644 --- a/tests/fsharp/PickPermutations.ps1 +++ b/tests/fsharp/PickPermutations.ps1 @@ -26,6 +26,6 @@ $specialCaseCriteria = @{ # seed for random selection is based on build # and test area # this ensures re-runs are predictable, but different test areas get different random choices $seed = (dir $fscPath).VersionInfo.FileBuildPart -bxor $testPath.GetHashCode() -$permutations = ($allPermutations -split '\s+') |?{ $specialCaseCriteria[$_] -ne $false } | Get-Random -SetSeed $seed +$permutations = ($allPermutations -split '\s+') |?{ $specialCaseCriteria[$_] -ne $false } #| Get-Random -SetSeed $seed $permutations -join ' ' \ No newline at end of file diff --git a/tests/fsharp/PlatformHelpers.fs b/tests/fsharp/PlatformHelpers.fs new file mode 100644 index 00000000000..d85a5792f5d --- /dev/null +++ b/tests/fsharp/PlatformHelpers.fs @@ -0,0 +1,204 @@ +module PlatformHelpers + +type ProcessorArchitecture = + | X86 + | IA64 + | AMD64 + | Unknown of string + override this.ToString() = + match this with + | X86 -> "x86" + | IA64 -> "IA64" + | AMD64 -> "AMD64" + | Unknown arc -> arc + +open System.IO + +type FilePath = string + +type CmdResult = + | Success + | ErrorLevel of int + +type CmdArguments = + { RedirectOutput : (string -> unit) option + RedirectError : (string -> unit) option + RedirectInput : (StreamWriter -> unit) option } + +module Process = + + open System.Diagnostics + + let processExePath baseDir exe = + if Path.IsPathRooted(exe) then exe + else + match Path.GetDirectoryName(exe) with + | "" -> exe + | _ -> Path.Combine(baseDir,exe) |> Path.GetFullPath + + let exec cmdArgs (workDir: FilePath) envs (path: FilePath) arguments = + + let exePath = path |> processExePath workDir + let processInfo = new ProcessStartInfo(exePath, arguments) + processInfo.CreateNoWindow <- true + processInfo.UseShellExecute <- false + processInfo.WorkingDirectory <- workDir + + envs + |> Map.iter (fun k v -> processInfo.EnvironmentVariables.[k] <- v) + + let p = new Process() + p.EnableRaisingEvents <- true + p.StartInfo <- processInfo + + cmdArgs.RedirectOutput + |> Option.map (fun f -> (fun (ea: DataReceivedEventArgs) -> ea.Data |> f)) + |> Option.iter (fun newOut -> + processInfo.RedirectStandardOutput <- true + p.OutputDataReceived.Add newOut + ) + + cmdArgs.RedirectError + |> Option.map (fun f -> (fun (ea: DataReceivedEventArgs) -> ea.Data |> f)) + |> Option.iter (fun newErr -> + processInfo.RedirectStandardError <- true + p.ErrorDataReceived.Add newErr + ) + + cmdArgs.RedirectInput + |> Option.iter (fun _ -> p.StartInfo.RedirectStandardInput <- true) + + let exitedAsync (proc: Process) = + let tcs = new System.Threading.Tasks.TaskCompletionSource(); + p.Exited.Add (fun s -> + tcs.TrySetResult(proc.ExitCode) |> ignore + proc.Dispose()) + tcs.Task + + p.Start() |> ignore + + cmdArgs.RedirectOutput |> Option.iter (fun _ -> p.BeginOutputReadLine()) + cmdArgs.RedirectError |> Option.iter (fun _ -> p.BeginErrorReadLine()) + + cmdArgs.RedirectInput + |> Option.map (fun input -> async { + let inputWriter = p.StandardInput + do! inputWriter.FlushAsync () |> Async.AwaitIAsyncResult |> Async.Ignore + input inputWriter + do! inputWriter.FlushAsync () |> Async.AwaitIAsyncResult |> Async.Ignore + inputWriter.Close () + }) + |> Option.iter Async.Start + + let exitCode = p |> exitedAsync |> Async.AwaitTask |> Async.RunSynchronously + + match exitCode with + | 0 -> Success + | err -> ErrorLevel err + + + +type Result<'S,'F> = + | Success of 'S + | Failure of 'F + +type Attempt<'S,'F> = (unit -> Result<'S,'F>) + +open System.Diagnostics + +[] +let internal succeed x = (fun () -> Success x) + +[] +let internal failed err = (fun () -> Failure err) + +[] +let runAttempt (a: Attempt<_,_>) = a () + +[] +let delay f = (fun () -> f() |> runAttempt) + +[] +let either successTrack failTrack (input : Attempt<_, _>) : Attempt<_, _> = + match runAttempt input with + | Success s -> successTrack s + | Failure f -> failTrack f + +[] +let bind successTrack = either successTrack failed + +[] +let fail failTrack result = either succeed failTrack result + +[] +type Attempt = + static member Run x = runAttempt x + +[] +type AttemptBuilder() = + member this.Bind(m : Attempt<_, _>, success) = bind success m + member this.Bind(m : Result<_, _>, success) = bind success (fun () -> m) + member this.Bind(m : Result<_, _> option, success) = + match m with + | None -> this.Combine(this.Zero(), success) + | Some x -> this.Bind(x, success) + member this.Return(x) : Attempt<_, _> = succeed x + member this.ReturnFrom(x : Attempt<_, _>) = x + member this.Combine(v, f) : Attempt<_, _> = bind f v + member this.Yield(x) = Success x + member this.YieldFrom(x) = x + member this.Delay(f) : Attempt<_, _> = delay f + member this.Zero() : Attempt<_, _> = succeed () + member this.While(guard, body: Attempt<_, _>) = + if not (guard()) + then this.Zero() + else this.Bind(body, fun () -> + this.While(guard, body)) + + member this.TryWith(body, handler) = + try this.ReturnFrom(body()) + with e -> handler e + + member this.TryFinally(body, compensation) = + try this.ReturnFrom(body()) + finally compensation() + + member this.Using(disposable:#System.IDisposable, body) = + let body' = fun () -> body disposable + this.TryFinally(body', fun () -> + match disposable with + | null -> () + | disp -> disp.Dispose()) + + member this.For(sequence:seq<'a>, body: 'a -> Attempt<_,_>) = + this.Using(sequence.GetEnumerator(),fun enum -> + this.While(enum.MoveNext, + this.Delay(fun () -> body enum.Current))) + +let processor = new AttemptBuilder() + + +let log format = Printf.ksprintf (printfn "%s") format + +type OutPipe (mailbox: MailboxProcessor<_>) = + member x.Post msg = mailbox.Post(msg) + interface System.IDisposable with + member x.Dispose () = + async { + while mailbox.CurrentQueueLength > 0 do + let timeout = System.TimeSpan.FromMilliseconds(50.0) + do! Async.Sleep (timeout.TotalMilliseconds |> int) + } |> Async.RunSynchronously + +let redirectTo (writer: TextWriter) = + let mailbox = MailboxProcessor.Start(fun inbox -> + let rec loop () = async { + let! (msg : string) = inbox.Receive () + do! writer.WriteLineAsync(msg) |> (Async.AwaitIAsyncResult >> Async.Ignore) + return! loop () } + loop ()) + new OutPipe (mailbox) + +let redirectToLog () = redirectTo System.Console.Out + +let inline (/) a (b: string) = System.IO.Path.Combine(a,b) diff --git a/tests/fsharp/Properties/AssemblyInfo.cs b/tests/fsharp/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..11e3bfec935 --- /dev/null +++ b/tests/fsharp/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Runtime.CompilerServices; +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("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[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("145B8577-B5E8-46A0-9FDF-2FB99C4D3573")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/fsharp/core/.gitignore b/tests/fsharp/core/.gitignore index e395d5b7827..34c12b24af2 100644 --- a/tests/fsharp/core/.gitignore +++ b/tests/fsharp/core/.gitignore @@ -51,3 +51,8 @@ topinit/both69514-noopt.pdb verify/xmlverify.exe verify/xmlverify.pdb + +fsi-reload/load1.exe +fsi-reload/load2.exe + +quotesInMultipleModules/module2-staticlink.exe diff --git a/tests/fsharp/core/tests_core.fs b/tests/fsharp/core/tests_core.fs new file mode 100644 index 00000000000..b3b600546a0 --- /dev/null +++ b/tests/fsharp/core/tests_core.fs @@ -0,0 +1,2683 @@ +module ``FSharp-Tests-Core`` + +open System +open System.IO +open NUnit.Framework + +open NUnitConf +open PlatformHelpers +open FSharpTestSuiteTypes + +let testContext = FSharpTestSuite.testContext + +let requireVSUltimate cfg = processor { + do! match cfg.INSTALL_SKU with + | Some (Ultimate) -> Success + | x -> + // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( + // echo Test not supported except on Ultimate + NUnitConf.skip (sprintf "Test not supported except on Ultimate, was %A" x) + // exit /b 0 + // ) + } + +module Access = + [] + let access p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Apporder = + [] + let apporder p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Array = + [] + let array p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Attributes = + [] + let attributes p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Comprehensions = + [] + let comprehensions p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Control = + [] + let control p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + [] + let ``control --tailcalls`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun {cfg with fsi_flags = " --tailcalls" } dir p + }) + +module ControlChamenos = + [] + let controlChamenos p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun { cfg with fsi_flags = " --tailcalls" } dir p + }) + +module ControlMailbox = + [] + let controlMailbox p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + [] + let ``controlMailbox --tailcalls`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun { cfg with fsi_flags = " --tailcalls" } dir p + }) + +module ControlWpf = + [] + let controlWpf p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Csext = + [] + let csext p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Events = + + let build cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None} p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + + // "%FSC%" %fsc_flags% -a -o:test.dll -g test.fs + do! fsc "%s -a -o:test.dll -g" cfg.fsc_flags ["test.fs"] + + // "%PEVERIFY%" test.dll + do! peverify "test.dll" + + // %CSC% /r:"%FSCOREDLLPATH%" /reference:test.dll /debug+ testcs.cs + do! csc """/r:"%s" /reference:test.dll /debug+""" cfg.FSCOREDLLPATH ["testcs.cs"] + + // "%PEVERIFY%" testcs.exe + do! peverify "testcs.exe" + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None} p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + use testOkFile = fileguard "test.ok" + + // %CLIX% "%FSI%" test.fs && ( + do! fsi "" ["test.fs"] + + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSI failed; + // goto Error + // set ERRORMSG=%ERRORMSG% FSI failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + + // %CLIX% .\testcs.exe + do! exec ("."/"testcs.exe") "" + } + + [] + let events () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + }) + + +module ``FSI-Shadowcopy`` = + + [] + // "%FSI%" %fsi_flags% < test1.fsx + [] + // "%FSI%" %fsi_flags% --shadowcopyreferences- < test1.fsx + [] + let ``shadowcopy disabled`` (flags: string) = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // if exist test1.ok (del /f /q test1.ok) + use testOkFile = fileguard "test1.ok" + + do! ``fsi <`` "%s %s" cfg.fsi_flags flags "test1.fsx" + + // if NOT EXIST test1.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + }) + + [] + // "%FSI%" %fsi_flags% /shadowcopyreferences+ < test2.fsx + [] + // "%FSI%" %fsi_flags% --shadowcopyreferences < test2.fsx + [] + let ``shadowcopy enabled`` (flags: string) = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // if exist test2.ok (del /f /q test2.ok) + use testOkFile = fileguard "test2.ok" + + // "%FSI%" %fsi_flags% /shadowcopyreferences+ < test2.fsx + do! ``fsi <`` "%s %s" cfg.fsi_flags flags "test2.fsx" + + // if NOT EXIST test2.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + }) + + + +module Forwarders = + + [] + let forwarders () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let copy_y f = Commands.copy_y dir f >> checkResult + let mkdir = Commands.mkdir_p dir + + // mkdir orig + mkdir "orig" + // mkdir split + mkdir "split" + + // %CSC% /nologo /target:library /out:orig\a.dll /define:PART1;PART2 a.cs + do! csc """/nologo /target:library /out:orig\a.dll /define:PART1;PART2""" ["a.cs"] + + // %CSC% /nologo /target:library /out:orig\b.dll /r:orig\a.dll b.cs + do! csc """/nologo /target:library /out:orig\b.dll /r:orig\a.dll""" ["b.cs"] + + // "%FSC%" -a -o:orig\c.dll -r:orig\b.dll -r:orig\a.dll c.fs + do! fsc """-a -o:orig\c.dll -r:orig\b.dll -r:orig\a.dll""" ["c.fs"] + + // %CSC% /nologo /target:library /out:split\a-part1.dll /define:PART1;SPLIT a.cs + do! csc """/nologo /target:library /out:split\a-part1.dll /define:PART1;SPLIT""" ["a.cs"] + + // %CSC% /nologo /target:library /r:split\a-part1.dll /out:split\a.dll /define:PART2;SPLIT a.cs + do! csc """/nologo /target:library /r:split\a-part1.dll /out:split\a.dll /define:PART2;SPLIT""" ["a.cs"] + + // copy /y orig\b.dll split\b.dll + do! copy_y ("orig"/"b.dll") ("split"/"b.dll") + // copy /y orig\c.dll split\c.dll + do! copy_y ("orig"/"c.dll") ("split"/"c.dll") + + // "%FSC%" -o:orig\test.exe -r:orig\b.dll -r:orig\a.dll test.fs + do! fsc """-o:orig\test.exe -r:orig\b.dll -r:orig\a.dll""" ["test.fs"] + + // "%FSC%" -o:split\test.exe -r:split\b.dll -r:split\a-part1.dll -r:split\a.dll test.fs + do! fsc """-o:split\test.exe -r:split\b.dll -r:split\a-part1.dll -r:split\a.dll""" ["test.fs"] + + // "%FSC%" -o:split\test-against-c.exe -r:split\c.dll -r:split\a-part1.dll -r:split\a.dll test.fs + do! fsc """-o:split\test-against-c.exe -r:split\c.dll -r:split\a-part1.dll -r:split\a.dll""" ["test.fs"] + + // pushd split + // "%PEVERIFY%" a-part1.dll + do! peverify ("split"/"a-part1.dll") + + // REM "%PEVERIFY%" a.dll + // REM @if ERRORLEVEL 1 goto Error + + // "%PEVERIFY%" b.dll + do! peverify ("split"/"b.dll") + + // "%PEVERIFY%" c.dll + do! peverify ("split"/"c.dll") + + // "%PEVERIFY%" test.exe + do! peverify ("split"/"test.exe") + + // "%PEVERIFY%" test-against-c.exe + do! peverify ("split"/"test-against-c.exe") + + // popd + + }) + +module FsFromCs = + + let build cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -a --doc:lib.xml -o:lib.dll -g lib.ml + do! fsc "%s -a --doc:lib.xml -o:lib.dll -g" fsc_flags ["lib.ml"] + + // "%PEVERIFY%" lib.dll + do! peverify "lib.dll" + + // %CSC% /nologo /r:"%FSCOREDLLPATH%" /r:System.Core.dll /r:lib.dll /out:test.exe test.cs + do! csc """/nologo /r:"%s" /r:System.Core.dll /r:lib.dll /out:test.exe""" cfg.FSCOREDLLPATH ["test.cs"] + + // "%FSC%" %fsc_flags% -a --doc:lib--optimize.xml -o:lib--optimize.dll -g lib.ml + do! fsc """%s -a --doc:lib--optimize.xml -o:lib--optimize.dll -g""" fsc_flags ["lib.ml"] + + // "%PEVERIFY%" lib--optimize.dll + do! peverify "lib--optimize.dll" + + // %CSC% + do! csc """/nologo /r:"%s" /r:System.Core.dll /r:lib--optimize.dll /out:test--optimize.exe""" cfg.FSCOREDLLPATH ["test.cs"] + + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + + // %CLIX% .\test.exe + do! exec ("."/"test.exe") "" + + // %CLIX% .\test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + + } + + [] + let fsfromcs () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + +module FsFromFsViaCs = + + let build cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -a -o:lib.dll -g lib.ml + do! fsc "%s -a -o:lib.dll -g" fsc_flags ["lib.ml"] + + // "%PEVERIFY%" lib.dll + do! peverify "lib.dll" + + // %CSC% /nologo /target:library /r:"%FSCOREDLLPATH%" /r:lib.dll /out:lib2.dll lib2.cs + do! csc """/nologo /target:library /r:"%s" /r:lib.dll /out:lib2.dll""" cfg.FSCOREDLLPATH ["lib2.cs"] + + // "%FSC%" %fsc_flags% -r:lib.dll -r:lib2.dll -o:test.exe -g test.fsx + do! fsc "%s -r:lib.dll -r:lib2.dll -o:test.exe -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + + // %CLIX% .\test.exe + do! exec ("."/"test.exe") "" + + } + + [] + let fsfromfsviacs () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +module ``FSI-reload`` = + + [] + let ``fsi-reload`` () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + + /////// build.bat /////// + + // REM NOTE that this test does not do anything. + // REM PEVERIFY not needed + + /////// run.bat //////// + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% --maxerrors:1 < test1.ml + do! ``fsi <`` "%s --maxerrors:1" cfg.fsi_flags "test1.ml" + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% --maxerrors:1 load1.fsx + do! fsi "%s --maxerrors:1" cfg.fsi_flags ["load1.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% --maxerrors:1 load2.fsx + do! fsi "%s --maxerrors:1" cfg.fsi_flags ["load2.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + // REM Check we can also compile, for sanity's sake + // "%FSC%" load1.fsx + do! fsc "" ["load1.fsx"] + + // REM Check we can also compile, for sanity's sake + // "%FSC%" load2.fsx + do! fsc "" ["load2.fsx"] + + }) + + +module fsiAndModifiers = + + let build cfg dir = processor { + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let del = Commands.rm dir + let exist = Commands.fileExists dir >> Option.isSome + + // if exist TestLibrary.dll (del /f /q TestLibrary.dll) + do if exist "TestLibrary.dll" then del "TestLibrary.dll" + + // "%FSI%" %fsi_flags% --maxerrors:1 < prepare.fsx + do! ``fsi <`` "%s --maxerrors:1" cfg.fsi_flags "prepare.fsx" + + } + + let run cfg dir = processor { + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // "%FSI%" %fsi_flags% --maxerrors:1 < test.fsx + do! ``fsi <`` "%s --maxerrors:1" cfg.fsi_flags "test.fsx" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + } + + [] + let fsiAndModifiers () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + +module GenericMeasures = + + [] + let genericmeasures p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Hiding = + + [] + let hiding () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -a --optimize -o:lib.dll lib.mli lib.ml libv.ml + do! fsc "%s -a --optimize -o:lib.dll" fsc_flags ["lib.mli";"lib.ml";"libv.ml"] + + // "%PEVERIFY%" lib.dll + do! peverify "lib.dll" + + // "%FSC%" %fsc_flags% -a --optimize -r:lib.dll -o:lib2.dll lib2.mli lib2.ml lib3.ml + do! fsc "%s -a --optimize -r:lib.dll -o:lib2.dll" fsc_flags ["lib2.mli";"lib2.ml";"lib3.ml"] + + // "%PEVERIFY%" lib2.dll + do! peverify "lib2.dll" + + // "%FSC%" %fsc_flags% --optimize -r:lib.dll -r:lib2.dll -o:client.exe client.ml + do! fsc "%s --optimize -r:lib.dll -r:lib2.dll -o:client.exe" fsc_flags ["client.ml"] + + // "%PEVERIFY%" client.exe + do! peverify "client.exe" + + }) + + +module Innerpoly = + + [] + let innerpoly p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``test int32`` = + + [] + let int32 p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module QueriesCustomQueryOps = + + let build cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -o:test.exe -g test.fsx + do! fsc """%s -o:test.exe -g""" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fsx + do! fsc """%s --optimize -o:test--optimize.exe -g""" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + // call ..\..\single-neg-test.bat negativetest + do! SingleNegTest.singleNegTest cfg dir "negativetest" + + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // echo TestC + log "TestC" + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // "%FSI%" %fsi_flags% test.fsx + do! fsi "%s" cfg.fsi_flags ["test.fsx"] + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + // echo TestD + log "TestD" + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + } + + [] + let queriesCustomQueryOps () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + +[] +module Printing = + + // "%FSI%" %fsc_flags_errors_ok% --nologo --use:preludePrintSize200.fsx z.raw.output.test.200.txt 2>&1 + // findstr /v "%CD%" z.raw.output.test.200.txt | findstr /v -C:"--help' for options" > z.output.test.200.txt + // if NOT EXIST z.output.test.200.bsl COPY z.output.test.200.txt z.output.test.200.bsl + // %PRDIFF% z.output.test.200.txt z.output.test.200.bsl > z.output.test.200.diff + [] + [] //not enough + [] + [] + [] + [] + [] + let printing flag diffFile expectedFile = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let copy from' = Commands.copy_y dir from' >> checkResult + let fileExists = Commands.fileExists dir >> Option.isSome + let getfullpath = Commands.getfullpath dir + + let ``fsi b 2>&1`` = + // "%FSI%" %fsc_flags_errors_ok% --nologo z.raw.output.test.default.txt 2>&1 + let ``exec b 2>&1`` inFile outFile p = + Command.exec dir cfg.EnvironmentVariables { Output = OutputAndError(Overwrite(outFile)); Input = Some(RedirectInput(inFile)); } p + >> checkResult + Printf.ksprintf (fun flags in' out -> Commands.fsi (``exec b 2>&1`` in' out) cfg.FSI flags []) + + let fsdiff a b = + let ``exec >`` f p = Command.exec dir cfg.EnvironmentVariables { Output = Output(Overwrite(f)); Input = None} p >> checkResult + let diffFile = Path.ChangeExtension(a, ".diff") + Commands.fsdiff (``exec >`` diffFile) cfg.FSDIFF false a b + + let fsc_flags_errors_ok = "" + + // echo == Plain + // "%FSI%" %fsc_flags_errors_ok% --nologo z.raw.output.test.default.txt 2>&1 + // echo == PrintSize 1000 + // "%FSI%" %fsc_flags_errors_ok% --nologo --use:preludePrintSize1000.fsx z.raw.output.test.1000.txt 2>&1 + // echo == PrintSize 200 + // "%FSI%" %fsc_flags_errors_ok% --nologo --use:preludePrintSize200.fsx z.raw.output.test.200.txt 2>&1 + // echo == ShowDeclarationValues off + // "%FSI%" %fsc_flags_errors_ok% --nologo --use:preludeShowDeclarationValuesFalse.fsx z.raw.output.test.off.txt 2>&1 + // echo == Quiet + // "%FSI%" %fsc_flags_errors_ok% --nologo --quiet z.raw.output.test.quiet.txt 2>&1 + let rawFile = Path.GetTempFileName() + do! ``fsi b 2>&1`` "%s --nologo %s" fsc_flags_errors_ok flag "test.fsx" rawFile + + // REM REVIEW: want to normalise CWD paths, not suppress them. + let ``findstr /v`` text = Seq.filter (fun (s: string) -> not <| s.Contains(text)) + let removeCDandHelp from' to' = + File.ReadLines from' |> (``findstr /v`` dir) |> (``findstr /v`` "--help' for options") |> (fun lines -> File.WriteAllLines(getfullpath to', lines)) + + // findstr /v "%CD%" z.raw.output.test.default.txt | findstr /v -C:"--help' for options" > z.output.test.default.txt + // findstr /v "%CD%" z.raw.output.test.1000.txt | findstr /v -C:"--help' for options" > z.output.test.1000.txt + // findstr /v "%CD%" z.raw.output.test.200.txt | findstr /v -C:"--help' for options" > z.output.test.200.txt + // findstr /v "%CD%" z.raw.output.test.off.txt | findstr /v -C:"--help' for options" > z.output.test.off.txt + // findstr /v "%CD%" z.raw.output.test.quiet.txt | findstr /v -C:"--help' for options" > z.output.test.quiet.txt + removeCDandHelp rawFile diffFile + + let withDefault default' to' = + if not (fileExists to') then Some (copy default' to') else None + // if NOT EXIST z.output.test.default.bsl COPY z.output.test.default.txt z.output.test.default.bsl + // if NOT EXIST z.output.test.off.bsl COPY z.output.test.off.txt z.output.test.off.bsl + // if NOT EXIST z.output.test.1000.bsl COPY z.output.test.1000.txt z.output.test.1000.bsl + // if NOT EXIST z.output.test.200.bsl COPY z.output.test.200.txt z.output.test.200.bsl + // if NOT EXIST z.output.test.quiet.bsl COPY z.output.test.quiet.txt z.output.test.quiet.bsl + do! expectedFile |> withDefault diffFile + + // %PRDIFF% z.output.test.default.txt z.output.test.default.bsl > z.output.test.default.diff + // %PRDIFF% z.output.test.off.txt z.output.test.off.bsl > z.output.test.off.diff + // %PRDIFF% z.output.test.1000.txt z.output.test.1000.bsl > z.output.test.1000.diff + // %PRDIFF% z.output.test.200.txt z.output.test.200.bsl > z.output.test.200.diff + // %PRDIFF% z.output.test.quiet.txt z.output.test.quiet.bsl > z.output.test.quiet.diff + do! fsdiff diffFile expectedFile + + // echo ======== Differences From ======== + // TYPE z.output.test.default.diff + // TYPE z.output.test.off.diff + // TYPE z.output.test.1000.diff + // TYPE z.output.test.200.diff + // TYPE z.output.test.quiet.diff + // echo ========= Differences To ========= + // + // TYPE z.output.test.default.diff > zz.alldiffs + // TYPE z.output.test.off.diff >> zz.alldiffs + // TYPE z.output.test.1000.diff >> zz.alldiffs + // TYPE z.output.test.200.diff >> zz.alldiffs + // TYPE z.output.test.quiet.diff >> zz.alldiffs + // + // for /f %%c IN (zz.alldiffs) do ( + // echo NOTE ------------------------------------- + // echo NOTE ---------- THERE ARE DIFFs ---------- + // echo NOTE ------------------------------------- + // echo . + // echo To update baselines: "sd edit *bsl", "del *bsl", "build.bat" regenerates bsl, "sd diff ...", check what changed. + // goto Error + // ) + ignore "printed to log" + + + }) + +module Quotes = + + let build cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc_flags = cfg.fsc_flags + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + + //missing csc + do! csc """/nologo /target:library /out:cslib.dll""" ["cslib.cs"] + + // "%FSC%" %fsc_flags% -o:test.exe -r cslib.dll -g test.fsx + do! fsc "%s -o:test.exe -r cslib.dll -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% -o:test-with-debug-data.exe --quotations-debug+ -r cslib.dll -g test.fsx + do! fsc "%s -o:test-with-debug-data.exe --quotations-debug+ -r cslib.dll -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test-with-debug-data.exe + do! peverify "test-with-debug-data.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -r cslib.dll -g test.fsx + do! fsc "%s --optimize -o:test--optimize.exe -r cslib.dll -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // "%FSI%" %fsi_flags% -r cslib.dll test.fsx + do! fsi "%s -r cslib.dll" cfg.fsi_flags ["test.fsx"] + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% test-with-debug-data.exe + do! exec ("."/"test-with-debug-data.exe") "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + do! processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + } + + [] + let quotes () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +module Namespaces = + + [] + let attributes p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Parsing = + + [] + let parsing () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -a -o:crlf.dll -g crlf.ml + do! fsc "%s -a -o:crlf.dll -g" fsc_flags ["crlf.ml"] + + // "%FSC%" %fsc_flags% -o:toplet.exe -g toplet.ml + do! fsc "%s -o:toplet.exe -g" fsc_flags ["toplet.ml"] + + // "%PEVERIFY%" toplet.exe + do! peverify "toplet.exe" + + }) + +module Unicode = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let fsc_flags = cfg.fsc_flags + + // REM just checking the files actually parse/compile for now.... + + // "%FSC%" %fsc_flags% -a -o:kanji-unicode-utf8-nosig-codepage-65001.dll -g kanji-unicode-utf8-nosig-codepage-65001.fs + do! fsc "%s -a -o:kanji-unicode-utf8-nosig-codepage-65001.dll -g" fsc_flags ["kanji-unicode-utf8-nosig-codepage-65001.fs"] + + // "%FSC%" %fsc_flags% -a -o:kanji-unicode-utf8-nosig-codepage-65001.dll -g kanji-unicode-utf8-nosig-codepage-65001.fs + do! fsc "%s -a -o:kanji-unicode-utf8-nosig-codepage-65001.dll -g" fsc_flags ["kanji-unicode-utf8-nosig-codepage-65001.fs"] + + let codepage = processor { + // "%FSC%" %fsc_flags% -a -o:kanji-unicode-utf16.dll -g kanji-unicode-utf16.fs + do! fsc "%s -a -o:kanji-unicode-utf16.dll -g" fsc_flags ["kanji-unicode-utf16.fs"] + + // "%FSC%" %fsc_flags% -a --codepage:65000 -o:kanji-unicode-utf7-codepage-65000.dll -g kanji-unicode-utf7-codepage-65000.fs + do! fsc "%s -a --codepage:65000 -o:kanji-unicode-utf7-codepage-65000.dll -g" fsc_flags ["kanji-unicode-utf7-codepage-65000.fs"] + } + + // REM check non-utf8 and --codepage flag for bootstrapped fsc.exe + // if NOT "%FSC:fscp=X%" == "%FSC%" ( + do! if not <| cfg.FSC.Contains("fscp") then codepage else Success + + // "%FSC%" %fsc_flags% -a -o:kanji-unicode-utf8-withsig-codepage-65001.dll -g kanji-unicode-utf8-withsig-codepage-65001.fs + do! fsc "%s -a -o:kanji-unicode-utf8-withsig-codepage-65001.dll -g" fsc_flags ["kanji-unicode-utf8-withsig-codepage-65001.fs"] + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fsi_flags = cfg.fsi_flags + + // if exist test.ok (del /f /q test.ok) + ignore "unused" + // "%FSI%" %fsi_flags% --utf8output kanji-unicode-utf8-nosig-codepage-65001.fs + do! fsi "%s --utf8output" fsi_flags ["kanji-unicode-utf8-nosig-codepage-65001.fs"] + + // if exist test.ok (del /f /q test.ok) + ignore "unused" + // "%FSI%" %fsi_flags% --utf8output --codepage:65001 kanji-unicode-utf8-withsig-codepage-65001.fs + do! fsi "%s --utf8output --codepage:65001" fsi_flags ["kanji-unicode-utf8-withsig-codepage-65001.fs"] + + // if exist test.ok (del /f /q test.ok) + ignore "unused" + // "%FSI%" %fsi_flags% --utf8output kanji-unicode-utf8-withsig-codepage-65001.fs + do! fsi "%s --utf8output" fsi_flags ["kanji-unicode-utf8-withsig-codepage-65001.fs"] + + // if exist test.ok (del /f /q test.ok) + ignore "unused" + // "%FSI%" %fsi_flags% --utf8output --codepage:65000 kanji-unicode-utf7-codepage-65000.fs + do! fsi "%s --utf8output --codepage:65000" fsi_flags ["kanji-unicode-utf7-codepage-65000.fs"] + + // if exist test.ok (del /f /q test.ok) + ignore "unused" + // "%FSI%" %fsi_flags% --utf8output kanji-unicode-utf16.fs + do! fsi "%s --utf8output" fsi_flags ["kanji-unicode-utf16.fs"] + } + + + [] + let unicode () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + do! run cfg dir + }) + + [] + let unicode2 p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + // call %~d0%~p0..\..\single-test-build.bat + do! SingleTestBuild.singleTestBuild cfg dir p + + // call %~d0%~p0..\..\single-test-run.bat + do! SingleTestRun.singleTestRun cfg dir p + }) + +module InternalsVisible = + + [] + let internalsvisible () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let fsc_flags = cfg.fsc_flags + + // REM Test internals visible + + // echo == Compiling F# Library + log "== Compiling F# Library" + // "%FSC%" %fsc_flags% --version:1.2.3 --keyfile:key.snk -a --optimize -o:library.dll library.fsi library.fs + do! fsc "%s --version:1.2.3 --keyfile:key.snk -a --optimize -o:library.dll" fsc_flags ["library.fsi"; "library.fs"] + + // echo == Verifying F# Library + log "== Verifying F# Library" + + // "%PEVERIFY%" library.dll + do! peverify "library.dll" + + // echo == Compiling C# Library + log "== Compiling C# Library" + // %CSC% /target:library /keyfile:key.snk /out:librarycs.dll librarycs.cs + do! csc "/target:library /keyfile:key.snk /out:librarycs.dll" ["librarycs.cs"] + + // echo == Verifying C# Library + log "== Verifying C# Library" + // "%PEVERIFY%" librarycs.dll + do! peverify "librarycs.dll" + + // echo == Compiling F# main referencing C# and F# libraries + log "== Compiling F# main referencing C# and F# libraries" + // "%FSC%" %fsc_flags% --version:1.2.3 --keyfile:key.snk --optimize -r:library.dll -r:librarycs.dll -o:main.exe main.fs + do! fsc "%s --version:1.2.3 --keyfile:key.snk --optimize -r:library.dll -r:librarycs.dll -o:main.exe" fsc_flags ["main.fs"] + + // echo == Verifying F# main + log "== Verifying F# main" + // "%PEVERIFY%" main.exe + do! peverify "main.exe" + + // echo == Run F# main. Quick test! + log "== Run F# main. Quick test!" + // main.exe + do! exec ("."/"main.exe") "" + }) + + +module Interop = + + let build cfg dir = processor { + let envVars = + cfg.EnvironmentVariables + |> Map.add "FSCOREDLLPATH" cfg.FSCOREDLLPATH + |> Map.add "FSCOREDLLNETCORE78PATH" cfg.FSCOREDLLNETCORE78PATH + + let exec p = Command.exec dir envVars { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let msbuild = Printf.ksprintf (Commands.msbuild exec (cfg.MSBUILD.Value)) + + // rd /S /Q obj + // del /f /q *.pdb *.xml *.config *.dll *.exe + + // "%MSBUILDTOOLSPATH%\msbuild.exe" PCL.fsproj + do! msbuild "" ["PCL.fsproj"] + + // "%MSBUILDTOOLSPATH%\msbuild.exe" User.fsproj + do! msbuild "" ["User.fsproj"] + + // %PEVERIFY% User.exe + do! peverify "User.exe" + + } + + let run cfg dir = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + + do! exec ("."/"User.exe") "" + } + + [] + let interop () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + +module ``test lazy`` = + + [] + let ``lazy`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module letrec = + + [] + let letrec p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module LibTest = + + [] + let libtest p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Lift = + + [] + let lift p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +[] +module ``Load-Script`` = + + let ``script > a 2>&1`` cfg dir to' = processor { + + let toPath = to' |> Commands.getfullpath dir + + let alwaysSuccess _ = Success () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = OutputAndError(Append(toPath)); Input = None; } p >> alwaysSuccess + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = OutputAndError(Append(toPath)); Input = Some(RedirectInput(l)) } p >> alwaysSuccess + + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let type_append_tofile from = Commands.type_append_tofile dir from toPath + let echo text = Commands.echo_append_tofile dir text toPath + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let fileExists = Commands.fileExists dir >> Option.isSome + let del = Commands.rm dir + let getfullpath = Commands.getfullpath dir + + File.WriteAllText(toPath, "") + + // del 3.exe 2>nul 1>nul + do if fileExists "3.exe" then getfullpath "3.exe" |> File.Delete + // type 1.fsx 2.fsx 3.fsx + ["1.fsx"; "2.fsx"; "3.fsx"] |> List.iter type_append_tofile + // echo Test 1================================================= + echo "Test 1=================================================" + // "%FSC%" 3.fsx --nologo + do! fsc "--nologo" ["3.fsx"] + // 3.exe + do! exec ("."/"3.exe") "" + // del 3.exe + del "3.exe" + // echo Test 2================================================= + echo "Test 2=================================================" + // "%FSI%" 3.fsx + do! fsi "" ["3.fsx"] + // echo Test 3================================================= + echo "Test 3=================================================" + // "%FSI%" --nologo < pipescr + do! ``fsi <`` "--nologo" "pipescr" + // echo. + echo "" + // echo Test 4================================================= + echo "Test 4=================================================" + // "%FSI%" usesfsi.fsx + do! fsi "" ["usesfsi.fsx"] + // echo Test 5================================================= + echo "Test 5=================================================" + // "%FSC%" usesfsi.fsx --nologo + do! fsc "--nologo" ["usesfsi.fsx"] + // echo Test 6================================================= + echo "Test 6=================================================" + // "%FSC%" usesfsi.fsx --nologo -r FSharp.Compiler.Interactive.Settings + do! fsc "--nologo -r FSharp.Compiler.Interactive.Settings" ["usesfsi.fsx"] + // echo Test 7================================================= + echo "Test 7=================================================" + // "%FSI%" 1.fsx 2.fsx 3.fsx + do! fsi "" ["1.fsx";"2.fsx";"3.fsx"] + // echo Test 8================================================= + echo "Test 8=================================================" + // "%FSI%" 3.fsx 2.fsx 1.fsx + do! fsi "" ["3.fsx";"2.fsx";"1.fsx"] + // echo Test 9================================================= + echo "Test 9=================================================" + // "%FSI%" multiple-load-1.fsx + do! fsi "" ["multiple-load-1.fsx"] + // echo Test 10================================================= + echo "Test 10=================================================" + // "%FSI%" multiple-load-2.fsx + do! fsi "" ["multiple-load-2.fsx"] + // echo Test 11================================================= + echo "Test 11=================================================" + // "%FSC%" FlagCheck.fs --nologo + do! fsc "--nologo" ["FlagCheck.fs"] + // FlagCheck.exe + do! exec ("."/"FlagCheck.exe") "" + // del FlagCheck.exe + del "FlagCheck.exe" + // echo Test 12================================================= + echo "Test 12=================================================" + // "%FSC%" FlagCheck.fsx --nologo + do! fsc "--nologo" ["FlagCheck.fsx"] + // FlagCheck.exe + do! exec ("."/"FlagCheck.exe") "" + // del FlagCheck.exe + del "FlagCheck.exe" + // echo Test 13================================================= + echo "Test 13=================================================" + // "%FSI%" load-FlagCheckFs.fsx + do! fsi "" ["load-FlagCheckFs.fsx"] + // echo Test 14================================================= + echo "Test 14=================================================" + // "%FSI%" FlagCheck.fsx + do! fsi "" ["FlagCheck.fsx"] + // echo Test 15================================================= + echo "Test 15=================================================" + // "%FSI%" ProjectDriver.fsx + do! fsi "" ["ProjectDriver.fsx"] + // echo Test 16================================================= + echo "Test 16=================================================" + // "%FSC%" ProjectDriver.fsx --nologo + do! fsc "--nologo" ["ProjectDriver.fsx"] + // ProjectDriver.exe + do! exec ("."/"ProjectDriver.exe") "" + // del ProjectDriver.exe + del "ProjectDriver.exe" + // echo Done ================================================== + echo "Done ==================================================" + } + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let ``script > out.txt 2>&1`` () = ``script > a 2>&1`` cfg dir "out.txt" + let getfullpath = Commands.getfullpath dir + + let fsdiff a b = processor { + let out = new ResizeArray() + let redirectOutputToFile path args = + log "%s %s" path args + let toLog = redirectToLog () + Process.exec { RedirectOutput = Some (function null -> () | s -> out.Add(s)); RedirectError = Some toLog.Post; RedirectInput = None; } dir cfg.EnvironmentVariables path args + do! (Commands.fsdiff redirectOutputToFile cfg.FSDIFF true a b) |> (fun _ -> Success ()) + return out.ToArray() |> List.ofArray + } + + + // script > out.txt 2>&1 + do! ``script > out.txt 2>&1`` () + + // if NOT EXIST out.bsl COPY out.txt + ignore "useless, first run, same as use an empty file" + + let normalizePaths f = + let text = File.ReadAllText(f) + let dummyPath = @"D:\staging\staging\src\tests\fsharp\core\load-script" + let contents = System.Text.RegularExpressions.Regex.Replace(text, System.Text.RegularExpressions.Regex.Escape(dir), dummyPath) + File.WriteAllText(f, contents) + + normalizePaths (getfullpath "out.txt") + + // %FSDIFF% out.txt out.bsl > out.diff + let! diffs = fsdiff (getfullpath "out.txt") (getfullpath "out.bsl") + + // %FSDIFF% z.output.fsi.help.txt z.output.fsi.help.bsl > z.output.fsi.help.diff + + // echo ======== Differences From ======== + // TYPE out.diff + // echo ========= Differences To ========= + + // for /f %%c IN (out.diff do ( + // echo . + // echo To update baselines: "sd edit *bsl", "del *bsl", "build.bat" regenerates bsl, "sd diff ...", check what changed. + // goto Error + // ) + do! match diffs with + | [] -> Success + | l -> + // echo NOTE ------------------------------------- + // echo NOTE ---------- THERE ARE DIFFs ---------- + // echo NOTE ------------------------------------- + log "NOTE -------------------------------------" + log "NOTE ---------- THERE ARE DIFFs ----------" + log "NOTE -------------------------------------" + NUnitConf.genericError (sprintf "'%s' and '%s' differ; %A" (getfullpath "out.txt") (getfullpath "out.bsl") diffs) + } + + [] + let ``load-script`` () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + }) + + +module LongNames = + + [] + let longnames p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``test map`` = + + [] + let map p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Math = + //TODO math/lalgebra does not have build.bat/run.bat and #r "FSharp.Math.Providers.dll" + + module Numbers = + + [] + let numbers p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + module numbersVS2008 = + + [] + let numbersVS2008 p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module Measures = + + [] + let measures p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + +module Members = + + //TODO members/console does not have build.bat/run.bat + + (* REVIEW This test fail for FSI_STDIN* + Output: + + // D:\github\fsharp\tests\fsharp\..\..\Debug\net40\bin\fsiAnyCPU.exe -r:System.Core.dll --nowarn:20 --define:INTERACTIVE --maxerrors:1 --abortonerror Map.add "FSCOREDLLPORTABLEPATH" cfg.FSCOREDLLPORTABLEPATH + + let exec p = Command.exec dir envVars { Output = Inherit; Input = None; } p >> checkResult + let msbuild = Printf.ksprintf (Commands.msbuild exec (cfg.MSBUILD.Value)) + + do! requireVSUltimate cfg + + // "%MSBUILDTOOLSPATH%\msbuild.exe" portablelibrary1.sln /p:Configuration=Debug + do! msbuild "/p:Configuration=Debug" ["portablelibrary1.sln"] + + } + + let run cfg dir = processor { + let getfullpath = Commands.getfullpath dir + + // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( + // echo Test not supported except on Ultimate + // exit /b 0 + // ) + do! requireVSUltimate cfg + + // set CONTROL_FAILURES_LOG=%~dp0\control_failures.log + let setLog = Map.add "CONTROL_FAILURES_LOG" (getfullpath "control_failures.log") + + let exec p = Command.exec dir (cfg.EnvironmentVariables |> setLog) { Output = Inherit; Input = None; } p >> checkResult + + // .\ConsoleApplication1\bin\Debug\PortableTestEntry.exe + do! exec ("."/"ConsoleApplication1"/"bin"/"Debug"/"PortableTestEntry.exe") "" + + } + + [] + let portable () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +module ``test printf`` = + let permutations = [ FSharpSuiteTestCaseData("core/printf", FSC_BASIC) ] + + [] + let printf p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module QueriesLeafExpressionConvert = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -o:test.exe -g test.fsx + do! fsc "%s -o:test.exe -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fsx + do! fsc "%s --optimize -o:test--optimize.exe -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + // echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% test.fsx + do! fsi "%s" cfg.fsi_flags ["test.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // REM fsc.exe testing + + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile2 = fileguard "test.ok" + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile2 |> NUnitConf.checkGuardExists + + + + // if exist test.ok (del /f /q test.ok) + use testOkFile3 = fileguard "test.ok" + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile3 |> NUnitConf.checkGuardExists + + } + + [] + let queriesLeafExpressionConvert () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +module QueriesNullableOperators = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let fsc_flags = cfg.fsc_flags + + // "%FSC%" %fsc_flags% -o:test.exe -g test.fsx + do! fsc "%s -o:test.exe -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fsx + do! fsc "%s --optimize -o:test--optimize.exe -g" fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + // echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% test.fsx + do! fsi "%s" cfg.fsi_flags ["test.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // REM fsc.exe testing + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile2 = fileguard "test.ok" + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile2 |> NUnitConf.checkGuardExists + + // if exist test.ok (del /f /q test.ok) + use testOkFile3 = fileguard "test.ok" + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile3 |> NUnitConf.checkGuardExists + + } + + [] + let queriesNullableOperators () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module QueriesOverIEnumerable = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + + // "%FSC%" %fsc_flags% -o:test.exe -g test.fsx + do! fsc "%s -o:test.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fsx + do! fsc "%s --optimize -o:test--optimize.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + //echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% test.fsx + do! fsi "%s" cfg.fsi_flags ["test.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + + // REM fsc.exe testing + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile2 = fileguard "test.ok" + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile2 |> NUnitConf.checkGuardExists + + + // if exist test.ok (del /f /q test.ok) + use testOkFile3 = fileguard "test.ok" + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile3 |> NUnitConf.checkGuardExists + + } + + [] + let queriesOverIEnumerable () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module QueriesOverIQueryable = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + + // "%FSC%" %fsc_flags% -o:test.exe -g test.fsx + do! fsc "%s -o:test.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fsx + do! fsc "%s --optimize -o:test--optimize.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + // echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% test.fsx + do! fsi "%s" cfg.fsi_flags ["test.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // REM fsc.exe testing + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile2 = fileguard "test.ok" + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile2 |> NUnitConf.checkGuardExists + + // if exist test.ok (del /f /q test.ok) + use testOkFile3 = fileguard "test.ok" + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile3 |> NUnitConf.checkGuardExists + + + } + + [] + let queriesOverIQueryable () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module QueriesOverOData = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%FSC%" %fsc_flags% -o:test.exe -g test.fsx + do! fsc "%s -o:test.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fsx + do! fsc "%s --optimize -o:test--optimize.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + // echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% test.fsx + do! fsi "%s" cfg.fsi_flags ["test.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // REM fsc.exe testing + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile2 = fileguard "test.ok" + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile2 |> NUnitConf.checkGuardExists + + + // if exist test.ok (del /f /q test.ok) + use testOkFile3 = fileguard "test.ok" + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile3 |> NUnitConf.checkGuardExists + + } + + [] + let queriesOverOData () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module QuotesDebugInfo = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + + // "%FSC%" %fsc_flags% --quotations-debug+ --optimize -o:test.exe -g test.fsx + do! fsc "%s --quotations-debug+ --optimize -o:test.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // "%FSC%" %fsc_flags% --quotations-debug+ --optimize -o:test--optimize.exe -g test.fsx + do! fsc "%s --quotations-debug+ --optimize -o:test--optimize.exe -g" cfg.fsc_flags ["test.fsx"] + + // "%PEVERIFY%" test--optimize.exe + do! peverify "test--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + // echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% --quotations-debug+ test.fsx + do! fsi "%s --quotations-debug+" cfg.fsi_flags ["test.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // REM fsc.exe testing + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile2 = fileguard "test.ok" + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile2 |> NUnitConf.checkGuardExists + + + // if exist test.ok (del /f /q test.ok) + use testOkFile3 = fileguard "test.ok" + // %CLIX% test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile3 |> NUnitConf.checkGuardExists + + } + + [] + let quotesDebugInfo () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module QuotesInMultipleModules = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%FSC%" %fsc_flags% -o:module1.dll --target:library module1.fsx + do! fsc "%s -o:module1.dll --target:library" cfg.fsc_flags ["module1.fsx"] + + // "%PEVERIFY%" module1.dll + do! peverify "module1.dll" + + // "%FSC%" %fsc_flags% -o:module2.exe -r:module1.dll module2.fsx + do! fsc "%s -o:module2.exe -r:module1.dll" cfg.fsc_flags ["module2.fsx"] + + // "%PEVERIFY%" module2.exe + do! peverify "module2.exe" + + // "%FSC%" %fsc_flags% --staticlink:module1 -o:module2-staticlink.exe -r:module1.dll module2.fsx + do! fsc "%s --staticlink:module1 -o:module2-staticlink.exe -r:module1.dll" cfg.fsc_flags ["module2.fsx"] + + // "%PEVERIFY%" module2-staticlink.exe + do! peverify "module2-staticlink.exe" + + // "%FSC%" %fsc_flags% -o:module1-opt.dll --target:library --optimize module1.fsx + do! fsc "%s -o:module1-opt.dll --target:library --optimize" cfg.fsc_flags ["module1.fsx"] + + // "%PEVERIFY%" module1-opt.dll + do! peverify "module1-opt.dll" + + // "%FSC%" %fsc_flags% -o:module2-opt.exe -r:module1-opt.dll --optimize module2.fsx + do! fsc "%s -o:module2-opt.exe -r:module1-opt.dll --optimize" cfg.fsc_flags ["module2.fsx"] + + // "%PEVERIFY%" module2-opt.exe + do! peverify "module2-opt.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // REM fsi.exe testing + // echo TestC + log "TestC" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // "%FSI%" %fsi_flags% -r module1.dll module2.fsx + do! fsi "%s -r module1.dll" cfg.fsi_flags ["module2.fsx"] + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // REM fsc.exe testing + // echo TestD + log "TestD" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // %CLIX% module2.exe + do! exec ("."/"module2.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // %CLIX% module2-opt.exe + do! exec ("."/"module2-opt.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + // %CLIX% module2-staticlink.exe + do! exec ("."/"module2-staticlink.exe") "" + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + } + + [] + let quotesInMultipleModules () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + + +module Reflect = + + [] + let reflect p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``test resources`` = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let resgen = Printf.ksprintf (Commands.resgen exec cfg.RESGEN) + + // REM Note that you have a VS SDK dependence here. + // "%RESGEN%" /compile Resources.resx + do! resgen "/compile" ["Resources.resx"] + + // "%FSC%" %fsc_flags% --resource:Resources.resources -o:test-embed.exe -g test.fs + do! fsc "%s --resource:Resources.resources -o:test-embed.exe -g" cfg.fsc_flags ["test.fs"] + + // "%PEVERIFY%" test-embed.exe + do! peverify "test-embed.exe" + + // "%FSC%" %fsc_flags% --linkresource:Resources.resources -o:test-link.exe -g test.fs + do! fsc "%s --linkresource:Resources.resources -o:test-link.exe -g" cfg.fsc_flags ["test.fs"] + + // "%PEVERIFY%" test-link.exe + do! peverify "test-link.exe" + + // "%FSC%" %fsc_flags% --resource:Resources.resources,ResourceName.resources -o:test-embed-named.exe -g test.fs + do! fsc "%s --resource:Resources.resources,ResourceName.resources -o:test-embed-named.exe -g" cfg.fsc_flags ["test.fs"] + + // "%PEVERIFY%" test-embed-named.exe + do! peverify "test-embed-named.exe" + + // "%FSC%" %fsc_flags% --linkresource:Resources.resources,ResourceName.resources -o:test-link-named.exe -g test.fs + do! fsc "%s --linkresource:Resources.resources,ResourceName.resources -o:test-link-named.exe -g" cfg.fsc_flags ["test.fs"] + + // "%PEVERIFY%" test-link-named.exe + do! peverify "test-link-named.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + + // %CLIX% .\test-embed.exe + do! exec ("."/"test-embed.exe") "" + + // %CLIX% .\test-link.exe + do! exec ("."/"test-link.exe") "" + + // %CLIX% .\test-link-named.exe ResourceName + do! exec ("."/"test-link-named.exe") "ResourceName" + + // %CLIX% .\test-embed-named.exe ResourceName + do! exec ("."/"test-embed-named.exe") "ResourceName" + + } + + [] + let resources () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +module ``test seq`` = + + [] + let seq p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module Subtype = + + [] + let subtype p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module Syntax = + + [] + let syntax p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module Tlr = + + [] + let tlr p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module Topinit = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let fsc_flags = cfg.fsc_flags + + + // "%FSC%" %fsc_flags% --optimize -o both69514.exe -g lib69514.fs app69514.fs + do! fsc "%s --optimize -o both69514.exe -g" fsc_flags ["lib69514.fs"; "app69514.fs"] + + // "%PEVERIFY%" both69514.exe + do! peverify "both69514.exe" + + // "%FSC%" %fsc_flags% --optimize- -o both69514-noopt.exe -g lib69514.fs app69514.fs + do! fsc "%s --optimize- -o both69514-noopt.exe -g" fsc_flags ["lib69514.fs"; "app69514.fs"] + + // "%PEVERIFY%" both69514-noopt.exe + do! peverify "both69514-noopt.exe" + + + // "%FSC%" %fsc_flags% --optimize -a -g lib69514.fs + do! fsc "%s --optimize -a -g" fsc_flags ["lib69514.fs"] + + // "%PEVERIFY%" lib69514.dll + do! peverify "lib69514.dll" + + // "%FSC%" %fsc_flags% --optimize -r:lib69514.dll -g app69514.fs + do! fsc "%s --optimize -r:lib69514.dll -g" fsc_flags ["app69514.fs"] + + // "%PEVERIFY%" app69514.exe + do! peverify "app69514.exe" + + // "%FSC%" %fsc_flags% --optimize- -o:lib69514-noopt.dll -a -g lib69514.fs + do! fsc "%s --optimize- -o:lib69514-noopt.dll -a -g" fsc_flags ["lib69514.fs"] + + // "%PEVERIFY%" lib69514-noopt.dll + do! peverify "lib69514-noopt.dll" + + // "%FSC%" %fsc_flags% --optimize- -r:lib69514-noopt.dll -o:app69514-noopt.exe -g app69514.fs + do! fsc "%s --optimize- -r:lib69514-noopt.dll -o:app69514-noopt.exe -g" fsc_flags ["app69514.fs"] + + // "%PEVERIFY%" app69514-noopt.exe + do! peverify "app69514-noopt.exe" + + + // "%FSC%" %fsc_flags% --optimize- -o:lib69514-noopt-withsig.dll -a -g lib69514.fsi lib69514.fs + do! fsc "%s --optimize- -o:lib69514-noopt-withsig.dll -a -g" fsc_flags ["lib69514.fsi"; "lib69514.fs"] + + // "%PEVERIFY%" lib69514-noopt-withsig.dll + do! peverify "lib69514-noopt-withsig.dll" + + // "%FSC%" %fsc_flags% --optimize- -r:lib69514-noopt-withsig.dll -o:app69514-noopt-withsig.exe -g app69514.fs + do! fsc "%s --optimize- -r:lib69514-noopt-withsig.dll -o:app69514-noopt-withsig.exe -g" fsc_flags ["app69514.fs"] + + // "%PEVERIFY%" app69514-noopt-withsig.exe + do! peverify "app69514-noopt-withsig.exe" + + // "%FSC%" %fsc_flags% -o:lib69514-withsig.dll -a -g lib69514.fsi lib69514.fs + do! fsc "%s -o:lib69514-withsig.dll -a -g" fsc_flags ["lib69514.fsi"; "lib69514.fs"] + + // "%PEVERIFY%" lib69514-withsig.dll + do! peverify "lib69514-withsig.dll" + + // "%FSC%" %fsc_flags% -r:lib69514-withsig.dll -o:app69514-withsig.exe -g app69514.fs + do! fsc "%s -r:lib69514-withsig.dll -o:app69514-withsig.exe -g" fsc_flags ["app69514.fs"] + + // "%PEVERIFY%" app69514-withsig.exe + do! peverify "app69514-withsig.exe" + + + // "%FSC%" %fsc_flags% -o:lib.dll -a -g lib.ml + do! fsc "%s -o:lib.dll -a -g" fsc_flags ["lib.ml"] + + // "%PEVERIFY%" lib.dll + do! peverify "lib.dll" + + // %CSC% /nologo /r:"%FSCOREDLLPATH%" /r:lib.dll /out:test.exe test.cs + do! csc """/nologo /r:"%s" /r:lib.dll /out:test.exe """ cfg.FSCOREDLLPATH ["test.cs"] + + // "%FSC%" %fsc_flags% --optimize -o:lib--optimize.dll -a -g lib.ml + do! fsc "%s --optimize -o:lib--optimize.dll -a -g" fsc_flags ["lib.ml"] + + // "%PEVERIFY%" lib--optimize.dll + do! peverify "lib--optimize.dll" + + // %CSC% /nologo /r:"%FSCOREDLLPATH%" /r:lib--optimize.dll /out:test--optimize.exe test.cs + do! csc """/nologo /r:"%s" /r:lib--optimize.dll /out:test--optimize.exe""" cfg.FSCOREDLLPATH ["test.cs"] + + // set dicases= flag_deterministic_init1.fs lib_deterministic_init1.fs flag_deterministic_init2.fs lib_deterministic_init2.fs flag_deterministic_init3.fs lib_deterministic_init3.fs flag_deterministic_init4.fs lib_deterministic_init4.fs flag_deterministic_init5.fs lib_deterministic_init5.fs flag_deterministic_init6.fs lib_deterministic_init6.fs flag_deterministic_init7.fs lib_deterministic_init7.fs flag_deterministic_init8.fs lib_deterministic_init8.fs flag_deterministic_init9.fs lib_deterministic_init9.fs flag_deterministic_init10.fs lib_deterministic_init10.fs flag_deterministic_init11.fs lib_deterministic_init11.fs flag_deterministic_init12.fs lib_deterministic_init12.fs flag_deterministic_init13.fs lib_deterministic_init13.fs flag_deterministic_init14.fs lib_deterministic_init14.fs flag_deterministic_init15.fs lib_deterministic_init15.fs flag_deterministic_init16.fs lib_deterministic_init16.fs flag_deterministic_init17.fs lib_deterministic_init17.fs flag_deterministic_init18.fs lib_deterministic_init18.fs flag_deterministic_init19.fs lib_deterministic_init19.fs flag_deterministic_init20.fs lib_deterministic_init20.fs flag_deterministic_init21.fs lib_deterministic_init21.fs flag_deterministic_init22.fs lib_deterministic_init22.fs flag_deterministic_init23.fs lib_deterministic_init23.fs flag_deterministic_init24.fs lib_deterministic_init24.fs flag_deterministic_init25.fs lib_deterministic_init25.fs flag_deterministic_init26.fs lib_deterministic_init26.fs flag_deterministic_init27.fs lib_deterministic_init27.fs flag_deterministic_init28.fs lib_deterministic_init28.fs flag_deterministic_init29.fs lib_deterministic_init29.fs flag_deterministic_init30.fs lib_deterministic_init30.fs flag_deterministic_init31.fs lib_deterministic_init31.fs flag_deterministic_init32.fs lib_deterministic_init32.fs flag_deterministic_init33.fs lib_deterministic_init33.fs flag_deterministic_init34.fs lib_deterministic_init34.fs flag_deterministic_init35.fs lib_deterministic_init35.fs flag_deterministic_init36.fs lib_deterministic_init36.fs flag_deterministic_init37.fs lib_deterministic_init37.fs flag_deterministic_init38.fs lib_deterministic_init38.fs flag_deterministic_init39.fs lib_deterministic_init39.fs flag_deterministic_init40.fs lib_deterministic_init40.fs flag_deterministic_init41.fs lib_deterministic_init41.fs flag_deterministic_init42.fs lib_deterministic_init42.fs flag_deterministic_init43.fs lib_deterministic_init43.fs flag_deterministic_init44.fs lib_deterministic_init44.fs flag_deterministic_init45.fs lib_deterministic_init45.fs flag_deterministic_init46.fs lib_deterministic_init46.fs flag_deterministic_init47.fs lib_deterministic_init47.fs flag_deterministic_init48.fs lib_deterministic_init48.fs flag_deterministic_init49.fs lib_deterministic_init49.fs flag_deterministic_init50.fs lib_deterministic_init50.fs flag_deterministic_init51.fs lib_deterministic_init51.fs flag_deterministic_init52.fs lib_deterministic_init52.fs flag_deterministic_init53.fs lib_deterministic_init53.fs flag_deterministic_init54.fs lib_deterministic_init54.fs flag_deterministic_init55.fs lib_deterministic_init55.fs flag_deterministic_init56.fs lib_deterministic_init56.fs flag_deterministic_init57.fs lib_deterministic_init57.fs flag_deterministic_init58.fs lib_deterministic_init58.fs flag_deterministic_init59.fs lib_deterministic_init59.fs flag_deterministic_init60.fs lib_deterministic_init60.fs flag_deterministic_init61.fs lib_deterministic_init61.fs flag_deterministic_init62.fs lib_deterministic_init62.fs flag_deterministic_init63.fs lib_deterministic_init63.fs flag_deterministic_init64.fs lib_deterministic_init64.fs flag_deterministic_init65.fs lib_deterministic_init65.fs flag_deterministic_init66.fs lib_deterministic_init66.fs flag_deterministic_init67.fs lib_deterministic_init67.fs flag_deterministic_init68.fs lib_deterministic_init68.fs flag_deterministic_init69.fs lib_deterministic_init69.fs flag_deterministic_init70.fs lib_deterministic_init70.fs flag_deterministic_init71.fs lib_deterministic_init71.fs flag_deterministic_init72.fs lib_deterministic_init72.fs flag_deterministic_init73.fs lib_deterministic_init73.fs flag_deterministic_init74.fs lib_deterministic_init74.fs flag_deterministic_init75.fs lib_deterministic_init75.fs flag_deterministic_init76.fs lib_deterministic_init76.fs flag_deterministic_init77.fs lib_deterministic_init77.fs flag_deterministic_init78.fs lib_deterministic_init78.fs flag_deterministic_init79.fs lib_deterministic_init79.fs flag_deterministic_init80.fs lib_deterministic_init80.fs flag_deterministic_init81.fs lib_deterministic_init81.fs flag_deterministic_init82.fs lib_deterministic_init82.fs flag_deterministic_init83.fs lib_deterministic_init83.fs flag_deterministic_init84.fs lib_deterministic_init84.fs flag_deterministic_init85.fs lib_deterministic_init85.fs + let dicases = ["flag_deterministic_init1.fs"; "lib_deterministic_init1.fs"; "flag_deterministic_init2.fs"; "lib_deterministic_init2.fs"; "flag_deterministic_init3.fs"; "lib_deterministic_init3.fs"; "flag_deterministic_init4.fs"; "lib_deterministic_init4.fs"; "flag_deterministic_init5.fs"; "lib_deterministic_init5.fs"; "flag_deterministic_init6.fs"; "lib_deterministic_init6.fs"; "flag_deterministic_init7.fs"; "lib_deterministic_init7.fs"; "flag_deterministic_init8.fs"; "lib_deterministic_init8.fs"; "flag_deterministic_init9.fs"; "lib_deterministic_init9.fs"; "flag_deterministic_init10.fs"; "lib_deterministic_init10.fs"; "flag_deterministic_init11.fs"; "lib_deterministic_init11.fs"; "flag_deterministic_init12.fs"; "lib_deterministic_init12.fs"; "flag_deterministic_init13.fs"; "lib_deterministic_init13.fs"; "flag_deterministic_init14.fs"; "lib_deterministic_init14.fs"; "flag_deterministic_init15.fs"; "lib_deterministic_init15.fs"; "flag_deterministic_init16.fs"; "lib_deterministic_init16.fs"; "flag_deterministic_init17.fs"; "lib_deterministic_init17.fs"; "flag_deterministic_init18.fs"; "lib_deterministic_init18.fs"; "flag_deterministic_init19.fs"; "lib_deterministic_init19.fs"; "flag_deterministic_init20.fs"; "lib_deterministic_init20.fs"; "flag_deterministic_init21.fs"; "lib_deterministic_init21.fs"; "flag_deterministic_init22.fs"; "lib_deterministic_init22.fs"; "flag_deterministic_init23.fs"; "lib_deterministic_init23.fs"; "flag_deterministic_init24.fs"; "lib_deterministic_init24.fs"; "flag_deterministic_init25.fs"; "lib_deterministic_init25.fs"; "flag_deterministic_init26.fs"; "lib_deterministic_init26.fs"; "flag_deterministic_init27.fs"; "lib_deterministic_init27.fs"; "flag_deterministic_init28.fs"; "lib_deterministic_init28.fs"; "flag_deterministic_init29.fs"; "lib_deterministic_init29.fs"; "flag_deterministic_init30.fs"; "lib_deterministic_init30.fs"; "flag_deterministic_init31.fs"; "lib_deterministic_init31.fs"; "flag_deterministic_init32.fs"; "lib_deterministic_init32.fs"; "flag_deterministic_init33.fs"; "lib_deterministic_init33.fs"; "flag_deterministic_init34.fs"; "lib_deterministic_init34.fs"; "flag_deterministic_init35.fs"; "lib_deterministic_init35.fs"; "flag_deterministic_init36.fs"; "lib_deterministic_init36.fs"; "flag_deterministic_init37.fs"; "lib_deterministic_init37.fs"; "flag_deterministic_init38.fs"; "lib_deterministic_init38.fs"; "flag_deterministic_init39.fs"; "lib_deterministic_init39.fs"; "flag_deterministic_init40.fs"; "lib_deterministic_init40.fs"; "flag_deterministic_init41.fs"; "lib_deterministic_init41.fs"; "flag_deterministic_init42.fs"; "lib_deterministic_init42.fs"; "flag_deterministic_init43.fs"; "lib_deterministic_init43.fs"; "flag_deterministic_init44.fs"; "lib_deterministic_init44.fs"; "flag_deterministic_init45.fs"; "lib_deterministic_init45.fs"; "flag_deterministic_init46.fs"; "lib_deterministic_init46.fs"; "flag_deterministic_init47.fs"; "lib_deterministic_init47.fs"; "flag_deterministic_init48.fs"; "lib_deterministic_init48.fs"; "flag_deterministic_init49.fs"; "lib_deterministic_init49.fs"; "flag_deterministic_init50.fs"; "lib_deterministic_init50.fs"; "flag_deterministic_init51.fs"; "lib_deterministic_init51.fs"; "flag_deterministic_init52.fs"; "lib_deterministic_init52.fs"; "flag_deterministic_init53.fs"; "lib_deterministic_init53.fs"; "flag_deterministic_init54.fs"; "lib_deterministic_init54.fs"; "flag_deterministic_init55.fs"; "lib_deterministic_init55.fs"; "flag_deterministic_init56.fs"; "lib_deterministic_init56.fs"; "flag_deterministic_init57.fs"; "lib_deterministic_init57.fs"; "flag_deterministic_init58.fs"; "lib_deterministic_init58.fs"; "flag_deterministic_init59.fs"; "lib_deterministic_init59.fs"; "flag_deterministic_init60.fs"; "lib_deterministic_init60.fs"; "flag_deterministic_init61.fs"; "lib_deterministic_init61.fs"; "flag_deterministic_init62.fs"; "lib_deterministic_init62.fs"; "flag_deterministic_init63.fs"; "lib_deterministic_init63.fs"; "flag_deterministic_init64.fs"; "lib_deterministic_init64.fs"; "flag_deterministic_init65.fs"; "lib_deterministic_init65.fs"; "flag_deterministic_init66.fs"; "lib_deterministic_init66.fs"; "flag_deterministic_init67.fs"; "lib_deterministic_init67.fs"; "flag_deterministic_init68.fs"; "lib_deterministic_init68.fs"; "flag_deterministic_init69.fs"; "lib_deterministic_init69.fs"; "flag_deterministic_init70.fs"; "lib_deterministic_init70.fs"; "flag_deterministic_init71.fs"; "lib_deterministic_init71.fs"; "flag_deterministic_init72.fs"; "lib_deterministic_init72.fs"; "flag_deterministic_init73.fs"; "lib_deterministic_init73.fs"; "flag_deterministic_init74.fs"; "lib_deterministic_init74.fs"; "flag_deterministic_init75.fs"; "lib_deterministic_init75.fs"; "flag_deterministic_init76.fs"; "lib_deterministic_init76.fs"; "flag_deterministic_init77.fs"; "lib_deterministic_init77.fs"; "flag_deterministic_init78.fs"; "lib_deterministic_init78.fs"; "flag_deterministic_init79.fs"; "lib_deterministic_init79.fs"; "flag_deterministic_init80.fs"; "lib_deterministic_init80.fs"; "flag_deterministic_init81.fs"; "lib_deterministic_init81.fs"; "flag_deterministic_init82.fs"; "lib_deterministic_init82.fs"; "flag_deterministic_init83.fs"; "lib_deterministic_init83.fs"; "flag_deterministic_init84.fs"; "lib_deterministic_init84.fs"; "flag_deterministic_init85.fs"; "lib_deterministic_init85.fs"] + + // "%FSC%" %fsc_flags% --optimize- -o test_deterministic_init.exe %dicases% test_deterministic_init.fs + do! fsc "%s --optimize- -o test_deterministic_init.exe" fsc_flags (dicases @ ["test_deterministic_init.fs"]) + + // "%PEVERIFY%" test_deterministic_init.exe + do! peverify "test_deterministic_init.exe" + + // "%FSC%" %fsc_flags% --optimize -o test_deterministic_init--optimize.exe %dicases% test_deterministic_init.fs + do! fsc "%s --optimize -o test_deterministic_init--optimize.exe" fsc_flags (dicases @ ["test_deterministic_init.fs"]) + + // "%PEVERIFY%" test_deterministic_init--optimize.exe + do! peverify "test_deterministic_init--optimize.exe" + + + // "%FSC%" %fsc_flags% --optimize- -a -o test_deterministic_init_lib.dll %dicases% + do! fsc "%s --optimize- -a -o test_deterministic_init_lib.dll" fsc_flags dicases + + // "%PEVERIFY%" test_deterministic_init_lib.dll + do! peverify "test_deterministic_init_lib.dll" + + // "%FSC%" %fsc_flags% --optimize- -r test_deterministic_init_lib.dll -o test_deterministic_init_exe.exe test_deterministic_init.fs + do! fsc "%s --optimize- -r test_deterministic_init_lib.dll -o test_deterministic_init_exe.exe" fsc_flags ["test_deterministic_init.fs"] + + // "%PEVERIFY%" test_deterministic_init_exe.exe + do! peverify "test_deterministic_init_exe.exe" + + // "%FSC%" %fsc_flags% --optimize -a -o test_deterministic_init_lib--optimize.dll %dicases% + do! fsc "%s --optimize -a -o test_deterministic_init_lib--optimize.dll" fsc_flags dicases + + // "%PEVERIFY%" test_deterministic_init_lib--optimize.dll + do! peverify "test_deterministic_init_lib--optimize.dll" + + // "%FSC%" %fsc_flags% --optimize -r test_deterministic_init_lib--optimize.dll -o test_deterministic_init_exe--optimize.exe test_deterministic_init.fs + do! fsc "%s --optimize -r test_deterministic_init_lib--optimize.dll -o test_deterministic_init_exe--optimize.exe" fsc_flags ["test_deterministic_init.fs"] + + // "%PEVERIFY%" test_deterministic_init_exe--optimize.exe + do! peverify "test_deterministic_init_exe--optimize.exe" + + + // set static_init_cases= test0.fs test1.fs test2.fs test3.fs test4.fs test5.fs test6.fs + let static_init_cases = [ "test0.fs"; "test1.fs"; "test2.fs"; "test3.fs"; "test4.fs"; "test5.fs"; "test6.fs" ] + + // "%FSC%" %fsc_flags% --optimize- -o test_static_init.exe %static_init_cases% static-main.fs + do! fsc "%s --optimize- -o test_static_init.exe" fsc_flags (static_init_cases @ ["static-main.fs"]) + + // "%PEVERIFY%" test_static_init.exe + do! peverify "test_static_init.exe" + + // "%FSC%" %fsc_flags% --optimize -o test_static_init--optimize.exe %static_init_cases% static-main.fs + do! fsc "%s --optimize -o test_static_init--optimize.exe" fsc_flags (static_init_cases @ [ "static-main.fs" ]) + + // "%PEVERIFY%" test_static_init--optimize.exe + do! peverify "test_static_init--optimize.exe" + + + // "%FSC%" %fsc_flags% --optimize- -a -o test_static_init_lib.dll %static_init_cases% + do! fsc "%s --optimize- -a -o test_static_init_lib.dll" fsc_flags static_init_cases + + // "%PEVERIFY%" test_static_init_lib.dll + do! peverify "test_static_init_lib.dll" + + // "%FSC%" %fsc_flags% --optimize- -r test_static_init_lib.dll -o test_static_init_exe.exe static-main.fs + do! fsc "%s --optimize- -r test_static_init_lib.dll -o test_static_init_exe.exe" fsc_flags ["static-main.fs"] + + // "%PEVERIFY%" test_static_init_exe.exe + do! peverify "test_static_init_exe.exe" + + // "%FSC%" %fsc_flags% --optimize -a -o test_static_init_lib--optimize.dll %static_init_cases% + do! fsc "%s --optimize -a -o test_static_init_lib--optimize.dll" fsc_flags static_init_cases + + // "%PEVERIFY%" test_static_init_lib--optimize.dll + do! peverify "test_static_init_lib--optimize.dll" + + // "%FSC%" %fsc_flags% --optimize -r test_static_init_lib--optimize.dll -o test_static_init_exe--optimize.exe static-main.fs + do! fsc "%s --optimize -r test_static_init_lib--optimize.dll -o test_static_init_exe--optimize.exe" fsc_flags ["static-main.fs"] + + // "%PEVERIFY%" test_static_init_exe--optimize.exe + do! peverify "test_static_init_exe--optimize.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + + // %CLIX% .\test.exe + do! exec ("."/"test.exe") "" + + // %CLIX% .\test--optimize.exe + do! exec ("."/"test--optimize.exe") "" + + // %CLIX% .\test_deterministic_init.exe + do! exec ("."/"test_deterministic_init.exe") "" + + // %CLIX% .\test_deterministic_init--optimize.exe + do! exec ("."/"test_deterministic_init--optimize.exe") "" + + // %CLIX% .\test_deterministic_init_exe.exe + do! exec ("."/"test_deterministic_init_exe.exe") "" + + // %CLIX% .\test_deterministic_init_exe--optimize.exe + do! exec ("."/"test_deterministic_init_exe--optimize.exe") "" + + + // %CLIX% .\test_static_init.exe + do! exec ("."/"test_static_init.exe") "" + + // %CLIX% .\test_static_init--optimize.exe + do! exec ("."/"test_static_init--optimize.exe") "" + + // %CLIX% .\test_static_init_exe.exe + do! exec ("."/"test_static_init_exe.exe") "" + + // %CLIX% .\test_static_init_exe--optimize.exe + do! exec ("."/"test_static_init_exe--optimize.exe") "" + + + } + + [] + let topinit () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +module UnitsOfMeasure = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%FSC%" %fsc_flags% --optimize- -o:test.exe -g test.fs + do! fsc "%s --optimize- -o:test.exe -g" cfg.fsc_flags ["test.fs"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% .\test.exe + do! exec ("."/"test.exe") "" + + do! testOkFile |> NUnitConf.checkGuardExists + } + + [] + let unitsOfMeasure () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module Verify = + + [] + let verify () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let peverify' = Printf.ksprintf (Commands.peverify exec cfg.PEVERIFY) + let getfullpath = Commands.getfullpath dir + + // "%PEVERIFY%" "%FSCOREDLLPATH%" + do! peverify cfg.FSCOREDLLPATH + + // "%PEVERIFY%" "%FSCOREDLL20PATH%" + do! peverify cfg.FSCOREDLL20PATH + + // "%PEVERIFY%" "%FSCOREDLLPORTABLEPATH%" + do! peverify cfg.FSCOREDLLPORTABLEPATH + + // "%PEVERIFY%" "%FSCOREDLLNETCOREPATH%" + do! peverify cfg.FSCOREDLLNETCOREPATH + + // "%PEVERIFY%" "%FSCOREDLLNETCORE78PATH%" + do! peverify cfg.FSCOREDLLNETCORE78PATH + + // "%PEVERIFY%" "%FSCOREDLLNETCORE259PATH%" + do! peverify cfg.FSCOREDLLNETCORE259PATH + + // "%PEVERIFY%" "%FSCBinPath%\FSharp.Build.dll" + do! peverify (cfg.FSCBinPath/"FSharp.Build.dll") + + // REM Use /MD because this contains some P/Invoke code + // "%PEVERIFY%" /MD "%FSCBinPath%\FSharp.Compiler.dll" + do! peverify' """/MD "%s" """ (cfg.FSCBinPath/"FSharp.Compiler.dll") + + // "%PEVERIFY%" "%FSCBinPath%\fsi.exe" + do! peverify (cfg.FSCBinPath/"fsi.exe") + + // "%PEVERIFY%" "%FSCBinPath%\FSharp.Compiler.Interactive.Settings.dll" + do! peverify (cfg.FSCBinPath/"FSharp.Compiler.Interactive.Settings.dll") + + // "%FSC%" %fsc_flags% -o:xmlverify.exe -g xmlverify.fs + do! fsc "%s -o:xmlverify.exe -g" cfg.fsc_flags ["xmlverify.fs"] + + // "%PEVERIFY%" xmlverify.exe + do! peverify "xmlverify.exe" + + // REM == Calc correct path to FSharp.Core.dll no matter what arch we are on + // call :SetFSCoreXMLPath "%FSCOREDLLPATH%" + // :SetFSCoreXMLPath + // set FSHARPCOREXML=%~dpn1.xml + let FSharpCoreXml = Path.ChangeExtension(cfg.FSCOREDLLPATH, ".xml") |> getfullpath + + // %CLIX% xmlverify.exe "%FSHARPCOREXML%" + do! exec ("."/"xmlverify.exe") FSharpCoreXml + + }) diff --git a/tests/fsharp/nunitConf.fs b/tests/fsharp/nunitConf.fs new file mode 100644 index 00000000000..a225502b2e7 --- /dev/null +++ b/tests/fsharp/nunitConf.fs @@ -0,0 +1,379 @@ +module NUnitConf + +open System +open System.IO +open NUnit.Framework + +open UpdateCmd +open TestConfig +open PlatformHelpers +open FSharpTestSuiteTypes + +let checkTestResult result = + match result with + | Success () -> () + | Failure (GenericError msg) -> Assert.Fail (msg) + | Failure (ProcessExecError (err, msg)) -> Assert.Fail (sprintf "ERRORLEVEL %i %s" err msg) + | Failure (Skipped msg) -> Assert.Ignore(sprintf "skipped. Reason: %s" msg) + +let checkResult result = + match result with + | CmdResult.ErrorLevel err -> let x = err, (sprintf "ERRORLEVEL %d" err) in Failure (RunError.ProcessExecError x) + | CmdResult.Success -> Success () + +let skip msg () = Failure (Skipped msg) +let genericError msg () = Failure (GenericError msg) +let errorLevel exitCode msg () = Failure (ProcessExecError (exitCode,msg)) + +let envVars () = + System.Environment.GetEnvironmentVariables () + |> Seq.cast + |> Seq.map (fun d -> d.Key :?> string, d.Value :?> string) + |> Map.ofSeq + +let defaultConfigurationName = +#if !DEBUG + DEBUG +#else + RELEASE +#endif + +let parseConfigurationName (name: string) = + match name.ToUpper() with + | "RELEASE" -> RELEASE + | "DEBUG" -> DEBUG + | s -> failwithf "invalid env var FSHARP_TEST_SUITE_CONFIGURATION '%s'" s + + +let initializeSuite () = + + let configurationName = defaultConfigurationName + + let doNgen = true; + + let FSCBinPath = __SOURCE_DIRECTORY__/".."/".."/(sprintf "%O" configurationName)/"net40"/"bin" + + let mapWithDefaults defaults m = + Seq.concat [ (Map.toSeq defaults) ; (Map.toSeq m) ] |> Map.ofSeq + + let env = + envVars () + |> mapWithDefaults ( [ "FSCBINPATH", FSCBinPath ] |> Map.ofList ) + + let configurationName = + match env |> Map.tryFind "FSHARP_TEST_SUITE_CONFIGURATION" |> Option.map parseConfigurationName with + | Some confName -> confName + | None -> configurationName + + processor { + do! updateCmd env { Configuration = configurationName; Ngen = doNgen; } + |> Attempt.Run + |> function Success () -> Success () | Failure msg -> genericError msg () + + let cfg = + let c = config env + let usedEnvVars = + c.EnvironmentVariables + |> Map.add "FSC" c.FSC + { c with EnvironmentVariables = usedEnvVars } + + logConfig cfg + + let directoryExists = Commands.directoryExists (Path.GetTempPath()) >> Option.isSome + + let checkfscBinPath () = processor { + + let fscBinPath = cfg.EnvironmentVariables |> Map.tryFind "FSCBINPATH" + return! + match fscBinPath with + | Some dir when directoryExists dir -> Success + | None -> genericError "environment variable 'FSCBinPath' is required to be a valid directory, is not set" + | Some dir -> genericError (sprintf "environment variable 'FSCBinPath' is required to be a valid directory, but is '%s'" dir) + } + + let smokeTest () = processor { + let tempFile ext = + let p = Path.ChangeExtension( Path.GetTempFileName(), ext) + File.AppendAllText (p, """printfn "ciao"; exit 0""") + p + + let tempDir = Commands.createTempDir () + let exec exe args = + log "%s %s" exe args + use toLog = redirectToLog () + Process.exec { RedirectError = Some toLog.Post; RedirectOutput = Some toLog.Post; RedirectInput = None } tempDir cfg.EnvironmentVariables exe args + + do! Commands.fsc exec cfg.FSC "" [ tempFile ".fs" ] |> checkResult + + do! Commands.fsi exec cfg.FSI "" [ tempFile ".fsx" ] |> checkResult + + } + + do! checkfscBinPath () + + do! smokeTest () + + return cfg + } + + +let suiteHelpers = lazy ( + initializeSuite () + |> Attempt.Run + |> function Success x -> x | Failure err -> failwith (sprintf "Error %A" err) +) + +[] +type public InitializeSuiteAttribute () = + inherit TestActionAttribute() + + override x.BeforeTest details = + if details.IsSuite + then suiteHelpers.Force() |> ignore + + override x.AfterTest details = + () + + override x.Targets with get() = ActionTargets.Test ||| ActionTargets.Suite + + +[] +() + +module FSharpTestSuite = + + let getTagsOfFile path = + match File.ReadLines(path) |> Seq.take 5 |> Seq.tryFind (fun s -> s.StartsWith("// #")) with + | None -> [] + | Some line -> + line.TrimStart('/').Split([| '#' |], StringSplitOptions.RemoveEmptyEntries) + |> Seq.map (fun s -> s.Trim()) + |> Seq.filter (fun s -> s.Length > 0) + |> Seq.distinct + |> Seq.toList + + let getTestFileMetadata dir = + Directory.EnumerateFiles(dir, "*.fs*") + |> Seq.toList + |> List.collect getTagsOfFile + + let parseTestLst path = + let dir = Path.GetDirectoryName(path) + let commentLine (t: string) = t.StartsWith("#") + let lines = + File.ReadAllLines(path) + |> Array.filter (not << commentLine) + |> Array.filter (not << String.IsNullOrWhiteSpace) + let parse (t: string) = + let a = t.Split([| '\t'; '\t' |], StringSplitOptions.RemoveEmptyEntries) + let testDir = Commands.getfullpath dir a.[1] + [| for x in a.[0].Split(',') do yield (x, testDir) |] + + lines |> Array.collect parse |> List.ofArray + + let ``test.lst`` = lazy ( + parseTestLst ( __SOURCE_DIRECTORY__/".."/"test.lst" ) + ) + + let getTestLstTags db dir = + let normalizePath path = + Uri(path).LocalPath + |> (fun s -> s.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)) + |> (fun s -> s.ToUpperInvariant()) + + let sameDir a = (normalizePath dir) = (normalizePath a) + let normalizedPath = normalizePath dir + db + |> List.choose (fun (tag, d) -> if sameDir d then Some tag else None) + + let fsharpSuiteDirectory = __SOURCE_DIRECTORY__ + + let setProps dir (props: NUnit.Framework.Interfaces.IPropertyBag) = + let testDir = dir |> Commands.getfullpath fsharpSuiteDirectory + + if not (Directory.Exists(testDir)) then failwithf "test directory '%s' does not exists" testDir + + let categories = [ dir ] @ (testDir |> getTestFileMetadata) @ (testDir |> getTestLstTags ``test.lst``.Value) + categories |> List.iter (fun (c: string) -> props.Add(NUnit.Framework.Internal.PropertyNames.Category, c)) + + props.Set("DIRECTORY", testDir) + + let testContext () = + let test = NUnit.Framework.TestContext.CurrentContext.Test + { Directory = test.Properties.Get("DIRECTORY") :?> string; + Config = suiteHelpers.Value } + +// parametrized test cases does not inherits properties of test ( see https://github.com/nunit/nunit/issues/548 ) +// and properties is where the custom context data is saved + +type FSharpSuiteTestAttribute(dir: string) = + inherit NUnitAttribute() + interface NUnit.Framework.Interfaces.IApplyToTest with + member x.ApplyToTest(test: NUnit.Framework.Internal.Test) = + try + test.Properties |> FSharpTestSuite.setProps dir + with ex -> + test.RunState <- NUnit.Framework.Interfaces.RunState.NotRunnable + test.Properties.Set(NUnit.Framework.Internal.PropertyNames.SkipReason, NUnit.Framework.Internal.ExceptionHelper.BuildMessage(ex)) + test.Properties.Set(NUnit.Framework.Internal.PropertyNames.ProviderStackTrace, NUnit.Framework.Internal.ExceptionHelper.BuildStackTrace(ex)) + +type FSharpSuiteTestCaseData = + inherit TestCaseData + + new (dir: string, [] arguments: Object array) as this = + { inherit TestCaseData(arguments) } + then + this.Properties |> FSharpTestSuite.setProps dir + arguments + |> Array.choose (fun a -> match a with :? Permutation as p -> Some p | _ -> None) + |> Array.iter (fun p -> this.SetCategory(sprintf "%A" p) |> ignore) + +[] +type FSharpSuiteTestCaseAttribute = + inherit TestCaseAttribute + + new (dir: string, [] arguments: Object array) as this = + { inherit TestCaseAttribute(arguments) } + then + this.Properties |> FSharpTestSuite.setProps dir + + +type FSharpSuitePermutationsAttribute(dir: string) = + inherit NUnitAttribute() + + let _builder = NUnit.Framework.Internal.Builders.NUnitTestCaseBuilder() + interface NUnit.Framework.Interfaces.ITestBuilder with + member x.BuildFrom(methodInfo, suite) = + let allPermutations = + [ FSI_FILE; FSI_STDIN; FSI_STDIN_OPT; FSI_STDIN_GUI; + FSC_BASIC; FSC_HW; FSC_O3; + GENERATED_SIGNATURE; EMPTY_SIGNATURE; EMPTY_SIGNATURE_OPT; + FSC_OPT_MINUS_DEBUG; FSC_OPT_PLUS_DEBUG; + FRENCH; SPANISH; + AS_DLL; + WRAPPER_NAMESPACE; WRAPPER_NAMESPACE_OPT + ] + |> List.map (fun p -> (new FSharpSuiteTestCaseData (dir, p))) + + allPermutations + |> List.map (fun tc -> _builder.BuildTestMethod(methodInfo, suite, tc)) + |> Seq.ofList + +module FileGuard = + let private remove path = if File.Exists(path) then Commands.rm (Path.GetTempPath()) path + + [] + type T (path: string) = + member x.Path = path + interface IDisposable with + member x.Dispose () = remove path + + let create path = + if not (Path.IsPathRooted(path)) then failwithf "path '%s' must be absolute" path + remove path + new T(path) + + let exists (guard: T) = guard.Path |> File.Exists + + +let checkGuardExists guard = processor { + if not <| (guard |> FileGuard.exists) + then return! genericError (sprintf "exit code 0 but %s file doesn't exists" (guard.Path |> Path.GetFileName)) + } + + +let check (f: Attempt<_,_>) = + f |> Attempt.Run |> checkTestResult + + +type RedirectInfo = + { Output : RedirectTo + Input : RedirectFrom option } + +and RedirectTo = + | Inherit + | Output of RedirectToType + | OutputAndError of RedirectToType + | Error of RedirectToType + +and RedirectToType = + | Overwrite of FilePath + | Append of FilePath + +and RedirectFrom = + | RedirectInput of FilePath + + +module Command = + + let logExec dir path args redirect = + let inF = + function + | None -> "" + | Some(RedirectInput l) -> sprintf " <%s" l + let redirectType = function Overwrite x -> sprintf ">%s" x | Append x -> sprintf ">>%s" x + let outF = + function + | Inherit -> "" + | Output r-> sprintf " 1%s" (redirectType r) + | OutputAndError r -> sprintf " 1%s 2>&1" (redirectType r) + | Error r -> sprintf " 2%s" (redirectType r) + sprintf "%s%s%s%s" path (match args with "" -> "" | x -> " " + x) (inF redirect.Input) (outF redirect.Output) + + let exec dir envVars redirect path args = + let { Output = o; Input = i} = redirect + + let inputWriter sources (writer: StreamWriter) = + let pipeFile name = async { + let path = Commands.getfullpath dir name + use reader = File.OpenRead (path) + use ms = new MemoryStream() + do! reader.CopyToAsync (ms) |> (Async.AwaitIAsyncResult >> Async.Ignore) + ms.Position <- 0L + try + do! ms.CopyToAsync(writer.BaseStream) |> (Async.AwaitIAsyncResult >> Async.Ignore) + do! writer.FlushAsync() |> (Async.AwaitIAsyncResult >> Async.Ignore) + with + | :? System.IO.IOException as ex -> //input closed is ok if process is closed + () + } + sources |> pipeFile |> Async.RunSynchronously + + let inF fCont cmdArgs = + match i with + | None -> fCont cmdArgs + | Some(RedirectInput l) -> fCont { cmdArgs with RedirectInput = Some (inputWriter l) } + + let openWrite rt = + let fullpath = Commands.getfullpath dir + match rt with + | Append p -> new StreamWriter (p |> fullpath, true) + | Overwrite p -> new StreamWriter (p |> fullpath, false) + + let outF fCont cmdArgs = + match o with + | RedirectTo.Inherit -> + use toLog = redirectToLog () + fCont { cmdArgs with RedirectOutput = Some (toLog.Post); RedirectError = Some (toLog.Post) } + | Output r -> + use writer = openWrite r + use outFile = redirectTo writer + use toLog = redirectToLog () + fCont { cmdArgs with RedirectOutput = Some (outFile.Post); RedirectError = Some (toLog.Post) } + | OutputAndError r -> + use writer = openWrite r + use outFile = redirectTo writer + fCont { cmdArgs with RedirectOutput = Some (outFile.Post); RedirectError = Some (outFile.Post) } + | Error r -> + use writer = openWrite r + use outFile = redirectTo writer + use toLog = redirectToLog () + fCont { cmdArgs with RedirectOutput = Some (toLog.Post); RedirectError = Some (outFile.Post) } + + let exec cmdArgs = + log "%s" (logExec dir path args redirect) + Process.exec cmdArgs dir envVars path args + + { RedirectOutput = None; RedirectError = None; RedirectInput = None } + |> (outF (inF exec)) + diff --git a/tests/fsharp/optimize/tests_optimize.fs b/tests/fsharp/optimize/tests_optimize.fs new file mode 100644 index 00000000000..f1ed301e1b7 --- /dev/null +++ b/tests/fsharp/optimize/tests_optimize.fs @@ -0,0 +1,276 @@ +module ``FSharp-Tests-Optimize`` + +open System +open System.IO +open NUnit.Framework + +open NUnitConf +open PlatformHelpers +open FSharpTestSuiteTypes + +let testContext = FSharpTestSuite.testContext + +module Analyses = + + let ``fsc >a 2>&1`` cfg dir = + let ``exec >a 2>&1`` outFile p = + Command.exec dir cfg.EnvironmentVariables { Output = OutputAndError(Overwrite(outFile)); Input = None; } p + >> checkResult + Printf.ksprintf (fun flags sources out -> Commands.fsc (``exec >a 2>&1`` out) cfg.FSC flags sources) + + let fsdiff cfg dir a b = processor { + let out = new ResizeArray() + let redirectOutputToFile path args = + log "%s %s" path args + let toLog = redirectToLog () + Process.exec { RedirectOutput = Some (function null -> () | s -> out.Add(s)); RedirectError = Some toLog.Post; RedirectInput = None; } dir cfg.EnvironmentVariables path args + do! (Commands.fsdiff redirectOutputToFile cfg.FSDIFF true a b) |> (fun _ -> Success ()) + return out.ToArray() |> List.ofArray + } + + [] + let functionSizes () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let getfullpath = Commands.getfullpath dir + let ``fsc >a 2>&1`` = ``fsc >a 2>&1`` cfg dir + let fsdiff = fsdiff cfg dir + + let outFile = "sizes.FunctionSizes.output.test.txt" + let expectedFile = "sizes.FunctionSizes.output.test.bsl" + + // echo == FunctionSizes + log "== FunctionSizes" + // "%FSC%" %fsc_flags% --nologo -O --test:FunctionSizes sizes.fs >sizes.FunctionSizes.output.test.txt 2>&1 + do! ``fsc >a 2>&1`` "%s --nologo -O --test:FunctionSizes" cfg.fsc_flags ["sizes.fs"] outFile + // if NOT EXIST sizes.FunctionSizes.output.test.bsl COPY sizes.FunctionSizes.output.test.txt sizes.FunctionSizes.output.test.bsl + ignore "used only the first time when no expected output file exists, useless" + // %FSDIFF% sizes.FunctionSizes.output.test.txt sizes.FunctionSizes.output.test.bsl > sizes.FunctionSizes.output.test.diff + let! diff = fsdiff outFile expectedFile + + do! match diff with + | [] -> Success + | l -> + NUnitConf.genericError (sprintf "'%s' and '%s' differ; %A" (getfullpath outFile) (getfullpath expectedFile) diff) + }) + + [] + let totalSizes () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let ``fsc >a 2>&1`` = ``fsc >a 2>&1`` cfg dir + let fsdiff = fsdiff cfg dir + let getfullpath = Commands.getfullpath dir + + let outFile = "sizes.TotalSizes.output.test.txt" + let expectedFile = "sizes.TotalSizes.output.test.bsl" + + // echo == TotalSizes + log "== TotalSizes" + // "%FSC%" %fsc_flags% --nologo -O --test:TotalSizes sizes.fs >sizes.TotalSizes.output.test.txt 2>&1 + do! ``fsc >a 2>&1`` "%s --nologo -O --test:TotalSizes" cfg.fsc_flags ["sizes.fs"] outFile + // if NOT EXIST sizes.TotalSizes.output.test.bsl COPY sizes.TotalSizes.output.test.txt sizes.TotalSizes.output.test.bsl + ignore "used only the first time when no expected output file exists, useless" + // %FSDIFF% sizes.TotalSizes.output.test.txt sizes.TotalSizes.output.test.bsl > sizes.TotalSizes.output.test.diff + let! diff = fsdiff outFile expectedFile + + do! match diff with + | [] -> Success + | l -> + NUnitConf.genericError (sprintf "'%s' and '%s' differ; %A" (getfullpath outFile) (getfullpath expectedFile) diff) + }) + + [] + let hasEffect () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let ``fsc >a 2>&1`` = ``fsc >a 2>&1`` cfg dir + let fsdiff = fsdiff cfg dir + let getfullpath = Commands.getfullpath dir + + let outFile = "effects.HasEffect.output.test.txt" + let expectedFile = "effects.HasEffect.output.test.bsl" + + // echo == HasEffect + log "== HasEffect" + // "%FSC%" %fsc_flags% --nologo -O --test:HasEffect effects.fs >effects.HasEffect.output.test.txt 2>&1 + do! ``fsc >a 2>&1`` "%s --nologo -O --test:HasEffect" cfg.fsc_flags ["effects.fs"] outFile + // if NOT EXIST effects.HasEffect.output.test.bsl COPY effects.HasEffect.output.test.txt effects.HasEffect.output.test.bsl + ignore "used only the first time when no expected output file exists, useless" + // %FSDIFF% effects.HasEffect.output.test.txt effects.HasEffect.output.test.bsl > effects.HasEffect.output.test.diff + let! diff = fsdiff outFile expectedFile + + do! match diff with + | [] -> Success + | l -> + NUnitConf.genericError (sprintf "'%s' and '%s' differ; %A" (getfullpath outFile) (getfullpath expectedFile) diff) + }) + + [] + let noNeedToTailcall () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let ``fsc >a 2>&1`` = ``fsc >a 2>&1`` cfg dir + let fsdiff = fsdiff cfg dir + let getfullpath = Commands.getfullpath dir + + let outFile = "tailcalls.NoNeedToTailcall.output.test.txt" + let expectedFile = "tailcalls.NoNeedToTailcall.output.test.bsl" + + // echo == NoNeedToTailcall + log "== NoNeedToTailcall" + // "%FSC%" %fsc_flags% --nologo -O --test:NoNeedToTailcall tailcalls.fs >tailcalls.NoNeedToTailcall.output.test.txt 2>&1 + do! ``fsc >a 2>&1`` "%s --nologo -O --test:NoNeedToTailcall" cfg.fsc_flags ["tailcalls.fs"] outFile + // if NOT EXIST tailcalls.NoNeedToTailcall.output.test.bsl COPY tailcalls.NoNeedToTailcall.output.test.txt tailcalls.NoNeedToTailcall.output.test.bsl + ignore "used only the first time when no expected output file exists, useless" + // %FSDIFF% tailcalls.NoNeedToTailcall.output.test.txt tailcalls.NoNeedToTailcall.output.test.bsl > tailcalls.NoNeedToTailcall.output.test.diff + let! diff = fsdiff outFile expectedFile + + do! match diff with + | [] -> Success + | l -> + NUnitConf.genericError (sprintf "'%s' and '%s' differ; %A" (getfullpath outFile) (getfullpath expectedFile) diff) + }) + + + + +module Inline = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + + // "%FSC%" %fsc_flags% -g --optimize- --target:library -o:lib.dll lib.fs + do! fsc "%s -g --optimize- --target:library -o:lib.dll" cfg.fsc_flags ["lib.fs"] + + // "%FSC%" %fsc_flags% --optimize --target:library -o:lib--optimize.dll -g lib.fs + do! fsc "%s --optimize --target:library -o:lib--optimize.dll -g" cfg.fsc_flags ["lib.fs"] + + // "%FSC%" %fsc_flags% -g --optimize- -o:test.exe test.fs -r:lib.dll + do! fsc "%s -g --optimize- -o:test.exe -r:lib.dll" cfg.fsc_flags ["test.fs "] + + // "%FSC%" %fsc_flags% --optimize -o:test--optimize.exe -g test.fs -r:lib--optimize.dll + do! fsc "%s --optimize -o:test--optimize.exe -g -r:lib--optimize.dll" cfg.fsc_flags ["test.fs "] + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let ildasm = Printf.ksprintf (Commands.ildasm exec cfg.ILDASM) + let getfullpath = Commands.getfullpath dir + + // if not exist "%ILDASM%" ( + // @echo '%ILDASM%' not found. + // goto Error + // ) + ignore "already checked at suite startup" + + // "%ILDASM%" /nobar /out=test.il test.exe + do! ildasm "/nobar /out=test.il" "test.exe" + + // "%ILDASM%" /nobar /out=test--optimize.il test--optimize.exe + do! ildasm "/nobar /out=test--optimize.il" "test--optimize.exe" + + // type test--optimize.il | find /C ".locals init" > count--optimize + let ``test--optimize.il`` = + File.ReadLines (getfullpath "test--optimize.il") + |> Seq.filter (fun line -> line.Contains(".locals init")) + |> List.ofSeq + + // for /f %%c IN (count--optimize) do (if NOT "%%c"=="0" ( + do! match ``test--optimize.il`` with + | [] -> Success + | lines -> + // echo Error: optimizations not removed. Relevant lines from IL file follow: + // type test--optimize.il | find ".locals init" + // goto SetError) + NUnitConf.genericError (sprintf "Error: optimizations not removed. Relevant lines from IL file follow: %A" lines) + // ) + + // type test.il | find /C ".locals init" > count + // for /f %%c IN (count) do ( + // set NUMELIM=%%c + // ) + let numElim = + File.ReadLines (getfullpath "test.il") + |> Seq.filter (fun line -> line.Contains(".locals init")) + |> Seq.length + + log "Ran ok - optimizations removed %d textual occurrences of optimizable identifiers from target IL" numElim + + } + + [] + let ``inline`` () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + +module Stats = + + [] + let stats () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let ildasm = Commands.ildasm exec cfg.ILDASM + let getfullpath = Commands.getfullpath dir + + // if not exist "%ILDASM%" (goto Error) + ignore "already checked at suite startup" + + // where sd.exe 2> NUL + // if not ERRORLEVEL 1 ( sd edit stats.txt ) else (attrib -r stats.txt ) + ignore "dont know" + + // "%ILDASM%" /nobar /out=FSharp.Core.il "%FSCOREDLLPATH%" + do! ildasm "/nobar /out=FSharp.Core.il" cfg.FSCOREDLLPATH + + let ``FSharp.Core.il`` = File.ReadLines(getfullpath "FSharp.Core.il") |> Seq.toList + + let contains text (s: string) = if s.Contains(text) then 1 else 0 + + // echo Counting TypeFuncs... + // type FSharp.Core.il | find /C "extends Microsoft.FSharp.TypeFunc" > count-Microsoft.FSharp-TypeFunc + let typeFunc = ``FSharp.Core.il`` |> List.sumBy (contains "extends Microsoft.FSharp.TypeFunc") + // echo Counting classes... + // type FSharp.Core.il | find /C ".class" > count-Microsoft.FSharp-.class + let classes = ``FSharp.Core.il`` |> List.sumBy (contains ".class") + // echo Counting methods... + // type FSharp.Core.il | find /C ".method" > count-Microsoft.FSharp-.method + let methods = ``FSharp.Core.il`` |> List.sumBy (contains ".method") + // echo Counting fields... + // type FSharp.Core.il | find /C ".field" > count-Microsoft.FSharp-.field + let fields = ``FSharp.Core.il`` |> List.sumBy (contains ".field") + + // for /f %%c IN (count-Microsoft.FSharp-TypeFunc) do ( + // for /f %%d IN (count-Microsoft.FSharp-.class) do ( + // for /f %%e IN (count-Microsoft.FSharp-.method) do ( + // for /f %%f IN (count-Microsoft.FSharp-.field) do ( + // echo %date%, %time%, Microsoft.FSharp-TypeFunc, %%c, Microsoft.FSharp-classes, %%d, Microsoft.FSharp-methods, %%e, , Microsoft.FSharp-fields, %%f, >> stats.txt + let date = DateTime.Today.ToString("dd/MM/yyyy") // 23/11/2006 + let time = DateTime.Now.ToString("HH:mm:ss.ff") // 16:03:23.40 + let m = sprintf "%s, %s, Microsoft.FSharp-TypeFunc, %d, Microsoft.FSharp-classes, %d, Microsoft.FSharp-methods, %d, , Microsoft.FSharp-fields, %d, " date time typeFunc classes methods fields + + log "now:" + log "%s" m + log "old (from 'stats.txt'):" + log "%s" (File.ReadAllLines(getfullpath "stats.txt") |> Seq.where (String.IsNullOrWhiteSpace >> not) |> Seq.last) + + //REVIEW test add a line to a versioned file 'stats.txt', but is not maintained anymore? + ignore (fun () -> File.AppendAllLines(getfullpath "stats.txt", [ m ]) ) + + + // ) + // ) + // ) + // ) + + }) diff --git a/tests/fsharp/packages.config b/tests/fsharp/packages.config new file mode 100644 index 00000000000..0c9dd291aa3 --- /dev/null +++ b/tests/fsharp/packages.config @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/fsharp/perf/tests_perf.fs b/tests/fsharp/perf/tests_perf.fs new file mode 100644 index 00000000000..1c57b24bb93 --- /dev/null +++ b/tests/fsharp/perf/tests_perf.fs @@ -0,0 +1,35 @@ +module ``FSharp-Tests-Perf`` + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open NUnitConf +open PlatformHelpers + +let testContext = FSharpTestSuite.testContext + + +module Graph = + + [] + let graph p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module Nbody = + + [] + let nbody p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) diff --git a/tests/fsharp/regression/tests_regression.fs b/tests/fsharp/regression/tests_regression.fs new file mode 100644 index 00000000000..ec737a90e91 --- /dev/null +++ b/tests/fsharp/regression/tests_regression.fs @@ -0,0 +1,235 @@ +module ``FSharp-Tests-Regression`` + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open NUnitConf +open PlatformHelpers + +let testContext = FSharpTestSuite.testContext + + +module ``26`` = + + [] + let ``26`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``321`` = + + [] + let ``321`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``655`` = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%FSC%" %fsc_flags% -a -o:pack.dll xlibC.ml + do! fsc "%s -a -o:pack.dll" cfg.fsc_flags ["xlibC.ml"] + + // "%PEVERIFY%" pack.dll + do! peverify "pack.dll" + + // "%FSC%" %fsc_flags% -o:test.exe -r:pack.dll main.fs + do! fsc "%s -o:test.exe -r:pack.dll" cfg.fsc_flags ["main.fs"] + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% test.exe + do! exec ("."/"test.exe") "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + } + + [] + let ``655`` () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + +[] +module ``656`` = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Printf.ksprintf (Commands.peverify exec cfg.PEVERIFY) + + //REVIEW ILX_CONFIG? + let ILX_CONFIG = "" + + // "%FSC%" %fsc_flags% -o:pack%ILX_CONFIG%.exe misc.fs mathhelper.fs filehelper.fs formshelper.fs plot.fs traj.fs playerrecord.fs trackedplayers.fs form.fs + do! fsc "%s -o:pack%s.exe" cfg.fsc_flags ILX_CONFIG ["misc.fs mathhelper.fs filehelper.fs formshelper.fs plot.fs traj.fs playerrecord.fs trackedplayers.fs form.fs"] + + // "%PEVERIFY%" pack%ILX_CONFIG%.exe + do! peverify "pack%s.exe" ILX_CONFIG + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + //REVIEW ILX_CONFIG? + let ILX_CONFIG = "" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% pack%ILX_CONFIG%.exe + do! exec ("."/(sprintf "pack%s.exe" ILX_CONFIG)) "" + + // if NOT EXIST test.ok goto SetError + do! testOkFile |> NUnitConf.checkGuardExists + + return! NUnitConf.genericError "env var 'ILX_CONFIG' not found, using '' as default the test pass" + } + + [] + let ``656`` () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module ``83`` = + + [] + let ``83`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + // if "%CLR_SUPPORTS_WINFORMS%"=="false" ( goto Skip) + do! match cfg.EnvironmentVariables |> Map.tryFind "CLR_SUPPORTS_WINFORMS" |> Option.map (fun s -> s.ToLower()) with + | Some "false" -> NUnitConf.skip "env var CLR_SUPPORTS_WINFORMS is false" + | Some _ | None -> Success + + // call %~d0%~p0..\..\single-test-build.bat + do! SingleTestBuild.singleTestBuild cfg dir p + + // if "%CLR_SUPPORTS_WINFORMS%"=="false" ( goto Skip ) + ignore "already skipped if CLR_SUPPORTS_WINFORMS == false" + + // if "%COMPLUS_Version%"=="v1.0.3705" ( goto Skip ) + do! match cfg.EnvironmentVariables |> Map.tryFind "COMPLUS_Version" |> Option.map (fun s -> s.ToLower()) with + | Some "v1.0.3705" -> NUnitConf.skip "env var COMPLUS_Version is v1.0.3705" + | Some _ | None -> Success + + // call %~d0%~p0..\..\single-test-run.bat + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module ``84`` = + + [] + let ``84`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``85`` = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + + // if "%CLR_SUPPORTS_GENERICS%"=="false" ( goto Skip) + do! match cfg.EnvironmentVariables |> Map.tryFind "CLR_SUPPORTS_GENERICS" |> Option.map (fun s -> s.ToLower()) with + | Some "false" -> NUnitConf.skip "env var CLR_SUPPORTS_GENERICS is false" + | Some _ | None -> Success + + // if "%CLR_SUPPORTS_SYSTEM_WEB%"=="false" ( goto Skip) + do! match cfg.EnvironmentVariables |> Map.tryFind "CLR_SUPPORTS_SYSTEM_WEB" |> Option.map (fun s -> s.ToLower()) with + | Some "false" -> NUnitConf.skip "env var CLR_SUPPORTS_SYSTEM_WEB is false" + | Some _ | None -> Success + + // "%FSC%" %fsc_flags% -r:Category.dll -a -o:petshop.dll Category.ml + do! fsc "%s -r:Category.dll -a -o:petshop.dll" cfg.fsc_flags ["Category.ml"] + + // "%PEVERIFY%" petshop.dll + do! peverify "petshop.dll" + + } + + [] + let ``85`` () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + // REM build.bat produces only dll's. Nothing to run + + }) + + +module ``86`` = + + [] + let ``86`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module ``Tuple-bug-1`` = + + [] + let ``tuple-bug-1`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) diff --git a/tests/fsharp/single-neg-test.fs b/tests/fsharp/single-neg-test.fs new file mode 100644 index 00000000000..b994fe87053 --- /dev/null +++ b/tests/fsharp/single-neg-test.fs @@ -0,0 +1,219 @@ +module SingleNegTest + +open System +open System.IO +open NUnit.Framework + +open PlatformHelpers +open NUnitConf +open FSharpTestSuiteTypes + +let private singleNegTest' (cfg: TestConfig) workDir testname = processor { + + // call %~d0%~p0..\config.bat + ignore "from arguments" + + // if errorlevel 1 ( + // set ERRORMSG=%ERRORMSG% config.bat failed; + // goto :ERROR + // ) + ignore "already checked" + + let exec p = Command.exec workDir cfg.EnvironmentVariables { Output = Inherit; Input = None } p >> checkResult + let fsdiff a = Commands.fsdiff exec cfg.FSDIFF true a + let envOrFail key = + cfg.EnvironmentVariables + |> Map.tryFind key + |> function Some x -> (fun () -> Success x) | None -> NUnitConf.genericError (sprintf "environment variable '%s' required " key) + let fullpath = Commands.getfullpath workDir + let fileExists = fullpath >> Commands.fileExists workDir >> Option.isSome + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let fsc_flags = cfg.fsc_flags + + // if not exist "%FSC%" ( + // set ERRORMSG=Could not find FSC at path "%FSC%" + // goto :ERROR + // ) + ignore "already checked" + + // set testname=%1 + ignore "from arguments" + + // REM == Set baseline (fsc vs vs, in case the vs baseline exists) + let BSLFILE = + // IF EXIST %testname%.vsbsl (set BSLFILE=%testname%.vsbsl) + // IF NOT EXIST %testname%.vsbsl (set BSLFILE=%testname%.bsl) + if (sprintf "%s.vsbsl" testname) |> fileExists + then sprintf "%s.vsbsl" testname + else sprintf "%s.bsl" testname + + // %FSDIFF% %~f0 %~f0 + // @if ERRORLEVEL 1 ( + // set ERRORMSG=%ERRORMSG% FSDIFF likely not found; + // goto Error + // ) + + //REVIEW move to suite smoke tests like fsc/fsi? + do! fsdiff BSLFILE BSLFILE + + // set sources= + // if exist "%testname%.mli" (set sources=%sources% %testname%.mli) + // if exist "%testname%.fsi" (set sources=%sources% %testname%.fsi) + // if exist "%testname%.ml" (set sources=%sources% %testname%.ml) + // if exist "%testname%.fs" (set sources=%sources% %testname%.fs) + // if exist "%testname%.fsx" (set sources=%sources% %testname%.fsx) + // if exist "%testname%a.mli" (set sources=%sources% %testname%a.mli) + // if exist "%testname%a.fsi" (set sources=%sources% %testname%a.fsi) + // if exist "%testname%a.ml" (set sources=%sources% %testname%a.ml) + // if exist "%testname%a.fs" (set sources=%sources% %testname%a.fs) + // if exist "%testname%b.mli" (set sources=%sources% %testname%b.mli) + // if exist "%testname%b.fsi" (set sources=%sources% %testname%b.fsi) + // if exist "%testname%b.ml" (set sources=%sources% %testname%b.ml) + // if exist "%testname%b.fs" (set sources=%sources% %testname%b.fs) + let sources = [ + let src = + [ testname + ".mli"; testname + ".fsi"; testname + ".ml"; testname + ".fs"; testname + ".fsx"; + testname + "a.mli"; testname + "a.fsi"; testname + "a.ml"; testname + "a.fs"; + testname + "b.mli"; testname + "b.fsi"; testname + "b.ml"; testname + "b.fs" ] + + yield! src |> List.filter fileExists + + // if exist "helloWorldProvider.dll" (set sources=%sources% -r:helloWorldProvider.dll) + if fileExists "helloWorldProvider.dll" + then yield "-r:helloWorldProvider.dll" + + // if exist "%testname%-pre.fs" ( + // set sources=%sources% -r:%testname%-pre.dll + // ) + if fileExists (testname + "-pre.fs") + then yield (sprintf "-r:%s-pre.dll" testname) + + ] + + // REM check negative tests for bootstrapped fsc.exe due to line-ending differences + // if "%FSC:fscp=X%" == "%FSC%" ( + do! if cfg.FSC.Contains("fscp") + then NUnitConf.skip "bootstrapped fsc.exe due to line-ending differences" + else Success + + // if exist "%testname%-pre.fs" ( + do! if fileExists (testname + "-pre.fs") + // "%FSC%" %fsc_flags% -a -o:%testname%-pre.dll "%testname%-pre.fs" + then fsc "%s -a -o:%s-pre.dll" fsc_flags testname [testname + "-pre.fs"] + else Success () + // @if ERRORLEVEL 1 ( + // set ERRORMSG=%ERRORMSG% FSC failed for precursor library code for %sources%; + // goto SetError + // ) + // ) + + // echo Negative typechecker testing: %testname% + log "Negative typechecker testing: %s" testname + + let fsc' = + // "%FSC%" %fsc_flags% --vserrors --warnaserror --nologo --maxerrors:10000 -a -o:%testname%.dll %sources% 2> %testname%.err + // @if NOT ERRORLEVEL 1 ( + // set ERRORMSG=%ERRORMSG% FSC passed unexpectedly for %sources%; + // goto SetError + // ) + let ``exec 2>`` errPath = Command.exec workDir cfg.EnvironmentVariables { Output = Error(Overwrite(errPath)); Input = None } + let checkErrorLevel1 = function + | CmdResult.ErrorLevel 1 -> Success + | CmdResult.Success | CmdResult.ErrorLevel _ -> NUnitConf.genericError (sprintf "FSC passed unexpectedly for %A" sources) + + Printf.ksprintf (fun flags sources errPath -> Commands.fsc (``exec 2>`` errPath) cfg.FSC flags sources |> checkErrorLevel1) + + let fsdiff a b = processor { + let out = new ResizeArray() + let redirectOutputToFile path args = + log "%s %s" path args + let toLog = redirectToLog () + Process.exec { RedirectOutput = Some (function null -> () | s -> out.Add(s)); RedirectError = Some toLog.Post; RedirectInput = None; } workDir cfg.EnvironmentVariables path args + do! (Commands.fsdiff redirectOutputToFile cfg.FSDIFF true a b) |> checkResult + return out.ToArray() |> List.ofArray + } + + // "%FSC%" %fsc_flags% --vserrors --warnaserror --nologo --maxerrors:10000 -a -o:%testname%.dll %sources% 2> %testname%.err + do! fsc' """%s --vserrors --warnaserror --nologo --maxerrors:10000 -a -o:%s.dll""" fsc_flags testname sources (sprintf "%s.err" testname) + + // %FSDIFF% %testname%.err %testname%.bsl > %testname%.diff + let! testnameDiff = fsdiff (sprintf "%s.err" testname) (sprintf "%s.bsl" testname) + + // for /f %%c IN (%testname%.diff) do ( + do! match testnameDiff with + | [] -> Success + | l -> + // echo ***** %testname%.err %testname%.bsl differed: a bug or baseline may neeed updating + log "***** %s.err %s.bsl differed: a bug or baseline may neeed updating" testname testname + // set ERRORMSG=%ERRORMSG% %testname%.err %testname%.bsl differ; + NUnitConf.genericError (sprintf "%s.err %s.bsl differ; %A" testname testname l) + + // echo Good, output %testname%.err matched %testname%.bsl + log "Good, output %s.err matched %s.bsl" testname testname + + // "%FSC%" %fsc_flags% --test:ContinueAfterParseFailure --vserrors --warnaserror --nologo --maxerrors:10000 -a -o:%testname%.dll %sources% 2> %testname%.vserr + do! fsc' "%s --test:ContinueAfterParseFailure --vserrors --warnaserror --nologo --maxerrors:10000 -a -o:%s.dll" fsc_flags testname sources (sprintf "%s.vserr" testname) + // @if NOT ERRORLEVEL 1 ( + // set ERRORMSG=%ERRORMSG% FSC passed unexpectedly for %sources%; + // goto SetError + // ) + + // %FSDIFF% %testname%.vserr %BSLFILE% > %testname%.vsdiff + let! testnameDiff = fsdiff (sprintf "%s.vserr" testname) BSLFILE + + // for /f %%c IN (%testname%.vsdiff) do ( + do! match testnameDiff with + | [] -> Success + | l -> + // echo ***** %testname%.vserr %BSLFILE% differed: a bug or baseline may neeed updating + log "***** %s.vserr %s differed: a bug or baseline may neeed updating" testname BSLFILE + // set ERRORMSG=%ERRORMSG% %testname%.vserr %BSLFILE% differ; + NUnitConf.genericError (sprintf "%s.vserr %s differ; %A" testname BSLFILE l) + + // echo Good, output %testname%.vserr matched %BSLFILE% + log "Good, output %s.vserr matched %s" testname BSLFILE + // ) + } + +let singleNegTest = + + // :Ok + let doneOK x = + // echo Ran fsharp %~f0 ok. + log "Ran fsharp %%~f0 ok" + // endlocal + // exit /b 0 + // goto :EOF + Success x + + // :Skip + let doneSkipped workDir msg x = + // echo Skipped %~f0 + log "Skipped neg run '%s' reason: %s" workDir msg + // endlocal + // exit /b 0 + // goto :EOF + Success x + + // :Error + let doneError err msg = + // echo %ERRORMSG% + log "%s" msg + // exit /b %ERRORLEVEL% + // goto :EOF + Failure (err) + + // :SETERROR + // set NonexistentErrorLevel 2> nul + // goto Error + // goto :EOF + + let flow cfg workDir testname () = + singleNegTest' cfg workDir testname + |> Attempt.Run + |> function + | Success () -> doneOK () + | Failure (Skipped msg) -> doneSkipped workDir msg () + | Failure (GenericError msg) -> doneError (GenericError msg) msg + | Failure (ProcessExecError (err,msg)) -> doneError (ProcessExecError(err,msg)) msg + flow diff --git a/tests/fsharp/single-test-build.fs b/tests/fsharp/single-test-build.fs new file mode 100644 index 00000000000..e2ff68e1d51 --- /dev/null +++ b/tests/fsharp/single-test-build.fs @@ -0,0 +1,404 @@ +module SingleTestBuild + +open System +open System.IO +open System.Diagnostics +open NUnit.Framework + +open PlatformHelpers +open NUnitConf +open FSharpTestSuiteTypes + + +let singleTestBuild cfg testDir = + + let fileExists = Commands.fileExists testDir >> Option.isSome + let del = Commands.rm testDir + + //if EXIST build.ok DEL /f /q build.ok + let buildOkPath = testDir / "build.ok" + do if fileExists "build.ok" then del "build.ok" + + //call %~d0%~p0..\config.bat + ignore "param" + + //if NOT "%FSC:NOTAVAIL=X%" == "%FSC%" ( + // goto Skip + //) + ignore "already checked fsc/fsi exists" + + //set source1= + //if exist test.ml (set source1=test.ml) + //if exist test.fs (set source1=test.fs) + let source1 = + ["test.ml"; "test.fs"] + |> List.rev + |> List.tryFind fileExists + + //set sources= + //if exist testlib.fsi (set sources=%sources% testlib.fsi) + //if exist testlib.fs (set sources=%sources% testlib.fs) + //if exist test.mli (set sources=%sources% test.mli) + //if exist test.ml (set sources=%sources% test.ml) + //if exist test.fsi (set sources=%sources% test.fsi) + //if exist test.fs (set sources=%sources% test.fs) + //if exist test2.mli (set sources=%sources% test2.mli) + //if exist test2.ml (set sources=%sources% test2.ml) + //if exist test2.fsi (set sources=%sources% test2.fsi) + //if exist test2.fs (set sources=%sources% test2.fs) + //if exist test.fsx (set sources=%sources% test.fsx) + //if exist test2.fsx (set sources=%sources% test2.fsx) + let sources = + ["testlib.fsi";"testlib.fs";"test.mli";"test.ml";"test.fsi";"test.fs";"test2.mli";"test2.ml";"test2.fsi";"test2.fs";"test.fsx";"test2.fsx"] + |> List.filter fileExists + + //set sourceshw= + //if exist test-hw.mli (set sourceshw=%sourceshw% test-hw.mli) + //if exist test-hw.ml (set sourceshw=%sourceshw% test-hw.ml) + //if exist test-hw.fsx (set sourceshw=%sourceshw% test-hw.fsx) + //if exist test2-hw.mli (set sourceshw=%sourceshw% test2-hw.mli) + //if exist test2-hw.ml (set sourceshw=%sourceshw% test2-hw.ml) + //if exist test2-hw.fsx (set sourceshw=%sourceshw% test2-hw.fsx) + let sourceshw = + ["test-hw.mli";"test-hw.ml";"test-hw.fsx";"test2-hw.mli";"test2-hw.ml";"test2-hw.fsx"] + |> List.filter fileExists + + //rem to run the 64 bit version of the code set FSC_BASIC_64=FSC_BASIC_64 + //set PERMUTATIONS_LIST=FSI_FILE FSI_STDIN FSI_STDIN_OPT FSI_STDIN_GUI FSC_BASIC %FSC_BASIC_64% FSC_HW FSC_O3 GENERATED_SIGNATURE EMPTY_SIGNATURE EMPTY_SIGNATURE_OPT FSC_OPT_MINUS_DEBUG FSC_OPT_PLUS_DEBUG FRENCH SPANISH AS_DLL WRAPPER_NAMESPACE WRAPPER_NAMESPACE_OPT + + //if "%REDUCED_RUNTIME%"=="1" ( + // echo REDUCED_RUNTIME set + // + // if not defined PERMUTATIONS ( + // powershell.exe %PSH_FLAGS% -command "&{& '%~d0%~p0\PickPermutations.ps1' '%cd%' '%FSC%' '%PERMUTATIONS_LIST%'}" > _perm.txt + // if errorlevel 1 ( + // set ERRORMSG=%ERRORMSG% PickPermutations.ps1 failed; + // goto :ERROR + // ) + // set /p PERMUTATIONS=<_perm.txt + // ) + // + // powershell.exe %PSH_FLAGS% -command "&{& '%~d0%~p0\DecidePEVerify.ps1' '%cd%' '%FSC%'}" + // if errorlevel 1 ( + // set ERRORMSG=%ERRORMSG% DecidePEVerify.ps1 failed; + // goto :ERROR + // ) + //) + + //if not defined PERMUTATIONS ( + // echo "PERMUTATIONS not defined. Building everything." + // set PERMUTATIONS=%PERMUTATIONS_LIST% + //) + + //for %%A in (%PERMUTATIONS%) do ( + // call :%%A + // IF ERRORLEVEL 1 EXIT /B 1 + //) + ignore "permutations useless because build type is an input" + + let exec p = Command.exec testDir cfg.EnvironmentVariables { Output = Inherit; Input = None } p >> checkResult + + let echo_tofile = Commands.echo_tofile testDir + let copy_y f = Commands.copy_y testDir f >> checkResult + let type_append_tofile = Commands.type_append_tofile testDir + let fsc = Printf.ksprintf (fun flags -> Commands.fsc exec cfg.FSC flags) + let fsc_flags = cfg.fsc_flags + let peverify = Commands.peverify exec cfg.PEVERIFY + let ``echo._tofile`` = Commands.``echo._tofile`` testDir + + //:Ok + let doneOk x = + //echo Built fsharp %~f0 ok. + log "Built fsharp %s ok." testDir + //echo. > build.ok + ``echo._tofile`` " " "build.ok" + //endlocal + //exit /b 0 + Success x + + //:Skip + let doneSkipped msg x = + //echo Skipped %~f0 + log "Skipped build '%s' reason: %s" testDir msg + //endlocal + ``echo._tofile`` " " "build.ok" + //exit /b 0 + Success x + + //:Error + let doneError err msg = + //echo Test Script Failed (perhaps test did not emit test.ok signal file?) + log "%s" msg + //endlocal + //exit /b %ERRORLEVEL% + Failure (err) + + let genericErrorMessage = "Test Script Failed (perhaps test did not emit test.ok signal file?)" + + //:SETERROR + //set NonexistentErrorLevel 2> nul + //goto Error + + let skipIfExists file = processor { + if fileExists file + then return! NUnitConf.skip (sprintf "file '%s' found" file) + } + + let skipIfNotExists file = processor { + if not (fileExists file) + then return! NUnitConf.skip (sprintf "file '%s' not found" file) + } + + /// + /// if NOT EXIST dont.run.peverify ( + /// "%PEVERIFY%" test.exe + /// @if ERRORLEVEL 1 goto Error + /// ) + /// + let doPeverify cmd = processor { + do! skipIfExists "dont.run.peverify" + + do! peverify cmd + } + + let doNOOP () = processor { + //@echo No build action to take for this permutation + log "No build action to take for this permutation" + } + + let doBasic () = processor { + // FSC %fsc_flags% --define:BASIC_TEST -o:test.exe -g %sources% + //if ERRORLEVEL 1 goto Error + do! fsc "%s --define:BASIC_TEST -o:test.exe -g" fsc_flags sources + + //if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test.exe + // @if ERRORLEVEL 1 goto Error + //) + do! doPeverify "test.exe" + } + + let doBasic64 () = processor { + // "%FSC%" %fsc_flags% --define:BASIC_TEST --platform:x64 -o:testX64.exe -g %sources% + do! fsc "%s --define:BASIC_TEST --platform:x64 -o:testX64.exe -g" fsc_flags sources + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" testX64.exe + // ) + do! doPeverify "testX64.exe" + } + + let doFscHW () = processor { + // if exist test-hw.* ( + if Directory.EnumerateFiles(testDir, "test-hw.*") |> Seq.exists fileExists then + // "%FSC%" %fsc_flags% -o:test-hw.exe -g %sourceshw% + do! fsc "%s -o:test-hw.exe -g" fsc_flags sourceshw + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test-hw.exe + // ) + do! doPeverify "test-hw.exe" + //) + else + do! NUnitConf.skip (sprintf "file '%s' not found" "test-hw.*") + } + + let doFscO3 () = processor { + //"%FSC%" %fsc_flags% --optimize --define:PERF -o:test--optimize.exe -g %sources% + do! fsc "%s --optimize --define:PERF -o:test--optimize.exe -g" fsc_flags sources + //if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test--optimize.exe + //) + do! doPeverify "test--optimize.exe" + } + + let doGeneratedSignature () = processor { + //if NOT EXIST dont.use.generated.signature ( + do! skipIfExists "dont.use.generated.signature" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // echo Generating interface file... + log "Generating interface file..." + // copy /y %source1% tmptest.ml + do! source1 |> Option.map (fun from -> copy_y from "tmptest.ml") + // REM NOTE: use --generate-interface-file since results may be in Unicode + // "%FSC%" %fsc_flags% --sig:tmptest.mli tmptest.ml + do! fsc "%s --sig:tmptest.mli" fsc_flags ["tmptest.ml"] + + // echo Compiling against generated interface file... + log "Compiling against generated interface file..." + // "%FSC%" %fsc_flags% -o:tmptest1.exe tmptest.mli tmptest.ml + do! fsc "%s -o:tmptest1.exe" fsc_flags ["tmptest.mli";"tmptest.ml"] + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" tmptest1.exe + // ) + do! doPeverify "tmptest1.exe" + } + + let doEmptySignature () = processor { + //if NOT EXIST dont.use.empty.signature ( + do! skipIfExists "dont.use.empty.signature" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // echo Compiling against empty interface file... + log "Compiling against empty interface file..." + // echo // empty file > tmptest2.mli + echo_tofile "// empty file " "tmptest2.mli" + // copy /y %source1% tmptest2.ml + do! source1 |> Option.map (fun from -> copy_y from "tmptest2.ml") + // "%FSC%" %fsc_flags% --define:COMPILING_WITH_EMPTY_SIGNATURE -o:tmptest2.exe tmptest2.mli tmptest2.ml + do! fsc "%s --define:COMPILING_WITH_EMPTY_SIGNATURE -o:tmptest2.exe" fsc_flags ["tmptest2.mli";"tmptest2.ml"] + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" tmptest2.exe + // ) + do! doPeverify "tmptest2.exe" + } + + + let doEmptySignatureOpt () = processor { + //if NOT EXIST dont.use.empty.signature ( + do! skipIfExists "dont.use.empty.signature" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // echo Compiling against empty interface file... + log "Compiling against empty interface file..." + // echo // empty file > tmptest2.mli + echo_tofile "// empty file " "tmptest2.mli" + // copy /y %source1% tmptest2.ml + do! source1 |> Option.map (fun from -> copy_y from "tmptest2.ml") + // "%FSC%" %fsc_flags% --define:COMPILING_WITH_EMPTY_SIGNATURE --optimize -o:tmptest2--optimize.exe tmptest2.mli tmptest2.ml + do! fsc "%s --define:COMPILING_WITH_EMPTY_SIGNATURE --optimize -o:tmptest2--optimize.exe" fsc_flags ["tmptest2.mli";"tmptest2.ml"] + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" tmptest2--optimize.exe + // ) + do! doPeverify "tmptest2--optimize.exe" + } + + let doOptFscMinusDebug () = processor { + // "%FSC%" %fsc_flags% --optimize- --debug -o:test--optminus--debug.exe -g %sources% + do! fsc "%s --optimize- --debug -o:test--optminus--debug.exe -g" fsc_flags sources + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test--optminus--debug.exe + // ) + do! doPeverify "test--optminus--debug.exe" + } + + let doOptFscPlusDebug () = processor { + // "%FSC%" %fsc_flags% --optimize+ --debug -o:test--optplus--debug.exe -g %sources% + do! fsc "%s --optimize+ --debug -o:test--optplus--debug.exe -g" fsc_flags sources + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test--optplus--debug.exe + // ) + do! doPeverify "test--optplus--debug.exe" + } + + let doAsDLL () = processor { + //REM Compile as a DLL to exercise pickling of interface data, then recompile the original source file referencing this DLL + //REM THe second compilation will not utilize the information from the first in any meaningful way, but the + //REM compiler will unpickle the interface and optimization data, so we test unpickling as well. + + //if NOT EXIST dont.compile.test.as.dll ( + do! skipIfExists "dont.compile.test.as.dll" + + // "%FSC%" %fsc_flags% --optimize -a -o:test--optimize-lib.dll -g %sources% + do! fsc "%s --optimize -a -o:test--optimize-lib.dll -g" fsc_flags sources + + // "%FSC%" %fsc_flags% --optimize -r:test--optimize-lib.dll -o:test--optimize-client-of-lib.exe -g %sources% + do! fsc "%s --optimize -r:test--optimize-lib.dll -o:test--optimize-client-of-lib.exe -g" fsc_flags sources + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test--optimize-lib.dll + // ) + do! doPeverify "test--optimize-lib.dll" + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" test--optimize-client-of-lib.exe + // ) + do! doPeverify "test--optimize-client-of-lib.exe" + } + + let doWrapperNamespace () = processor { + // if NOT EXIST dont.use.wrapper.namespace ( + do! skipIfExists "dont.use.wrapper.namespace" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // echo Compiling when wrapped in a namespace declaration... + log "Compiling when wrapped in a namespace declaration..." + // echo module TestNamespace.TestModule > tmptest3.ml + echo_tofile "module TestNamespace.TestModule " "tmptest3.ml" + // type %source1% >> tmptest3.ml + source1 |> Option.iter (fun from -> type_append_tofile from "tmptest3.ml") + // "%FSC%" %fsc_flags% -o:tmptest3.exe tmptest3.ml + do! fsc "%s -o:tmptest3.exe" fsc_flags ["tmptest3.ml"] + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" tmptest3.exe + // ) + do! doPeverify "tmptest3.exe" + } + + let doWrapperNamespaceOpt () = processor { + //if NOT EXIST dont.use.wrapper.namespace ( + do! skipIfExists "dont.use.wrapper.namespace" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // echo Compiling when wrapped in a namespace declaration... + log "Compiling when wrapped in a namespace declaration..." + // echo module TestNamespace.TestModule > tmptest3.ml + echo_tofile "module TestNamespace.TestModule " "tmptest3.ml" + // type %source1% >> tmptest3.ml + source1 |> Option.iter (fun from -> type_append_tofile from "tmptest3.ml") + // "%FSC%" %fsc_flags% --optimize -o:tmptest3--optimize.exe tmptest3.ml + do! fsc "%s --optimize -o:tmptest3--optimize.exe" fsc_flags ["tmptest3.ml"] + + // if NOT EXIST dont.run.peverify ( + // "%PEVERIFY%" tmptest3--optimize.exe + // ) + do! doPeverify "tmptest3--optimize.exe" + } + + let build = function + | FSI_FILE -> doNOOP + | FSI_STDIN -> doNOOP + | FSI_STDIN_OPT -> doNOOP + | FSI_STDIN_GUI -> doNOOP + | FRENCH -> doBasic + | SPANISH -> doBasic + | FSC_BASIC -> doBasic + | FSC_BASIC_64 -> doBasic64 + | FSC_HW -> doFscHW + | FSC_O3 -> doFscO3 + | GENERATED_SIGNATURE -> doGeneratedSignature + | EMPTY_SIGNATURE -> doEmptySignature + | EMPTY_SIGNATURE_OPT -> doEmptySignatureOpt + | FSC_OPT_MINUS_DEBUG -> doOptFscMinusDebug + | FSC_OPT_PLUS_DEBUG -> doOptFscPlusDebug + | AS_DLL -> doAsDLL + | WRAPPER_NAMESPACE -> doWrapperNamespace + | WRAPPER_NAMESPACE_OPT -> doWrapperNamespaceOpt + + let flow p () = + build p () + |> Attempt.Run + |> function + | Success () -> doneOk () + | Failure (Skipped msg) -> doneSkipped msg () + | Failure (GenericError msg) -> doneError (GenericError msg) msg + | Failure (ProcessExecError (err,msg)) -> doneError (ProcessExecError(err,msg)) msg + + flow diff --git a/tests/fsharp/single-test-run.fs b/tests/fsharp/single-test-run.fs new file mode 100644 index 00000000000..4ef0801f425 --- /dev/null +++ b/tests/fsharp/single-test-run.fs @@ -0,0 +1,527 @@ +module SingleTestRun + +open System +open System.IO +open NUnit.Framework + +open PlatformHelpers +open NUnitConf +open FSharpTestSuiteTypes + +let private singleTestRun' cfg testDir = + + let getfullpath = Commands.getfullpath testDir + let fileExists = Commands.fileExists testDir >> Option.isSome + + // set sources= + // if exist testlib.fsi (set sources=%sources% testlib.fsi) + // if exist testlib.fs (set sources=%sources% testlib.fs) + // if exist test.mli (set sources=%sources% test.mli) + // if exist test.ml (set sources=%sources% test.ml) + // if exist test.fsi (set sources=%sources% test.fsi) + // if exist test.fs (set sources=%sources% test.fs) + // if exist test2.mli (set sources=%sources% test2.mli) + // if exist test2.ml (set sources=%sources% test2.ml) + // if exist test2.fsi (set sources=%sources% test2.fsi) + // if exist test2.fs (set sources=%sources% test2.fs) + // if exist test.fsx (set sources=%sources% test.fsx) + // if exist test2.fsx (set sources=%sources% test2.fsx) + let sources = + ["testlib.fsi";"testlib.fs";"test.mli";"test.ml";"test.fsi";"test.fs";"test2.mli";"test2.ml";"test2.fsi";"test2.fs";"test.fsx";"test2.fsx"] + |> List.filter fileExists + + // set sourceshw= + // if exist test-hw.mli (set sourceshw=%sourceshw% test-hw.mli) + // if exist test-hw.ml (set sourceshw=%sourceshw% test-hw.ml) + // if exist test2-hw.mli (set sourceshw=%sourceshw% test2-hw.mli) + // if exist test2-hw.ml (set sourceshw=%sourceshw% test2-hw.ml) + // if exist test-hw.fsi (set sourceshw=%sourceshw% test-hw.fsi) + // if exist test-hw.fs (set sourceshw=%sourceshw% test-hw.fs) + // if exist test2-hw.fsi (set sourceshw=%sourceshw% test2-hw.fsi) + // if exist test2-hw.fs (set sourceshw=%sourceshw% test2-hw.fs) + // if exist test-hw.fsx (set sourceshw=%sourceshw% test-hw.fsx) + // if exist test2-hw.fsx (set sourceshw=%sourceshw% test2-hw.fsx) + let sourceshw = + ["test-hw.mli";"test-hw.ml";"test2-hw.mli";"test2-hw.ml";"test-hw.fsi";"test-hw.fs";"test2-hw.fsi";"test2-hw.fs";"test-hw.fsx";"test2-hw.fsx"] + |> List.filter fileExists + + // :START + + // set PERMUTATIONS_LIST=FSI_FILE FSI_STDIN FSI_STDIN_OPT FSI_STDIN_GUI FSC_BASIC %FSC_BASIC_64% FSC_HW FSC_O3 GENERATED_SIGNATURE EMPTY_SIGNATURE EMPTY_SIGNATURE_OPT FSC_OPT_MINUS_DEBUG FSC_OPT_PLUS_DEBUG FRENCH SPANISH AS_DLL WRAPPER_NAMESPACE WRAPPER_NAMESPACE_OPT + // + // if "%REDUCED_RUNTIME%"=="1" ( + // echo REDUCED_RUNTIME set + // + // if not defined PERMUTATIONS ( + // powershell.exe %PSH_FLAGS% -command "&{& '%~d0%~p0\PickPermutations.ps1' '%cd%' '%FSC%' '%PERMUTATIONS_LIST%'}" > _perm.txt + // if errorlevel 1 ( + // set ERRORMSG=%ERRORMSG% PickPermutations.ps1 failed; + // goto :ERROR + // ) + // set /p PERMUTATIONS=<_perm.txt + // ) + // ) + ignore "test is parametrized" + + // if not defined PERMUTATIONS ( + // echo "PERMUTATIONS not defined. Running everything." + // set PERMUTATIONS=%PERMUTATIONS_LIST% + // ) + ignore "test is parametrized" + + // for %%A in (%PERMUTATIONS%) do ( + // call :%%A + // IF ERRORLEVEL 1 EXIT /B 1 + // ) + ignore "test is parametrized" + + // if "%ERRORMSG%"=="" goto Ok + + // set NonexistentErrorLevel 2> nul + // goto :ERROR + + // :END + + // :EXIT_PATHS + + // REM ========================================= + // REM THE TESTS + // REM ========================================= + + let exec p = Command.exec testDir cfg.EnvironmentVariables { Output = Inherit; Input = None } p >> checkResult + + let fsi = Printf.ksprintf (fun flags l -> Commands.fsi exec cfg.FSI flags l) + let ``exec <`` l p = Command.exec testDir cfg.EnvironmentVariables { Output = Inherit; Input = Some(RedirectInput(l)) } p >> checkResult + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + + let fsi_flags = cfg.fsi_flags + + let createTestOkFile () = NUnitConf.FileGuard.create (getfullpath "test.ok") + + let skipIfExists file = processor { + if fileExists file + then return! NUnitConf.skip (sprintf "file '%s' found" file) + } + + let skipIfNotExists file = processor { + if not (fileExists file) + then return! NUnitConf.skip (sprintf "file '%s' not found" file) + } + + + // :FSI_STDIN + // @echo do :FSI_STDIN + let runFSI_STDIN () = processor { + // if NOT EXIST dont.pipe.to.stdin ( + do! skipIfExists "dont.pipe.to.stdin" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% "%FSI%" %fsi_flags% < %sources% && ( + do! ``fsi <`` "%s" fsi_flags (sources |> List.rev |> List.head) //use last file, because `cmd < a.txt b.txt` redirect b.txt only + // dir test.ok > NUL 2>&1 ) || ( + // @echo FSI_STDIN failed; + // set ERRORMSG=%ERRORMSG% FSI_STDIN failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + } + + // :FSI_STDIN_OPT + // @echo do :FSI_STDIN_OPT + let runFSI_STDIN_OPT () = processor { + // if NOT EXIST dont.pipe.to.stdin ( + do! skipIfExists "dont.pipe.to.stdin" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% "%FSI%" %fsi_flags% --optimize < %sources% && ( + do! ``fsi <`` "%s --optimize" fsi_flags (sources |> List.rev |> List.head) //use last file, because `cmd < a.txt b.txt` redirect b.txt only + // dir test.ok > NUL 2>&1 ) || ( + // @echo FSI_STDIN_OPT failed + // set ERRORMSG=%ERRORMSG% FSI_STDIN_OPT failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + } + + // :FSI_STDIN_GUI + // @echo do :FSI_STDIN_GUI + let runFSI_STDIN_GUI () = processor { + // if NOT EXIST dont.pipe.to.stdin ( + do! skipIfExists "dont.pipe.to.stdin" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% "%FSI%" %fsi_flags% --gui < %sources% && ( + do! ``fsi <`` "%s --gui" fsi_flags (sources |> List.rev |> List.head) //use last file, because `cmd < a.txt b.txt` redirect b.txt only + // dir test.ok > NUL 2>&1 ) || ( + // @echo FSI_STDIN_GUI failed; + // set ERRORMSG=%ERRORMSG% FSI_STDIN_GUI failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + } + + // :FSI_FILE + // @echo do :FSI_FILE + let runFSI_FILE () = processor { + // if NOT EXIST dont.run.as.script ( + do! skipIfExists "dont.run.as.script" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% "%FSI%" %fsi_flags% %sources% && ( + do! fsi "%s" fsi_flags sources + // dir test.ok > NUL 2>&1 ) || ( + // @echo FSI_FILE failed + // set ERRORMSG=%ERRORMSG% FSI_FILE failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + } + + // :FSC_BASIC + // @echo do :FSC_BASIC + let runFSC_BASIC () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test.exe && ( + do! exec ("."/"test.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSC_BASIC failed + // set ERRORMSG=%ERRORMSG% FSC_BASIC failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :FSC_BASIC_64 + // @echo do :FSC_BASIC_64 + let runFSC_BASIC_64 () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\testX64.exe && ( + do! exec ("."/"testX64.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSC_BASIC_64 failed + // set ERRORMSG=%ERRORMSG% FSC_BASIC_64 failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :FSC_HW + // @echo do :FSC_HW + let runFSC_HW () = processor { + // if exist test-hw.* ( + if Directory.EnumerateFiles(testDir, "test-hw.*") |> Seq.exists fileExists then + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test-hw.exe && ( + do! exec ("."/"test-hw.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSC_HW failed + // set ERRORMSG=%ERRORMSG% FSC_HW failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + //) + else + do! NUnitConf.skip (sprintf "file '%s' not found" "test-hw.*") + } + + // :FSC_O3 + // @echo do :FSC_O3 + let runFSC_O3 () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test--optimize.exe && ( + do! exec ("."/"test--optimize.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSC_O3 failed + // set ERRORMSG=%ERRORMSG% FSC_03 failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :FSC_OPT_MINUS_DEBUG + // @echo do :FSC_OPT_MINUS_DEBUG + let runFSC_OPT_MINUS_DEBUG () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test--optminus--debug.exe && ( + do! exec ("."/"test--optminus--debug.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSC_OPT_MINUS_DEBUG failed + // set ERRORMSG=%ERRORMSG% FSC_OPT_MINUS_DEBUG failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :FSC_OPT_PLUS_DEBUG + // @echo do :FSC_OPT_PLUS_DEBUG + let runFSC_OPT_PLUS_DEBUG () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test--optplus--debug.exe && ( + do! exec ("."/"test--optplus--debug.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSC_OPT_PLUS_DEBUG failed + // set ERRORMSG=%ERRORMSG% FSC_OPT_PLUS_DEBUG failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :GENERATED_SIGNATURE + // @echo do :GENERATED_SIGNATURE + let runGENERATED_SIGNATURE () = processor { + // if NOT EXIST dont.use.generated.signature ( + do! skipIfExists "dont.use.generated.signature" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% tmptest1.exe && ( + do! exec ("."/"tmptest1.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :GENERATED_SIGNATURE failed + // set ERRORMSG=%ERRORMSG% FSC_GENERATED_SIGNATURE failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + //) + } + + // :EMPTY_SIGNATURE + // @echo do :EMPTY_SIGNATURE + let runEMPTY_SIGNATURE () = processor { + // if NOT EXIST dont.use.empty.signature ( + do! skipIfExists "dont.use.empty.signature" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% tmptest2.exe && ( + do! exec ("."/"tmptest2.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :EMPTY_SIGNATURE failed + // set ERRORMSG=%ERRORMSG% FSC_EMPTY_SIGNATURE failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + //) + } + + // :EMPTY_SIGNATURE_OPT + // @echo do :EMPTY_SIGNATURE_OPT + let runEMPTY_SIGNATURE_OPT () = processor { + // if NOT EXIST dont.use.empty.signature ( + do! skipIfExists "dont.use.empty.signature" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% tmptest2--optimize.exe && ( + do! exec ("."/"tmptest2--optimize.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :EMPTY_SIGNATURE_OPT --optimize failed + // set ERRORMSG=%ERRORMSG% EMPTY_SIGNATURE_OPT --optimize failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + //) + } + + // :FRENCH + // @echo do :FRENCH + let runFRENCH () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test.exe fr-FR && ( + do! exec ("."/"test.exe") "fr-FR" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FRENCH failed + // set ERRORMSG=%ERRORMSG% FRENCH failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :SPANISH + // @echo do :SPANISH + let runSPANISH () = processor { + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test.exe es-ES && ( + do! exec ("."/"test.exe") "es-ES" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :SPANISH failed + // set ERRORMSG=%ERRORMSG% SPANISH failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + } + + // :AS_DLL + // @echo do :AS_DLL + let runAS_DLL () = processor { + //if NOT EXIST dont.compile.test.as.dll ( + do! skipIfExists "dont.compile.test.as.dll" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\test--optimize-client-of-lib.exe && ( + do! exec ("."/"test--optimize-client-of-lib.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :AS_DLL failed + // set ERRORMSG=%ERRORMSG% AS_DLL failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + //) + } + + // :WRAPPER_NAMESPACE + // @echo do :WRAPPER_NAMESPACE + let runWRAPPER_NAMESPACE () = processor { + // if NOT EXIST dont.use.wrapper.namespace ( + do! skipIfExists "dont.use.wrapper.namespace" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\tmptest3.exe && ( + do! exec ("."/"tmptest3.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :WRAPPER_NAMESPACE failed + // set ERRORMSG=%ERRORMSG% WRAPPER_NAMESPACE failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + //) + } + + // :WRAPPER_NAMESPACE_OPT + // @echo do :WRAPPER_NAMESPACE_OPT + let runWRAPPER_NAMESPACE_OPT () = processor { + // if NOT EXIST dont.use.wrapper.namespace ( + do! skipIfExists "dont.use.wrapper.namespace" + + // if exist test.ml ( + do! skipIfNotExists "test.ml" + + // if exist test.ok (del /f /q test.ok) + use testOkFile = createTestOkFile () + // %CLIX% .\tmptest3--optimize.exe && ( + do! exec ("."/"tmptest3--optimize.exe") "" + // dir test.ok > NUL 2>&1 ) || ( + // @echo :WRAPPER_NAMESPACE_OPT failed + // set ERRORMSG=%ERRORMSG% WRAPPER_NAMESPACE_OPT failed; + // ) + do! testOkFile |> NUnitConf.checkGuardExists + // ) + // ) + } + + let run = function + | FSI_FILE -> runFSI_FILE + | FSI_STDIN -> runFSI_STDIN + | FSI_STDIN_OPT -> runFSI_STDIN_OPT + | FSI_STDIN_GUI -> runFSI_STDIN_GUI + | FRENCH -> runFRENCH + | SPANISH -> runSPANISH + | FSC_BASIC -> runFSC_BASIC + | FSC_BASIC_64 -> runFSC_BASIC_64 + | FSC_HW -> runFSC_HW + | FSC_O3 -> runFSC_O3 + | GENERATED_SIGNATURE -> runGENERATED_SIGNATURE + | EMPTY_SIGNATURE -> runEMPTY_SIGNATURE + | EMPTY_SIGNATURE_OPT -> runEMPTY_SIGNATURE_OPT + | FSC_OPT_MINUS_DEBUG -> runFSC_OPT_MINUS_DEBUG + | FSC_OPT_PLUS_DEBUG -> runFSC_OPT_PLUS_DEBUG + | AS_DLL -> runAS_DLL + | WRAPPER_NAMESPACE -> runWRAPPER_NAMESPACE + | WRAPPER_NAMESPACE_OPT -> runWRAPPER_NAMESPACE_OPT + + run + +let singleTestRun config testDir = + let fileExists = Commands.fileExists testDir >> Option.isSome + + //@if "%_echo%"=="" echo off + //setlocal + ignore "unused" + + //set ERRORMSG= + ignore "unused" + + //:Ok + let doneOK x = + //echo Ran fsharp %~f0 ok. + log "Ran fsharp %s ok." testDir + //exit /b 0 + Success x + + //:Skip + let doneSkipped msg = + //echo Skipped %~f0 + log "Skipped run '%s' reason: %s" testDir msg + //exit /b 0 + Failure (Skipped msg) + + //:Error + let doneError err msg = + //echo %ERRORMSG% + log "%s" msg + //exit /b %ERRORLEVEL% + Failure (err) + + let skipIfNotExists file = processor { + if not (fileExists file) + then return! NUnitConf.skip (sprintf "file '%s' not found" file) + } + + let tests config p = processor { + //dir build.ok > NUL ) || ( + // @echo 'build.ok' not found. + // set ERRORMSG=%ERRORMSG% Skipped because 'build.ok' not found. + // goto :ERROR + //) + do! skipIfNotExists "build.ok" + + // call %~d0%~p0..\config.bat + let cfg = config + // if errorlevel 1 ( + // set ERRORMSG=%ERRORMSG% config.bat failed; + // goto :ERROR + // ) + + // if not exist "%FSC%" ( + // set ERRORMSG=%ERRORMSG% fsc.exe not found at the location "%FSC%" + // goto :ERROR + // ) + ignore "already checked at test suite startup" + + // if not exist "%FSI%" ( + // set ERRORMSG=%ERRORMSG% fsi.exe not found at the location "%FSI%" + // goto :ERROR + // ) + ignore "already checked at test suite startup" + + do! singleTestRun' cfg testDir p () + } + + let flow p () = + tests config p + |> Attempt.Run + |> function + | Success () -> doneOK () + | Failure (Skipped msg) -> doneSkipped msg + | Failure (GenericError msg) -> doneError (GenericError msg) msg + | Failure (ProcessExecError (err,msg)) -> doneError (ProcessExecError(err,msg)) msg + + + flow diff --git a/tests/fsharp/tools/tests_tools.fs b/tests/fsharp/tools/tests_tools.fs new file mode 100644 index 00000000000..8d6f183c9c0 --- /dev/null +++ b/tests/fsharp/tools/tests_tools.fs @@ -0,0 +1,62 @@ +module ``FSharp-Tests-Tools`` + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open NUnitConf +open PlatformHelpers + +let testContext = FSharpTestSuite.testContext + + +module Bundle = + + [] + let bundle () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%FSC%" %fsc_flags% --progress --standalone -o:test-one-fsharp-module.exe -g test-one-fsharp-module.fs + do! fsc "%s --progress --standalone -o:test-one-fsharp-module.exe -g" cfg.fsc_flags ["test-one-fsharp-module.fs"] + + // "%PEVERIFY%" test-one-fsharp-module.exe + do! peverify "test-one-fsharp-module.exe" + + // "%FSC%" %fsc_flags% -a -o:test_two_fsharp_modules_module_1.dll -g test_two_fsharp_modules_module_1.fs + do! fsc "%s -a -o:test_two_fsharp_modules_module_1.dll -g" cfg.fsc_flags ["test_two_fsharp_modules_module_1.fs"] + + // "%PEVERIFY%" test_two_fsharp_modules_module_1.dll + do! peverify "test_two_fsharp_modules_module_1.dll" + + + // "%FSC%" %fsc_flags% --standalone -r:test_two_fsharp_modules_module_1.dll -o:test_two_fsharp_modules_module_2.exe -g test_two_fsharp_modules_module_2.fs + do! fsc "%s --standalone -r:test_two_fsharp_modules_module_1.dll -o:test_two_fsharp_modules_module_2.exe -g" cfg.fsc_flags ["test_two_fsharp_modules_module_2.fs"] + + // "%PEVERIFY%" test_two_fsharp_modules_module_2.exe + do! peverify "test_two_fsharp_modules_module_2.exe" + + // "%FSC%" %fsc_flags% -a --standalone -r:test_two_fsharp_modules_module_1.dll -o:test_two_fsharp_modules_module_2_as_dll.dll -g test_two_fsharp_modules_module_2.fs + do! fsc "%s -a --standalone -r:test_two_fsharp_modules_module_1.dll -o:test_two_fsharp_modules_module_2_as_dll.dll -g" cfg.fsc_flags ["test_two_fsharp_modules_module_2.fs"] + + // "%PEVERIFY%" test_two_fsharp_modules_module_2_as_dll.dll + do! peverify "test_two_fsharp_modules_module_2_as_dll.dll" + + }) + + + +module Eval = + + [] + let eval p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) diff --git a/tests/fsharp/typeProviders/build-typeprovider-test.fs b/tests/fsharp/typeProviders/build-typeprovider-test.fs new file mode 100644 index 00000000000..dc38e806cc4 --- /dev/null +++ b/tests/fsharp/typeProviders/build-typeprovider-test.fs @@ -0,0 +1,43 @@ +module BuildTypeProviderTest + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open PlatformHelpers +open NUnitConf + +let build (cfg: TestConfig) (dir: string) p = processor { + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let del = Commands.rm dir + + // if EXIST provided.dll del provided.dll + del "provided.dll" + + // "%FSC%" --out:provided.dll -a ..\helloWorld\provided.fs + do! fsc "--out:provided.dll -a" [".."/"helloWorld"/"provided.fs"] + + // if EXIST providedJ.dll del providedJ.dll + del "providedJ.dll" + + // "%FSC%" --out:providedJ.dll -a ..\helloWorld\providedJ.fs + do! fsc "--out:providedJ.dll -a" [".."/"helloWorld"/"providedJ.fs"] + + // if EXIST providedK.dll del providedK.dll + del "providedK.dll" + + // "%FSC%" --out:providedK.dll -a ..\helloWorld\providedK.fs + do! fsc "--out:providedK.dll -a" [".."/"helloWorld"/"providedK.fs"] + + // if EXIST provider.dll del provider.dll + del "provider.dll" + + // "%FSC%" --out:provider.dll -a provider.fsx + do! fsc "--out:provider.dll -a" ["provider.fsx"] + + // call %~d0%~p0..\single-test-build.bat + do! SingleTestBuild.singleTestBuild cfg dir p + + } diff --git a/tests/fsharp/typeProviders/builtin/copyFSharpDataTypeProviderDLL.fs b/tests/fsharp/typeProviders/builtin/copyFSharpDataTypeProviderDLL.fs new file mode 100644 index 00000000000..960fc915a5a --- /dev/null +++ b/tests/fsharp/typeProviders/builtin/copyFSharpDataTypeProviderDLL.fs @@ -0,0 +1,71 @@ +module CopyFSharpDataTypeProviderDLL + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open PlatformHelpers +open NUnitConf + +let copy (cfg: TestConfig) (dir: string) = processor { + let fileExists = Commands.fileExists dir >> Option.isSome + let getfullpath = Commands.getfullpath dir + + let copy_y a = Commands.copy_y dir a >> checkResult + + // REM == Find out OS architecture, no matter what cmd prompt + // SET OSARCH=%PROCESSOR_ARCHITECTURE% + // IF NOT "%PROCESSOR_ARCHITEW6432%"=="" SET OSARCH=%PROCESSOR_ARCHITEW6432% + let osArch = WindowsPlatform.osArch cfg.EnvironmentVariables + + // REM == Find out path to native 'Program Files 32bit', no matter what + // REM == architecture we are running on and no matter what command + // REM == prompt we came from. + // IF /I "%OSARCH%"=="x86" set X86_PROGRAMFILES=%ProgramFiles% + // IF /I "%OSARCH%"=="AMD64" set X86_PROGRAMFILES=%ProgramFiles(x86)% + let x86ProgramFiles = WindowsPlatform.x86ProgramFilesDirectory cfg.EnvironmentVariables osArch + + // REM == Set path to FSharp.Data.TypeProviders.dll + // REM == This binary is frozen at 4.3.0.0 version + // set FSDATATYPEPROVIDERSPATH=%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\FSharp\.NETFramework\v4.0\4.3.0.0\Type Providers\FSharp.Data.TypeProviders.dll + // IF EXIST "%FSCBinPath%\FSharp.Data.TypeProviders.dll" set FSDATATYPEPROVIDERSPATH=%FSCBinPath%\FSharp.Data.TypeProviders.dll + let FSDATATYPEPROVIDERSPATH = + if fileExists (cfg.FSCBinPath/"FSharp.Data.TypeProviders.dll") + then cfg.FSCBinPath/"FSharp.Data.TypeProviders.dll" + else x86ProgramFiles/"Reference Assemblies"/"Microsoft"/"FSharp"/".NETFramework"/"v4.0"/"4.3.0.0"/"Type Providers"/"FSharp.Data.TypeProviders.dll" + + + // REM == Copy the FSharp.Data.TypeProvider.dll + // REM == Note: we need this because we are doing white box testing + // IF EXIST "%FSDATATYPEPROVIDERSPATH%" copy /y "%FSDATATYPEPROVIDERSPATH%" . + do! if fileExists FSDATATYPEPROVIDERSPATH + then copy_y FSDATATYPEPROVIDERSPATH ("."/"FSharp.Data.TypeProviders.dll") + else Success () + + // REM == Copy in config files with needed binding redirects + let xcopy_ry a b = + let removeReadonly p = + let attr = File.GetAttributes(p) + File.SetAttributes(p, attr &&& (~~~ FileAttributes.ReadOnly)) + + if fileExists b then removeReadonly (getfullpath b) + copy_y a b + + let ``test.exe.config`` = __SOURCE_DIRECTORY__/"test.exe.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\test.exe.config*" + do! xcopy_ry ``test.exe.config`` "test.exe.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\testX64.exe.config*" + do! xcopy_ry ``test.exe.config`` "testX64.exe.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\test--optimize.exe.config*" + do! xcopy_ry ``test.exe.config`` "test--optimize.exe.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\test--optimize-lib.dll.config*" + do! xcopy_ry ``test.exe.config`` "test--optimize-lib.dll.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\test--optimize-client-of-lib.exe.config*" + do! xcopy_ry ``test.exe.config`` "test--optimize-client-of-lib.exe.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\test--optminus--debug.exe.config*" + do! xcopy_ry ``test.exe.config`` "test--optminus--debug.exe.config" + // xcopy /RY "%~dp0test.exe.config" "%cd%\test--optplus--debug.exe.config*" + do! xcopy_ry ``test.exe.config`` "test--optplus--debug.exe.config" + + } diff --git a/tests/fsharp/typeProviders/tests_typeProviders.fs b/tests/fsharp/typeProviders/tests_typeProviders.fs new file mode 100644 index 00000000000..f467ad5cfed --- /dev/null +++ b/tests/fsharp/typeProviders/tests_typeProviders.fs @@ -0,0 +1,680 @@ +module ``FSharp-Tests-TypeProviders`` + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open NUnitConf +open PlatformHelpers + +let testContext = FSharpTestSuite.testContext + +let requireVSUltimate cfg = processor { + do! match cfg.INSTALL_SKU with + | Some (Ultimate) -> Success + | x -> + // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( + // echo Test not supported except on Ultimate + NUnitConf.skip (sprintf "Test not supported except on Ultimate, was %A" x) + // exit /b 0 + // ) + } + +module Builtin = + + module EdmxFile = + + [] + let EdmxFile p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + //call %~d0%~p0..\copyFSharpDataTypeProviderDLL.cmd + do! CopyFSharpDataTypeProviderDLL.copy cfg dir + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + module ODataService = + + [] + let oDataService p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + //call %~d0%~p0..\copyFSharpDataTypeProviderDLL.cmd + do! CopyFSharpDataTypeProviderDLL.copy cfg dir + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + module SqlDataConnection = + + [] + let sqlDataConnection p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fileExists = Commands.fileExists dir >> Option.isSome + + //call %~d0%~p0..\copyFSharpDataTypeProviderDLL.cmd + do! CopyFSharpDataTypeProviderDLL.copy cfg dir + + do! SingleTestBuild.singleTestBuild cfg dir p + + // IF /I "%INSTALL_SKU%" NEQ "ULTIMATE" ( + // echo Test not supported except on Ultimate + // exit /b 0 + // ) + do! requireVSUltimate cfg + + // IF EXIST test.exe ( + // echo Running test.exe to warm up SQL + // test.exe > nul 2> nul + // ) + do! if fileExists "test.exe" + then + // echo Running test.exe to warm up SQL + // test.exe > nul 2> nul + exec ("."/"test.exe") "" + else Success () + + do! SingleTestRun.singleTestRun cfg dir p + }) + + module WsdlService = + + [] + let wsdlService p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + //call %~d0%~p0..\copyFSharpDataTypeProviderDLL.cmd + do! CopyFSharpDataTypeProviderDLL.copy cfg dir + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +[] +module DiamondAssembly = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let del = Commands.rm dir + + // if EXIST provider.dll del provider.dll + del "provider.dll" + + // "%FSC%" --out:provided.dll -a ..\helloWorld\provided.fs + do! fsc "%s" "--out:provided.dll -a" [".."/"helloWorld"/"provided.fs"] + + // "%FSC%" --out:provider.dll -a ..\helloWorld\provider.fsx + do! fsc "%s" "--out:provider.dll -a" [".."/"helloWorld"/"provider.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test1.dll -a test1.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test1.dll -a" cfg.fsc_flags ["test1.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2a.dll -a -r:test1.dll test2a.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2a.dll -a -r:test1.dll" cfg.fsc_flags ["test2a.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2b.dll -a -r:test1.dll test2b.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2b.dll -a -r:test1.dll" cfg.fsc_flags ["test2b.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test3.exe -r:test1.dll -r:test2a.dll -r:test2b.dll test3.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test3.exe -r:test1.dll -r:test2a.dll -r:test2b.dll" cfg.fsc_flags ["test3.fsx"] + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsi = Printf.ksprintf (Commands.fsi exec cfg.FSI) + let fileguard = (Commands.getfullpath dir) >> FileGuard.create + + // "%PEVERIFY%" test1.dll + do! peverify "test1.dll" + + // "%PEVERIFY%" test2a.dll + do! peverify "test2a.dll" + + // "%PEVERIFY%" test2b.dll + do! peverify "test2b.dll" + + // "%PEVERIFY%" test3.exe + do! peverify "test3.exe" + + // test3.exe + do! exec ("."/"test3.exe") "" + + + + // if exist test.ok (del /f /q test.ok) + use testOkFile = fileguard "test.ok" + + // %CLIX% "%FSI%" %fsi_flags% test1.fsx test2a.fsx test2b.fsx test3.fsx && ( + do! fsi "%s" cfg.fsi_flags ["test1.fsx"; "test2a.fsx"; "test2b.fsx"; "test3.fsx"] + + // dir test.ok > NUL 2>&1 ) || ( + // @echo :FSI load failed + // set ERRORMSG=%ERRORMSG% FSI load failed; + do! testOkFile |> NUnitConf.checkGuardExists + // ) + + } + + [] + let diamondAssembly () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +module GlobalNamespace = + + [] + let globalNamespace () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + + // %CSC% /out:globalNamespaceTP.dll /debug+ /target:library /r:"%FSCOREDLLPATH%" globalNamespaceTP.cs + do! csc """/out:globalNamespaceTP.dll /debug+ /target:library /r:"%s" """ cfg.FSCOREDLLPATH ["globalNamespaceTP.cs"] + + // "%FSC%" %fsc_flags% /debug+ /r:globalNamespaceTP.dll /optimize- test.fsx + do! fsc "%s /debug+ /r:globalNamespaceTP.dll /optimize-" cfg.fsc_flags ["test.fsx"] + + }) + + +module HelloWorld = + + let build cfg dir p = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let del = Commands.rm dir + let execIn workDir p = Command.exec workDir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc' execIn = Printf.ksprintf (Commands.fsc execIn cfg.FSC) + let mkdir = Commands.mkdir_p dir + let getfullpath = Commands.getfullpath dir + + //if EXIST provided.dll del provided.dll + del "provided.dll" + + //if EXIST provided1.dll del provided1.dll + del "provided1.dll" + + //"%FSC%" --out:provided1.dll -g -a ..\helloWorld\provided.fs + do! fsc "%s" "--out:provided1.dll -g -a" [".."/"helloWorld"/"provided.fs"] + + //if EXIST provided2.dll del provided2.dll + del "provided2.dll" + + //"%FSC%" --out:provided2.dll -g -a ..\helloWorld\provided.fs + do! fsc "%s" "--out:provided2.dll -g -a" [".."/"helloWorld"/"provided.fs"] + + //if EXIST provided3.dll del provided3.dll + del "provided3.dll" + + //"%FSC%" --out:provided3.dll -g -a ..\helloWorld\provided.fs + do! fsc "%s" "--out:provided3.dll -g -a" [".."/"helloWorld"/"provided.fs"] + + //if EXIST provided4.dll del provided4.dll + del "provided4.dll" + + //"%FSC%" --out:provided4.dll -g -a ..\helloWorld\provided.fs + do! fsc "%s" "--out:provided4.dll -g -a" [".."/"helloWorld"/"provided.fs"] + + //if EXIST providedJ.dll del providedJ.dll + del "providedJ.dll" + + //"%FSC%" --out:providedJ.dll -g -a ..\helloWorld\providedJ.fs + do! fsc "%s" "--out:providedJ.dll -g -a" [".."/"helloWorld"/"providedJ.fs"] + + //if EXIST providedK.dll del providedK.dll + del "providedK.dll" + + //"%FSC%" --out:providedK.dll -g -a ..\helloWorld\providedK.fs + do! fsc "%s" "--out:providedK.dll -g -a" [".."/"helloWorld"/"providedK.fs"] + + //"%FSC%" --out:providedNullAssemblyName.dll -g -a ..\helloWorld\providedNullAssemblyName.fsx + do! fsc "%s" "--out:providedNullAssemblyName.dll -g -a" [".."/"helloWorld"/"providedNullAssemblyName.fsx"] + + //call %~d0%~p0\..\build-typeprovider-test.bat + do! BuildTypeProviderTest.build cfg dir p + + //if EXIST provider_with_binary_compat_changes.dll del provider_with_binary_compat_changes.dll + del "provider_with_binary_compat_changes.dll" + + //mkdir bincompat1 + mkdir "bincompat1" + + //pushd bincompat1 + log "pushd bincompat1" + let bincompat1 = getfullpath "bincompat1" + + //xcopy /y ..\*.dll . + Directory.EnumerateFiles(bincompat1/"..", "*.dll") + |> Seq.iter (fun from -> Commands.copy_y bincompat1 from ("."/Path.GetFileName(from)) |> ignore) + + //"%FSC%" -g -a -o:test_lib.dll -r:provider.dll ..\test.fsx + do! fsc' (execIn bincompat1) "%s" "-g -a -o:test_lib.dll -r:provider.dll" [".."/"test.fsx"] + + //"%FSC%" -r:test_lib.dll -r:provider.dll ..\testlib_client.fsx + do! fsc' (execIn bincompat1) "%s" "-r:test_lib.dll -r:provider.dll" [".."/"testlib_client.fsx"] + + //popd + log "popd" + + //mkdir bincompat2 + mkdir "bincompat2" + + //pushd bincompat2 + log "pushd bincompat2" + let bincompat2 = getfullpath "bincompat2" + + //xcopy /y ..\bincompat1\*.dll . + Directory.EnumerateFiles(bincompat2/".."/"bincompat1", "*.dll") + |> Seq.iter (fun from -> Commands.copy_y bincompat2 from ("."/Path.GetFileName(from)) |> ignore) + + + //REM overwrite provider.dll + //"%FSC%" --define:ADD_AN_OPTIONAL_STATIC_PARAMETER --define:USE_IMPLICIT_ITypeProvider2 --out:provider.dll -g -a ..\provider.fsx + do! fsc' (execIn bincompat2) "%s" "--define:ADD_AN_OPTIONAL_STATIC_PARAMETER --define:USE_IMPLICIT_ITypeProvider2 --out:provider.dll -g -a" [".."/"provider.fsx"] + + // "%FSC%" -g -a -o:test_lib_recompiled.dll -r:provider.dll ..\test.fsx + do! fsc' (execIn bincompat2) "-g -a -o:test_lib_recompiled.dll -r:provider.dll" [".."/"test.fsx"] + + //REM This is the important part of the binary compatibility part of the test: the new provider is being used, but + //REM with a binary that was generated w.r.t. the old provider. The new provider can still resolve the references + //REM generated by the old provider which are stored in the F# metadata for test_lib.dll + //"%FSC%" --define:ADD_AN_OPTIONAL_STATIC_PARAMETER -r:test_lib.dll -r:provider.dll ..\testlib_client.fsx + do! fsc' (execIn bincompat2) "%s" "--define:ADD_AN_OPTIONAL_STATIC_PARAMETER -r:test_lib.dll -r:provider.dll" [".."/"testlib_client.fsx"] + + //"%PEVERIFY%" provider.dll + do! peverify (bincompat2/"provider.dll") + + //"%PEVERIFY%" test_lib.dll + do! peverify (bincompat2/"test_lib.dll") + + // "%PEVERIFY%" test_lib_recompiled.dll + do! peverify (bincompat2/"test_lib_recompiled.dll") + + //"%PEVERIFY%" testlib_client.exe + do! peverify (bincompat2/"testlib_client.exe") + + } + + [] + let helloWorld p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + + }) + + + +module HelloWorldCSharp = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + let del = Commands.rm dir + let gacutil = Commands.gacutil exec cfg.GACUTIL + + // if EXIST magic.dll del magic.dll + del "magic.dll" + + // "%FSC%" --out:magic.dll -a magic.fs --keyfile:magic.snk + do! fsc "%s" "--out:magic.dll -a --keyfile:magic.snk" ["magic.fs "] + + // REM == If we are running this test on a lab machine, we may not be running from an elev cmd prompt + // REM == In that case, ADMIN_PIPE is set to the tool to invoke the command elevated. + // IF DEFINED ADMIN_PIPE %ADMIN_PIPE% %GACUTIL% /if magic.dll + + //REVIEW check ADMIN_PIPE and elevated gac + ignore "useless ADMIN_PIPE, test are run as administrator" + + // if EXIST provider.dll del provider.dll + del "provider.dll" + + // %CSC% /out:provider.dll /target:library "/r:%FSCOREDLLPATH%" /r:magic.dll provider.cs + do! csc """/out:provider.dll /target:library "/r:%s" /r:magic.dll""" cfg.FSCOREDLLPATH ["provider.cs"] + + // "%GACUTIL%" /if magic.dll + do! gacutil "/if" "magic.dll" + + // "%FSC%" %fsc_flags% /debug+ /r:provider.dll /optimize- test.fsx + do! fsc "%s /debug+ /r:provider.dll /optimize-" cfg.fsc_flags ["test.fsx"] + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%PEVERIFY%" magic.dll + do! peverify "magic.dll" + + // "%PEVERIFY%" provider.dll + do! peverify "provider.dll" + + // "%PEVERIFY%" test.exe + do! peverify "test.exe" + + // test.exe + do! exec ("."/"test.exe") "" + + } + + [] + let helloWorldCSharp () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) + + + +[] +module NegTests = + + let testData = + // set TESTS_SIMPLE=neg2h neg4 neg1 neg1_a neg2 neg2c neg2e neg2g neg6 + let testsSimple = + ["neg2h"; "neg4"; "neg1"; "neg1_a"; "neg2"; "neg2c"; "neg2e"; "neg2g"; "neg6"] + // REM neg7 - excluded + // set TESTS_SIMPLE=%TESTS_SIMPLE% InvalidInvokerExpression providerAttributeErrorConsume ProviderAttribute_EmptyConsume + @ ["InvalidInvokerExpression"; "providerAttributeErrorConsume"; "ProviderAttribute_EmptyConsume"] + + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetNestedNamespaces_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_NamespaceName_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_NamespaceName_Empty + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetTypes_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_ResolveTypeName_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetNamespaces_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetStaticParameters_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetInvokerExpression_Exception + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetTypes_Null + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_ResolveTypeName_Null + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetNamespaces_Null + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetStaticParameters_Null + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_GetInvokerExpression_Null + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_DoesNotHaveConstructor + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_ConstructorThrows + // set TESTS_WITH_DEFINE=%TESTS_WITH_DEFINE% EVIL_PROVIDER_ReturnsTypeWithIncorrectNameFromApplyStaticArguments + let testsWithDefine = [ + "EVIL_PROVIDER_GetNestedNamespaces_Exception"; + "EVIL_PROVIDER_NamespaceName_Exception"; + "EVIL_PROVIDER_NamespaceName_Empty"; + "EVIL_PROVIDER_GetTypes_Exception"; + "EVIL_PROVIDER_ResolveTypeName_Exception"; + "EVIL_PROVIDER_GetNamespaces_Exception"; + "EVIL_PROVIDER_GetStaticParameters_Exception"; + "EVIL_PROVIDER_GetInvokerExpression_Exception"; + "EVIL_PROVIDER_GetTypes_Null"; + "EVIL_PROVIDER_ResolveTypeName_Null"; + "EVIL_PROVIDER_GetNamespaces_Null"; + "EVIL_PROVIDER_GetStaticParameters_Null"; + "EVIL_PROVIDER_GetInvokerExpression_Null"; + "EVIL_PROVIDER_DoesNotHaveConstructor"; + "EVIL_PROVIDER_ConstructorThrows"; + "EVIL_PROVIDER_ReturnsTypeWithIncorrectNameFromApplyStaticArguments" ] + + (testsSimple @ testsWithDefine) + |> List.map (fun t -> FSharpSuiteTestCaseData("typeProviders/negTests", t)) + + [] + let negTests name = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Commands.fsc exec cfg.FSC + let del = Commands.rm dir + let fileExists = Commands.fileExists dir >> Option.isSome + let getfullpath = Commands.getfullpath dir + + // if EXIST provided.dll del provided.dll + del "provided.dll" + + // "%FSC%" --out:provided.dll -a ..\helloWorld\provided.fs + do! fsc "--out:provided.dll -a" [".."/"helloWorld"/"provided.fs"] + + // if EXIST providedJ.dll del providedJ.dll + del "providedJ.dll" + + // "%FSC%" --out:providedJ.dll -a ..\helloWorld\providedJ.fs + do! fsc "--out:providedJ.dll -a" [".."/"helloWorld"/"providedJ.fs"] + + // if EXIST providedK.dll del providedK.dll + del "providedK.dll" + + // "%FSC%" --out:providedK.dll -a ..\helloWorld\providedK.fs + do! fsc "--out:providedK.dll -a" [".."/"helloWorld"/"providedK.fs"] + + // if EXIST provider.dll del provider.dll + del "provider.dll" + + // "%FSC%" --out:provider.dll -a provider.fsx + do! fsc "--out:provider.dll -a" ["provider.fsx"] + + // "%FSC%" --out:provider_providerAttributeErrorConsume.dll -a providerAttributeError.fsx + do! fsc "--out:provider_providerAttributeErrorConsume.dll -a" ["providerAttributeError.fsx"] + + // "%FSC%" --out:provider_ProviderAttribute_EmptyConsume.dll -a providerAttribute_Empty.fsx + do! fsc "--out:provider_ProviderAttribute_EmptyConsume.dll -a" ["providerAttribute_Empty.fsx"] + + // if EXIST helloWorldProvider.dll del helloWorldProvider.dll + del "helloWorldProvider.dll" + + // "%FSC%" --out:helloWorldProvider.dll -a ..\helloWorld\provider.fsx + do! fsc "--out:helloWorldProvider.dll -a" [".."/"helloWorld"/"provider.fsx"] + + // if EXIST MostBasicProvider.dll del MostBasicProvider.dll + del "MostBasicProvider.dll" + + // "%FSC%" --out:MostBasicProvider.dll -a MostBasicProvider.fsx + do! fsc "--out:MostBasicProvider.dll -a" ["MostBasicProvider.fsx"] + + //REVIEW use testfixture setup to run this code ---^ only once? + + // if "%1"=="" goto :RunAllTests + // if "%1"=="--withDefine" goto :RunSpecificWithDefine + // call :RunTest %1 + // goto :ReportResults + ignore "is a parametrized test, like --withDefine" + + // :Preprocess + let preprocess bslppName pref = processor { + + let tempFile = Path.GetTempFileName() + + let ``exec <`` l p = Command.exec dir cfg.EnvironmentVariables { Output = Output(Overwrite(tempFile)); Input = Some(RedirectInput(l)) } p >> checkResult + let ``| exec >`` out p = Command.exec dir cfg.EnvironmentVariables { Output = Output(Overwrite(out)); Input = Some(RedirectInput(tempFile)) } p >> checkResult + + let ``fsi <`` = Printf.ksprintf (fun flags l -> Commands.fsi (``exec <`` l) cfg.FSI flags []) + let ``| fsi >`` = Printf.ksprintf (fun flags sources out -> Commands.fsi (``| exec >`` out) cfg.FSI flags sources) + + // "%FSI%" --exec sed.fsx "" "%~d0%~p0provider_%1.dll" < %~1.%~2bslpp + do! ``fsi <`` """--exec sed.fsx "" "%s" """ (getfullpath (sprintf "provider_%s.dll" name)) (sprintf "%s.%sbslpp" bslppName pref) + + // | fsi --exec sed.fsx "" "file:///%CD%\\" > %~1.%~2bsl + do! ``| fsi >`` """--exec sed.fsx "" "%O" """ (Uri(dir |> Commands.pathAddBackslash)) [] (sprintf "%s.%sbsl" bslppName pref) + } + + // :RunTestWithDefine + let runTestWithDefine = processor { + // "%FSC%" --define:%1 --out:provider_%1.dll -a provider.fsx + do! fsc (sprintf "--define:%s --out:provider_%s.dll -a" name name) ["provider.fsx"] + + // :RunTest + // if EXIST %1.bslpp call :Preprocess "%1" "" + do! if fileExists (sprintf "%s.bslpp" name) + then preprocess name "" + else Success + + // if EXIST %1.vsbslpp call :Preprocess "%1" "vs" + do! if fileExists (sprintf "%s.vsbslpp" name) + then preprocess name "vs" + else Success + + // :DoRunTest + // call ..\..\single-neg-test.bat %1 + do! SingleNegTest.singleNegTest cfg dir name + + } + + // :RunSpecificWithDefine + // call :RunTestWithDefine %2 + do! runTestWithDefine + // goto :ReportResults + ignore "useless, checked already" + + // :RunAllTests + // for %%T in (%TESTS_SIMPLE%) do call :RunTest %%T + // for %%T in (%TESTS_WITH_DEFINE%) do call :RunTestWithDefine %%T + ignore "is a parametrized test" + + + }) + + +module SplitAssembly = + + [] + let splitAssembly p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + + // "%FSC%" --out:provider.dll -a provider.fs + do! fsc "--out:provider.dll -a" ["provider.fs"] + + // "%FSC%" --out:providerDesigner.dll -a providerDesigner.fsx + do! fsc "--out:providerDesigner.dll -a" ["providerDesigner.fsx"] + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + + +module WedgeAssembly = + + let build cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let del = Commands.rm dir + + // if EXIST provider.dll del provider.dll + del "provider.dll" + + // if EXIST provided.dll del provided.dll + del "provided.dll" + + // "%FSC%" --out:provided.dll -a ..\helloWorld\provided.fs + do! fsc "%s" "--out:provided.dll -a" [".."/"helloWorld"/"provided.fs"] + + // if EXIST providedJ.dll del providedJ.dll + del "providedJ.dll" + + // "%FSC%" --out:providedJ.dll -a ..\helloWorld\providedJ.fs + do! fsc "%s" "--out:providedJ.dll -a" [".."/"helloWorld"/"providedJ.fs"] + + // if EXIST providedK.dll del providedK.dll + del "providedK.dll" + + // "%FSC%" --out:providedK.dll -a ..\helloWorld\providedK.fs + do! fsc "%s" "--out:providedK.dll -a" [".."/"helloWorld"/"providedK.fs"] + + // "%FSC%" --out:provider.dll -a ..\helloWorld\provider.fsx + do! fsc "%s" "--out:provider.dll -a" [".."/"helloWorld"/"provider.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2a.dll -a test2a.fs + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2a.dll -a" cfg.fsc_flags ["test2a.fs"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2b.dll -a test2b.fs + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2b.dll -a" cfg.fsc_flags ["test2b.fs"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test3.exe test3.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test3.exe" cfg.fsc_flags ["test3.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2a-with-sig.dll -a test2a.fsi test2a.fs + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2a-with-sig.dll -a" cfg.fsc_flags ["test2a.fsi"; "test2a.fs"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2b-with-sig.dll -a test2b.fsi test2b.fs + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2b-with-sig.dll -a" cfg.fsc_flags ["test2b.fsi"; "test2b.fs"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test3-with-sig.exe --define:SIGS test3.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test3-with-sig.exe --define:SIGS" cfg.fsc_flags ["test3.fsx"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2a-with-sig-restricted.dll -a test2a-restricted.fsi test2a.fs + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2a-with-sig-restricted.dll -a" cfg.fsc_flags ["test2a-restricted.fsi"; "test2a.fs"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test2b-with-sig-restricted.dll -a test2b-restricted.fsi test2b.fs + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test2b-with-sig-restricted.dll -a"cfg.fsc_flags ["test2b-restricted.fsi"; "test2b.fs"] + + // "%FSC%" %fsc_flags% --debug+ -r:provider.dll --optimize- -o:test3-with-sig-restricted.exe --define:SIGS_RESTRICTED test3.fsx + do! fsc "%s --debug+ -r:provider.dll --optimize- -o:test3-with-sig-restricted.exe --define:SIGS_RESTRICTED" cfg.fsc_flags ["test3.fsx"] + + } + + let run cfg dir = processor { + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let peverify = Commands.peverify exec cfg.PEVERIFY + + // "%PEVERIFY%" test2a.dll + do! peverify "test2a.dll" + + // "%PEVERIFY%" test2b.dll + do! peverify "test2b.dll" + + // "%PEVERIFY%" test3.exe + do! peverify "test3.exe" + + // test3.exe + do! exec ("."/"test3.exe") "" + + } + + [] + let wedgeAssembly () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! build cfg dir + + do! run cfg dir + + }) diff --git a/tests/fsharp/typecheck/tests_typecheck.fs b/tests/fsharp/typecheck/tests_typecheck.fs new file mode 100644 index 00000000000..d8e715b8054 --- /dev/null +++ b/tests/fsharp/typecheck/tests_typecheck.fs @@ -0,0 +1,311 @@ +module ``FSharp-Tests-Typecheck`` + +open System +open System.IO +open NUnit.Framework + +open FSharpTestSuiteTypes +open NUnitConf +open PlatformHelpers + +let testContext = FSharpTestSuite.testContext + + +module ``Full-rank-arrays`` = + + [] + let ``full-rank-arrays`` p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let csc = Printf.ksprintf (Commands.csc exec cfg.CSC) + + // %CSC% /target:library /out:HighRankArrayTests.dll .\Class1.cs + do! csc "/target:library /out:HighRankArrayTests.dll" ["Class1.cs"] + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module Misc = + + [] + let misc p = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + do! SingleTestBuild.singleTestBuild cfg dir p + + do! SingleTestRun.singleTestRun cfg dir p + }) + + +module Sigs = + + [] + let sigs () = check (processor { + let { Directory = dir; Config = cfg } = testContext () + + let exec p = Command.exec dir cfg.EnvironmentVariables { Output = Inherit; Input = None; } p >> checkResult + let fsc = Printf.ksprintf (Commands.fsc exec cfg.FSC) + let peverify = Commands.peverify exec cfg.PEVERIFY + let fsc_flags = cfg.fsc_flags + + let singleNegTest = SingleNegTest.singleNegTest cfg dir + + + // call ..\..\single-neg-test.bat neg91 + do! singleNegTest "neg91" + + // "%FSC%" %fsc_flags% --target:exe -o:pos20.exe pos20.fs + do! fsc "%s --target:exe -o:pos20.exe" fsc_flags ["pos20.fs"] + // "%PEVERIFY%" pos20.exe + do! peverify "pos20.exe" + // pos20.exe + do! exec ("."/"pos20.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos19.exe pos19.fs + do! fsc "%s --target:exe -o:pos19.exe" fsc_flags ["pos19.fs"] + // "%PEVERIFY%" pos19.exe + do! peverify "pos19.exe" + // pos19.exe + do! exec ("."/"pos19.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos18.exe pos18.fs + do! fsc "%s --target:exe -o:pos18.exe" fsc_flags ["pos18.fs"] + // "%PEVERIFY%" pos18.exe + do! peverify "pos18.exe" + // pos18.exe + do! exec ("."/"pos18.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos16.exe pos16.fs + do! fsc "%s --target:exe -o:pos16.exe" fsc_flags ["pos16.fs"] + // "%PEVERIFY%" pos16.exe + do! peverify "pos16.exe" + // pos16.exe + do! exec ("."/"pos16.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos17.exe pos17.fs + do! fsc "%s --target:exe -o:pos17.exe" fsc_flags ["pos17.fs"] + // "%PEVERIFY%" pos17.exe + do! peverify "pos17.exe" + // pos17.exe + do! exec ("."/"pos17.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos15.exe pos15.fs + do! fsc "%s --target:exe -o:pos15.exe" fsc_flags ["pos15.fs"] + // "%PEVERIFY%" pos15.exe + do! peverify "pos15.exe" + // pos15.exe + do! exec ("."/"pos15.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos14.exe pos14.fs + do! fsc "%s --target:exe -o:pos14.exe" fsc_flags ["pos14.fs"] + // "%PEVERIFY%" pos14.exe + do! peverify "pos14.exe" + // pos14.exe + do! exec ("."/"pos14.exe") "" + + // "%FSC%" %fsc_flags% --target:exe -o:pos13.exe pos13.fs + do! fsc "%s --target:exe -o:pos13.exe" fsc_flags ["pos13.fs"] + // "%PEVERIFY%" pos13.exe + do! peverify "pos13.exe" + // pos13.exe + do! exec ("."/"pos13.exe") "" + + // "%FSC%" %fsc_flags% -a -o:pos12.dll pos12.fs + do! fsc "%s -a -o:pos12.dll" fsc_flags ["pos12.fs"] + + // "%FSC%" %fsc_flags% -a -o:pos11.dll pos11.fs + do! fsc "%s -a -o:pos11.dll" fsc_flags ["pos11.fs"] + + // "%FSC%" %fsc_flags% -a -o:pos10.dll pos10.fs + do! fsc "%s -a -o:pos10.dll" fsc_flags ["pos10.fs"] + + // "%PEVERIFY%" pos10.dll + do! peverify "pos10.dll" + + // call ..\..\single-neg-test.bat neg90 + // call ..\..\single-neg-test.bat neg89 + // call ..\..\single-neg-test.bat neg88 + do! processor.For (["neg90"; "neg89"; "neg88"], singleNegTest) + + // "%FSC%" %fsc_flags% -a -o:pos09.dll pos09.fs + do! fsc "%s -a -o:pos09.dll" fsc_flags ["pos09.fs"] + + // "%PEVERIFY%" pos09.dll + do! peverify "pos09.dll" + + // call ..\..\single-neg-test.bat neg87 + // call ..\..\single-neg-test.bat neg86 + // call ..\..\single-neg-test.bat neg85 + // call ..\..\single-neg-test.bat neg84 + // call ..\..\single-neg-test.bat neg83 + // call ..\..\single-neg-test.bat neg82 + // call ..\..\single-neg-test.bat neg81 + // call ..\..\single-neg-test.bat neg80 + // call ..\..\single-neg-test.bat neg79 + // call ..\..\single-neg-test.bat neg78 + // call ..\..\single-neg-test.bat neg77 + // call ..\..\single-neg-test.bat neg76 + // call ..\..\single-neg-test.bat neg75 + // call ..\..\single-neg-test.bat neg74 + // call ..\..\single-neg-test.bat neg73 + // call ..\..\single-neg-test.bat neg72 + // call ..\..\single-neg-test.bat neg71 + // call ..\..\single-neg-test.bat neg70 + // call ..\..\single-neg-test.bat neg69 + // call ..\..\single-neg-test.bat neg68 + // call ..\..\single-neg-test.bat neg67 + // call ..\..\single-neg-test.bat neg66 + // call ..\..\single-neg-test.bat neg65 + // call ..\..\single-neg-test.bat neg64 + // call ..\..\single-neg-test.bat neg61 + // call ..\..\single-neg-test.bat neg63 + // call ..\..\single-neg-test.bat neg62 + // call ..\..\single-neg-test.bat neg20 + // call ..\..\single-neg-test.bat neg24 + // call ..\..\single-neg-test.bat neg32 + // call ..\..\single-neg-test.bat neg37 + // call ..\..\single-neg-test.bat neg37_a + // call ..\..\single-neg-test.bat neg60 + // call ..\..\single-neg-test.bat neg59 + // call ..\..\single-neg-test.bat neg58 + // call ..\..\single-neg-test.bat neg57 + // call ..\..\single-neg-test.bat neg56 + // call ..\..\single-neg-test.bat neg56_a + // call ..\..\single-neg-test.bat neg56_b + // call ..\..\single-neg-test.bat neg55 + // call ..\..\single-neg-test.bat neg54 + // call ..\..\single-neg-test.bat neg53 + // call ..\..\single-neg-test.bat neg52 + // call ..\..\single-neg-test.bat neg51 + // call ..\..\single-neg-test.bat neg50 + // call ..\..\single-neg-test.bat neg49 + // call ..\..\single-neg-test.bat neg48 + // call ..\..\single-neg-test.bat neg47 + // call ..\..\single-neg-test.bat neg46 + // call ..\..\single-neg-test.bat neg10 + // call ..\..\single-neg-test.bat neg10_a + // call ..\..\single-neg-test.bat neg45 + // call ..\..\single-neg-test.bat neg44 + // call ..\..\single-neg-test.bat neg43 + // call ..\..\single-neg-test.bat neg38 + // call ..\..\single-neg-test.bat neg39 + // call ..\..\single-neg-test.bat neg40 + // call ..\..\single-neg-test.bat neg41 + // call ..\..\single-neg-test.bat neg42 + do! processor.For (["neg87"; "neg86"; "neg85"; "neg84"; "neg83"; "neg82"; "neg81"; "neg80"; "neg79"; "neg78"; "neg77"; "neg76"; "neg75"; "neg74"; "neg73"; "neg72"; "neg71"; "neg70"; "neg69"; "neg68"; "neg67"; "neg66"; "neg65"; "neg64"; "neg61"; "neg63"; "neg62"; "neg20"; "neg24"; "neg32"; "neg37"; "neg37_a"; "neg60"; "neg59"; "neg58"; "neg57"; "neg56"; "neg56_a"; "neg56_b"; "neg55"; "neg54"; "neg53"; "neg52"; "neg51"; "neg50"; "neg49"; "neg48"; "neg47"; "neg46"; "neg10"; "neg10_a"; "neg45"; "neg44"; "neg43"; "neg38"; "neg39"; "neg40"; "neg41"; "neg42"], singleNegTest) + + // "%FSC%" %fsc_flags% -a -o:pos07.dll pos07.fs + do! fsc "%s -a -o:pos07.dll" fsc_flags ["pos07.fs"] + + // "%PEVERIFY%" pos07.dll + do! peverify "pos07.dll" + + + // "%FSC%" %fsc_flags% -a -o:pos08.dll pos08.fs + do! fsc "%s -a -o:pos08.dll" fsc_flags ["pos08.fs"] + + // "%PEVERIFY%" pos08.dll + do! peverify "pos08.dll" + + // "%FSC%" %fsc_flags% -a -o:pos06.dll pos06.fs + do! fsc "%s -a -o:pos06.dll" fsc_flags ["pos06.fs"] + + // "%PEVERIFY%" pos06.dll + do! peverify "pos06.dll" + + + // "%FSC%" %fsc_flags% -a -o:pos03.dll pos03.fs + do! fsc "%s -a -o:pos03.dll" fsc_flags ["pos03.fs"] + + // "%PEVERIFY%" pos03.dll + do! peverify "pos03.dll" + + // "%FSC%" %fsc_flags% -a -o:pos03a.dll pos03a.fsi pos03a.fs + do! fsc "%s -a -o:pos03a.dll" fsc_flags ["pos03a.fsi"; "pos03a.fs"] + + // "%PEVERIFY%" pos03a.dll + do! peverify "pos03a.dll" + + + // call ..\..\single-neg-test.bat neg34 + // call ..\..\single-neg-test.bat neg33 + // call ..\..\single-neg-test.bat neg30 + // call ..\..\single-neg-test.bat neg31 + // call ..\..\single-neg-test.bat neg29 + // call ..\..\single-neg-test.bat neg28 + // call ..\..\single-neg-test.bat neg07 + // call ..\..\single-neg-test.bat neg_byref_20 + // call ..\..\single-neg-test.bat neg_byref_1 + // call ..\..\single-neg-test.bat neg_byref_2 + // call ..\..\single-neg-test.bat neg_byref_3 + // call ..\..\single-neg-test.bat neg_byref_4 + // call ..\..\single-neg-test.bat neg_byref_5 + // call ..\..\single-neg-test.bat neg_byref_6 + // call ..\..\single-neg-test.bat neg_byref_7 + // call ..\..\single-neg-test.bat neg_byref_8 + // call ..\..\single-neg-test.bat neg_byref_10 + // call ..\..\single-neg-test.bat neg_byref_11 + // call ..\..\single-neg-test.bat neg_byref_12 + // call ..\..\single-neg-test.bat neg_byref_13 + // call ..\..\single-neg-test.bat neg_byref_14 + // call ..\..\single-neg-test.bat neg_byref_15 + // call ..\..\single-neg-test.bat neg_byref_16 + // call ..\..\single-neg-test.bat neg_byref_17 + // call ..\..\single-neg-test.bat neg_byref_18 + // call ..\..\single-neg-test.bat neg_byref_19 + // call ..\..\single-neg-test.bat neg_byref_21 + // call ..\..\single-neg-test.bat neg_byref_22 + // call ..\..\single-neg-test.bat neg_byref_23 + // call ..\..\single-neg-test.bat neg36 + // call ..\..\single-neg-test.bat neg17 + // call ..\..\single-neg-test.bat neg26 + // call ..\..\single-neg-test.bat neg27 + // call ..\..\single-neg-test.bat neg25 + // call ..\..\single-neg-test.bat neg03 + // call ..\..\single-neg-test.bat neg23 + // call ..\..\single-neg-test.bat neg22 + // call ..\..\single-neg-test.bat neg21 + // call ..\..\single-neg-test.bat neg04 + // call ..\..\single-neg-test.bat neg05 + // call ..\..\single-neg-test.bat neg06 + // call ..\..\single-neg-test.bat neg06_a + // call ..\..\single-neg-test.bat neg06_b + // call ..\..\single-neg-test.bat neg08 + // call ..\..\single-neg-test.bat neg09 + // call ..\..\single-neg-test.bat neg11 + // call ..\..\single-neg-test.bat neg12 + // call ..\..\single-neg-test.bat neg13 + // call ..\..\single-neg-test.bat neg14 + // call ..\..\single-neg-test.bat neg16 + // call ..\..\single-neg-test.bat neg18 + // call ..\..\single-neg-test.bat neg19 + // call ..\..\single-neg-test.bat neg01 + // call ..\..\single-neg-test.bat neg02 + // call ..\..\single-neg-test.bat neg15 + + do! processor.For(["neg34"; "neg33"; "neg30"; "neg31"; "neg29"; "neg28"; "neg07"; "neg_byref_20"; "neg_byref_1"; "neg_byref_2"; "neg_byref_3"; "neg_byref_4"; "neg_byref_5"; "neg_byref_6"; "neg_byref_7"; "neg_byref_8"; "neg_byref_10"; "neg_byref_11"; "neg_byref_12"; "neg_byref_13"; "neg_byref_14"; "neg_byref_15"; "neg_byref_16"; "neg_byref_17"; "neg_byref_18"; "neg_byref_19"; "neg_byref_21"; "neg_byref_22"; "neg_byref_23"; "neg36"; "neg17"; "neg26"; "neg27"; "neg25"; "neg03"; "neg23"; "neg22"; "neg21"; "neg04"; "neg05"; "neg06"; "neg06_a"; "neg06_b"; "neg08"; "neg09"; "neg11"; "neg12"; "neg13"; "neg14"; "neg16"; "neg18"; "neg19"; "neg01"; "neg02"; "neg15" ], singleNegTest) + + // echo Some random positive cases found while developing the negative tests + // "%FSC%" %fsc_flags% -a -o:pos01a.dll pos01a.fsi pos01a.fs + do! fsc "%s -a -o:pos01a.dll" fsc_flags ["pos01a.fsi"; "pos01a.fs"] + + // "%PEVERIFY%" pos01a.dll + do! peverify "pos01a.dll" + + // "%FSC%" %fsc_flags% -a -o:pos02.dll pos02.fs + do! fsc "%s -a -o:pos02.dll" fsc_flags ["pos02.fs"] + + // "%PEVERIFY%" pos02.dll + do! peverify "pos02.dll" + + // call ..\..\single-neg-test.bat neg35 + do! singleNegTest "neg35" + + // "%FSC%" %fsc_flags% -a -o:pos05.dll pos05.fs + do! fsc "%s -a -o:pos05.dll" fsc_flags ["pos05.fs"] + + }) diff --git a/tests/windowsPlatform.fs b/tests/windowsPlatform.fs new file mode 100644 index 00000000000..d5af155c10a --- /dev/null +++ b/tests/windowsPlatform.fs @@ -0,0 +1,101 @@ +[] +module WindowsPlatform + +open PlatformHelpers + +// REM == Find out path to native 'Program Files 32bit', no matter what +// REM == architecture we are running on and no matter what command +// REM == prompt we came from. +// IF /I "%OSARCH%"=="x86" set X86_PROGRAMFILES=%ProgramFiles% +// IF /I "%OSARCH%"=="IA64" set X86_PROGRAMFILES=%ProgramFiles(x86)% +// IF /I "%OSARCH%"=="AMD64" set X86_PROGRAMFILES=%ProgramFiles(x86)% +let x86ProgramFilesDirectory envVars osArch = + match osArch with + | X86 -> envVars |> Map.find "ProgramFiles" + | IA64 -> envVars |> Map.find "ProgramFiles(x86)" + | AMD64 -> envVars |> Map.find "ProgramFiles(x86)" + | Unknown os -> failwithf "OSARCH '%s' not supported" os + +let private parseProcessorArchitecture (s : string) = + match s.ToUpper() with + | "X86" -> X86 + | "IA64" -> IA64 + | "AMD64" -> AMD64 + | arc -> Unknown s + +/// +/// Return current process architecture, using PROCESSOR_ARCHITECTURE environment variable +/// +let processorArchitecture envVars = + match envVars |> Map.tryFind "PROCESSOR_ARCHITECTURE" |> Option.map parseProcessorArchitecture with + | Some x -> x + | None -> failwithf "environment variable '%s' required " "PROCESSOR_ARCHITECTURE" + +/// +/// Return real processor architecture (ignore WOW64) +/// more info: http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx +/// use PROCESSOR_ARCHITEW6432 and PROCESSOR_ARCHITECTURE environment variables +/// +let osArch envVars = + // SET OSARCH=%PROCESSOR_ARCHITECTURE% + // IF NOT "%PROCESSOR_ARCHITEW6432%"=="" SET OSARCH=%PROCESSOR_ARCHITEW6432% + match envVars |> Map.tryFind "PROCESSOR_ARCHITEW6432" |> Option.map parseProcessorArchitecture with + | Some arc -> arc + | None -> processorArchitecture envVars + + +// %~i - expands %i removing any surrounding quotes (") +// %~fi - expands %i to a fully qualified path name +// %~di - expands %i to a drive letter only +// %~pi - expands %i to a path only +// %~ni - expands %i to a file name only +// %~xi - expands %i to a file extension only +// %~si - expanded path contains short names only + +open Microsoft.Win32 + +let regQuery path value (baseKey: RegistryKey) = + use regKey = baseKey.OpenSubKey(path, false) + + if (regKey = null) then None + else + match regKey.GetValue(value) with + | null -> None + | x -> Some x + +open System.Text.RegularExpressions +open FSharpTestSuiteTypes + +let visualStudioVersion () = + + let hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) + let keys = hklm32.OpenSubKey(@"Software\Microsoft\VisualStudio\14.0\Setup").GetSubKeyNames() + let findstr r = Array.exists (fun t -> Regex.IsMatch(t, r)) keys + + // reg query "%REG_SOFTWARE%\Microsoft\VisualStudio\14.0\Setup" | findstr /r /c:"Express .* for Windows Desktop" > NUL + // if NOT ERRORLEVEL 1 ( + // set INSTALL_SKU=DESKTOP_EXPRESS + // goto :done_SKU + // ) + if findstr "Express .* for Windows Desktop" + then Some INSTALL_SKU.DesktopExpress + + // reg query "%REG_SOFTWARE%\Microsoft\VisualStudio\14.0\Setup" | findstr /r /c:"Express .* for Web" > NUL + // if NOT ERRORLEVEL 1 ( + // set INSTALL_SKU=WEB_EXPRESS + // goto :done_SKU + // ) + elif findstr "Express .* for Web" + then Some INSTALL_SKU.WebExpress + + // reg query "%REG_SOFTWARE%\Microsoft\VisualStudio\14.0\Setup" | findstr /r /c:"Ultimate" > NUL + // if NOT ERRORLEVEL 1 ( + // set INSTALL_SKU=ULTIMATE + // goto :done_SKU + // ) + elif findstr "Ultimate" + then Some INSTALL_SKU.Ultimate + + // set INSTALL_SKU=CLEAN + // :done_SKU + else Some INSTALL_SKU.Clean