<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- This is the target that copies the test assets to the test output -->
  <Import Project="$(MSBuildThisFileDirectory)publishtest.targets" />
  <UsingTask TaskName="GetTargetMachineInfo" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
  <!-- Which categories of tests to run by default -->
  <PropertyGroup>
    <TestDisabled>false</TestDisabled>
    <TestDisabled Condition="'$(IsTestProject)'!='true' Or '$(SkipTests)'=='true' Or '$(RunTestsForProject)'=='false'">true</TestDisabled>
    <TestsSuccessfulSemaphore>tests.passed</TestsSuccessfulSemaphore>
  </PropertyGroup>

  <ItemGroup>
    <!-- Split semicolon separated lists -->
    <WithCategoriesItems Include="$(WithCategories)" />
    <WithoutCategoriesItems Include="$(WithoutCategories)" />
    <DefaultNoCategories Include="$(DefaultNoCategories)" />
    <UnsupportedPlatformsItems Include="$(UnsupportedPlatforms)"/>
  </ItemGroup>

  <PropertyGroup>
    <TestWithCore Condition="'$(TestWithCore)' == '' And '$(TargetGroup)' == 'net45'">false</TestWithCore>
    <TestWithCore Condition="'$(TestWithCore)' == '' And '$(TargetGroup)' == 'net46'">false</TestWithCore>
    <TestWithCore Condition="'$(TestWithCore)' == '' And '$(TargetGroup)' == 'net461'">false</TestWithCore>
    <TestWithCore Condition="'$(TestWithCore)' == '' And '$(TargetGroup)' == 'net462'">false</TestWithCore>
    <TestWithCore Condition="'$(TestWithCore)' == ''">true</TestWithCore>
  </PropertyGroup>

  <PropertyGroup Condition="'$(TestWithCore)' == 'true'">
    <TestRuntimeProjectJson Condition="'$(TestRuntimeProjectJson)' == ''">$(MSBuildThisFileDirectory)test-runtime/project.json</TestRuntimeProjectJson>
    <TestRuntimeProjectLockJson Condition="'$(TestRuntimeProjectLockJson)' == ''">$(MSBuildThisFileDirectory)test-runtime/project.lock.json</TestRuntimeProjectLockJson>
    <!-- Invoke with the correct casing of corerun per-OS.  There are some process tests
         that check the invoked process name against known casing which fail under code coverage.
         This is probably because the code coverage target invocation does not canonicalize the
         process name. -->
    <TestHost Condition="'$(OS)' == 'Windows_NT'">CoreRun.exe</TestHost>
    <TestHost Condition="'$(OS)' != 'Windows_NT'">corerun</TestHost>
    <TestHost>$(TestPath)dnxcore50/$(TestHost)</TestHost>
    <XunitExecutable Condition="'$(XunitExecutable)' == ''">xunit.console.netcore.exe</XunitExecutable>
    <DebugTestFrameworkFolder>dnxcore50</DebugTestFrameworkFolder>
    <DebugEngines>{2E36F1D4-B23C-435D-AB41-18E608940038}</DebugEngines>
  </PropertyGroup>

  <PropertyGroup Condition="'$(TestWithCore)' != 'true'">
    <XunitExecutable Condition="'$(XunitExecutable)' == ''">xunit.console.exe</XunitExecutable>
    <DebugTestFrameworkFolder>dnx45</DebugTestFrameworkFolder>
  </PropertyGroup>

  <ItemGroup Condition="'$(TestWithCore)' == 'true'">
    <TestTargetFramework Include="DNXCore,Version=v5.0">
      <Folder>dnxcore50</Folder>
    </TestTargetFramework>
  </ItemGroup>

  <ItemGroup Condition="'$(TestWithCore)' != 'true'">
    <TestTargetFramework Include=".NETFramework,Version=v4.6.2" Condition="'$(TargetGroup)' == 'net462'">
      <Folder>net462</Folder>
    </TestTargetFramework>
    <TestTargetFramework Include=".NETFramework,Version=v4.6.1" Condition="'$(TargetGroup)' == 'net461'">
      <Folder>net461</Folder>
    </TestTargetFramework>
    <TestTargetFramework Include=".NETFramework,Version=v4.6" Condition="'$(TargetGroup)' == 'net46'">
      <Folder>net46</Folder>
    </TestTargetFramework>
    <TestTargetFramework Include=".NETFramework,Version=v4.5" Condition="'$(TargetGroup)' == 'net45'">
      <Folder>net45</Folder>
    </TestTargetFramework>
  </ItemGroup>

  <!-- General xunit options -->
  <PropertyGroup>
    <XunitResultsFileName>testResults.xml</XunitResultsFileName>
    <XunitOptions>$(XunitOptions) -xml $(XunitResultsFileName)</XunitOptions>

    <XunitOptions Condition="'$(Performance)'!='true'">$(XunitOptions) -notrait Benchmark=true</XunitOptions>

    <XunitOptions Condition="'$(XunitMaxThreads)'!=''">$(XunitOptions) -maxthreads $(XunitMaxThreads)</XunitOptions>
    <XunitArguments>$(TargetFileName) $(XunitOptions)</XunitArguments>

    <TestProgram Condition="'$(TestHost)'!=''">$(TestHost)</TestProgram>
    <TestArguments Condition="'$(TestHost)'!=''">$(XunitExecutable) $(XunitArguments)</TestArguments>

    <TestProgram Condition="'$(TestHost)'==''">$(XunitExecutable)</TestProgram>
    <TestArguments Condition="'$(TestHost)'==''">$(XunitArguments)</TestArguments>

    <TestCommandLine>$(TestProgram) $(TestArguments) {XunitTraitOptions}</TestCommandLine>
  </PropertyGroup>

  <!-- The Code Coverage targets will override TestHost and TestCommandLine if coverage is enabled -->
  <Import Project="$(MSBuildThisFileDirectory)CodeCoverage.targets" />

  <!-- import settings for perf testing -->
  <Import Project="$(MSBuildThisFileDirectory)PerfTesting.targets" />

  <!-- In VS (2015 Preview or later currently required): Debug to run unit tests on CoreCLR. -->
  <PropertyGroup Condition="'$(IsTestProject)'=='true'">
    <StartWorkingDirectory Condition="'$(StartWorkingDirectory)'==''">$(TestPath)$(DebugTestFrameworkFolder)</StartWorkingDirectory>
    <StartAction Condition="'$(StartAction)'==''">Program</StartAction>
    <StartProgram Condition="'$(StartProgram)'==''">$(TestProgram)</StartProgram>
    <StartArguments Condition="'$(StartArguments)'==''">$(TestArguments) -wait</StartArguments>
  </PropertyGroup>

  <Target Name="DiscoverTestInputs" DependsOnTargets="ResolveProjectReferences;ResolveAssemblyReferences;GetCopyToOutputDirectoryItems">
    <ItemGroup>
      <RunTestsForProjectInputs Include="@(ReferenceCopyLocalPaths)" />
      <RunTestsForProjectInputs Include="@(Content)" />
      <RunTestsForProjectInputs Include="@(IntermediateAssembly)" />
      <RunTestsForProjectInputs Include="@(_DebugSymbolsIntermediatePath)" />
      <RunTestsForProjectInputs Include="@(AllItemsFullPathWithTargetPath)" />
    </ItemGroup>
  </Target>

  <!--
    On command line run unit tests on CoreCLR after the Test target.
    Set ForceRunTests to true to run tests even if there have been no changes since the last successful run.
  -->
  <Target Name="RunTestsForProject"
          DependsOnTargets="DiscoverTestInputs"
          AfterTargets="CheckTestCategories"
          Inputs="@(RunTestsForProjectInputs)"
          Outputs="$(TestsSuccessfulSemaphore);$(TestPath)%(TestTargetFramework.Folder)/$(XunitResultsFileName);$(CoverageOutputFilePath)"
          Condition="'$(TestDisabled)'!='true'">

    <ItemGroup>
      <RunWithoutTraits Condition="'$(TargetOS)'=='Windows_NT'" Include="nonwindowstests" />
      <RunWithoutTraits Condition="'$(TargetOS)'=='Linux'" Include="nonlinuxtests" />
      <RunWithoutTraits Condition="'$(TargetOS)'=='OSX'" Include="nonosxtests"/>
      <RunWithoutTraits Condition="'$(TargetOS)'=='FreeBSD'" Include="nonfreebsdtests"/>
      <RunWithoutTraits Condition="'$(TargetOS)'=='NetBSD'" Include="nonnetbsdtests"/>
    </ItemGroup>
    
    <PropertyGroup>
      <XunitTraitOptions Condition="'@(RunWithTraits)'!=''">$(XunitTraitOptions) -trait category=@(RunWithTraits, ' -trait category=') </XunitTraitOptions>
      <XunitTraitOptions Condition="'@(RunWithoutTraits)'!=''">$(XunitTraitOptions) -notrait category=@(RunWithoutTraits, ' -notrait category=') </XunitTraitOptions>
    </PropertyGroup>

    <!-- Replace the {XunitTraitOptions} place holder with the actual traits.  We use the place holder
         because code coverage needs to have a bit of the test command line after the traits (it adds ending quotes
         to one of its options).  Simply appending the traits would break code coverage. -->
    <PropertyGroup>
      <TestCommandLine>$(TestCommandLine.Replace('{XunitTraitOptions}', '$(XunitTraitOptions)'))</TestCommandLine>
    </PropertyGroup>

    <MakeDir Condition="'$(CoverageEnabledForProject)'=='true'" Directories="$(CoverageReportDir)" />

    <Exec Command="$(TestCommandLine)"
          WorkingDirectory="$(TestPath)%(TestTargetFramework.Folder)"
          ContinueOnError="true">
      <Output PropertyName="TestRunExitCode" TaskParameter="ExitCode" />
    </Exec>

    <Delete Condition="'$(DeletePerfDataFile)' == 'true'" Files="$(TestPath)%(TestTargetFramework.Folder)/$(EventTracerDataFile)" />
    <Error Condition="'$(TestRunExitCode)' != '0'" Text="One or more tests failed while running tests from '$(MSBuildProjectName)' please check log for details!" />
    <Touch Condition="'$(TestRunExitCode)' == '0'" Files="$(TestsSuccessfulSemaphore)" AlwaysCreate="true" />
  </Target>

  <!-- Needs to run before RunTestsForProject target as it computes categories and set TestDisabled -->
  <Target Name="CheckTestCategories"
          AfterTargets="CheckTestPlatforms"
          Condition="'$(TestDisabled)'!='true'">

    <!-- Default behavior is to disable OuterLoop and failing tests if not specified in WithCategories. -->
    <ItemGroup>
      <DefaultNoCategories Condition="'$(Outerloop)'!='true'" Include="OuterLoop" />
      <DefaultNoCategories Include="failing" />
      <WithoutCategoriesItems Include="@(DefaultNoCategories)" Exclude="@(WithCategoriesItems)" />
      <WithoutCategoriesItemsDistinct Include="@(WithoutCategoriesItems->Distinct())" />
    </ItemGroup>

    <ItemGroup>
      <RunWithTraits Condition="'@(WithCategoriesItems)'!=''" Include="@(WithCategoriesItems)" />
      <RunWithoutTraits Condition="'@(WithoutCategoriesItemsDistinct)'!=''" Include="@(WithoutCategoriesItemsDistinct)" />
    </ItemGroup>

    <PropertyGroup>
      <TestsSuccessfulSemaphore Condition="'@(RunWithTraits)' != ''">$(TestsSuccessfulSemaphore).with.@(RunWithTraits, '.')</TestsSuccessfulSemaphore>
      <TestsSuccessfulSemaphore Condition="'@(RunWithoutTraits)' != ''">$(TestsSuccessfulSemaphore).without.@(RunWithoutTraits, '.')</TestsSuccessfulSemaphore>
      <TestsSuccessfulSemaphore>$(TestPath)%(TestTargetFramework.Folder)/$(TestsSuccessfulSemaphore)</TestsSuccessfulSemaphore>
    </PropertyGroup>

    <Delete Condition="'$(ForceRunTests)'=='true' And Exists($(TestsSuccessfulSemaphore))"
            Files="$(TestsSuccessfulSemaphore)" />
  </Target>

  <Target Name="CheckTestPlatforms"
          AfterTargets="Test"
          Condition="'$(TestDisabled)'!='true'">
    <GetTargetMachineInfo>
      <Output TaskParameter="TargetOS" PropertyName="TargetOS" />
    </GetTargetMachineInfo>
    <PropertyGroup>
      <TestDisabled Condition="'%(UnsupportedPlatformsItems.Identity)' == '$(TargetOS)'">true</TestDisabled>
    </PropertyGroup>
    <Message Condition="'%(UnsupportedPlatformsItems.Identity)' == '$(TargetOS)'"
      Text="Skipping tests in $(AssemblyName) because it is not supported on $(TargetOS)" />
  </Target>
</Project>
