trigger:
- main

pr:
- main

variables:
  # Turn this Powershell console into a developer powershell console.
  # https://intellitect.com/enter-vsdevshell-powershell/
  PWSH_DEV: |
    if ($env:Agent_OS -eq 'Windows_NT') {
      $installPath = &"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationpath
      $devShell    = &"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -find **\Microsoft.VisualStudio.DevShell.dll
      Import-Module $devShell
      Enter-VsDevShell -VsInstallPath $installPath -SkipAutomaticLocation -DevCmdArguments "-arch=amd64"
    }
  RAKUDO_CHECKOUT_TYPE: main
  NQP_CHECKOUT_TYPE: main
  MOAR_CHECKOUT_TYPE: "rev-$(Build.SourceVersion)-selfrepo"
  INSTALL_DIR: install

stages:
- stage: Test
  jobs:
    # Keep the job and matrix entry names as short as possible as the webinterface
    # leaves little space for the name.
    - job: T
      strategy:
       matrix:
         Win_MVM:
           IMAGE_NAME: 'windows-2019'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: ''
         Win_MVM_reloc:
           IMAGE_NAME: 'windows-2019'
           RELOCATABLE: 'yes'
           RAKUDO_OPTIONS: '--relocatable'
           NQP_OPTIONS: '--backends=moar --relocatable'
           MOAR_OPTIONS: '--relocatable'

         Mac_MVM:
           IMAGE_NAME: 'macOS-13'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: ''
         Mac_MVM_reloc:
           IMAGE_NAME: 'macOS-13'
           RELOCATABLE: 'yes'
           RAKUDO_OPTIONS: '--relocatable'
           NQP_OPTIONS: '--backends=moar --relocatable'
           MOAR_OPTIONS: '--relocatable'
         Mac_MVM_no_C11_atomics:
           IMAGE_NAME: 'macOS-13'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--no-c11-atomics'
         Mac_12_MVM:
           IMAGE_NAME: 'macOS-12'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: ''

         Lin_MVM:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--debug=3'
           CHECK_LEAKS: 'yes'
         Lin_MVM_reloc:
           IMAGE_NAME: 'ubuntu-22.04'
           RELOCATABLE: 'yes'
           RAKUDO_OPTIONS: '--relocatable'
           NQP_OPTIONS: '--backends=moar --relocatable'
           MOAR_OPTIONS: '--relocatable --debug=3'
           CHECK_LEAKS: 'yes'

         MVM_gcc_njit:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--no-jit --cc=gcc --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_gcc:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=gcc --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_clang_njit:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--no-jit --cc=clang --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_clang:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=clang --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_gcc_njit_libffi:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--has-libffi --no-jit --cc=gcc --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_gcc_libffi:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--has-libffi --cc=gcc --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_clang_njit_libffi:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--has-libffi --no-jit --cc=clang --debug=3'
           CHECK_LEAKS: 'yes'
         MVM_clang_libffi:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--has-libffi --cc=clang --debug=3'
           CHECK_LEAKS: 'yes'
#         MVM_gcc_mingw:
#           IMAGE_NAME: 'windows-2019'
#           RAKUDO_OPTIONS: ''
#           NQP_OPTIONS: '--backends=moar'
#           MOAR_OPTIONS: '--os=mingw32'
#         MVM_coverage:
#           IMAGE_NAME: 'ubuntu-22.04'
#           RAKUDO_OPTIONS: ''
#           NQP_OPTIONS: '--backends=moar'
#           MOAR_OPTIONS: '--compiler=clang --coverage --optimize=0 --debug=3 --cc=clang'
#           COVERAGE: 'yes'

         MVM_gcc_malloc:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=gcc --debug=3 --no-mimalloc'
           CHECK_LEAKS: 'yes'
         MVM_clang_malloc:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=clang --debug=3 --no-mimalloc'
           CHECK_LEAKS: 'yes'
         MVM_gcc_no_c11_atomics:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=gcc --debug=3 --no-c11-atomics'
           CHECK_LEAKS: 'yes'
         MVM_clang_no_c11_atomics:
           IMAGE_NAME: 'ubuntu-22.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=clang --debug=3 --no-c11-atomics'
           CHECK_LEAKS: 'yes'

         # Backwards compatability jobs, using the oldest OS version that GH actions support
         MVM_Ub_20_gcc:
           IMAGE_NAME: 'ubuntu-20.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=gcc --debug=3'
         MVM_Ub_20_clang:
           IMAGE_NAME: 'ubuntu-20.04'
           RAKUDO_OPTIONS: ''
           NQP_OPTIONS: '--backends=moar'
           MOAR_OPTIONS: '--cc=clang --debug=3'

      pool:
        vmImage: $(IMAGE_NAME)
      workspace:
        clean: all
      timeoutInMinutes: 180
      steps:

        - pwsh: |
            # Windows has a maximum PATH variable length of 2048 (depending on
            # how it's accessed). The length of PATH in AzureCI is already
            # really tight. We'll run into the limit when we add Java and the
            # MS BuildTools to the path.
            # To work around this, we remove a bunch of stuff we won't need
            # from PATH here.
            $shortened_path = "$(PATH)" -replace ';[^;]*(SeleniumWebDrivers|SQL Server|Mercurial|Amazon|mysql|\\sbt\\|NSIS|Windows Performance Toolkit|php|Subversion)[^;]*(?=(;|$))', ''
            echo "##vso[task.setvariable variable=PATH]$shortened_path"
          displayName: "Shorten PATH on Windows"
          condition: eq( variables['Agent.OS'], 'Windows_NT' )

        - script: |
            sudo apt-get update
            sudo apt-get install libzstd-dev valgrind
            # The loop with libc-bin and glibc-tools are because catchsegv moved packages with Ubuntu 20.04 and again with 22.04
            for pkg in libc-bin glibc-tools
            do
              sudo apt-get install -qy $pkg || true
            done
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Linux' ))
          displayName: Install libzstd-dev and valgrind

        - checkout: self
          path: selfrepo
          displayName: Checkout script repo

        - script: perl selfrepo/tools/build/checkout-repos-for-test.pl $(RAKUDO_CHECKOUT_TYPE) $(NQP_CHECKOUT_TYPE) $(MOAR_CHECKOUT_TYPE)
          workingDirectory: $(Pipeline.Workspace)
          displayName: Checkout repositories

        # Build MoarVM
        - script: |
            perl Configure.pl --prefix=../$(INSTALL_DIR) $(MOAR_OPTIONS)
            make -j2 install
          workingDirectory: '$(Pipeline.Workspace)/MoarVM'
          condition: and(succeeded(), ne( variables['Agent.OS'], 'Windows_NT' ))
          displayName: Build MoarVM
        - pwsh: |
            ${{ variables.PWSH_DEV }}
            perl Configure.pl --prefix=..\$(INSTALL_DIR) $(MOAR_OPTIONS)
            gmake -j2 install
          failOnStderr: false
          workingDirectory: '$(Pipeline.Workspace)/MoarVM'
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Windows_NT' ), contains( variables['MOAR_OPTIONS'], 'mingw32' ))
          displayName: Build MoarVM (Windows, MinGW)
        - pwsh: |
            ${{ variables.PWSH_DEV }}
            perl Configure.pl --prefix=..\$(INSTALL_DIR) $(MOAR_OPTIONS)
            set CL=/MP
            nmake install
          failOnStderr: false
          workingDirectory: '$(Pipeline.Workspace)/MoarVM'
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Windows_NT' ), not(contains( variables['MOAR_OPTIONS'], 'mingw32' )))
          displayName: Build MoarVM (Windows, MSVC)

        # Build NQP
        - pwsh: |
            ${{ variables.PWSH_DEV }}
            perl Configure.pl --prefix=../$(INSTALL_DIR) $(NQP_OPTIONS) --make-install
          workingDirectory: '$(Pipeline.Workspace)/nqp'
          condition: and(succeeded(), ne( variables['Agent.OS'], 'Linux' ) )
          displayName: Build NQP
        - script: |
            export SEGFAULT_SIGNALS="all"
            catchsegv perl Configure.pl --prefix=../$(INSTALL_DIR) $(NQP_OPTIONS) --make-install
          workingDirectory: '$(Pipeline.Workspace)/nqp'
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Linux' ) )
          displayName: Build NQP (Linux)

        # Build Rakudo
        - pwsh: |
            ${{ variables.PWSH_DEV }}
            perl Configure.pl --prefix=../$(INSTALL_DIR) $(RAKUDO_OPTIONS) --make-install
          workingDirectory: '$(Pipeline.Workspace)/rakudo'
          condition: and(succeeded(), ne( variables['Agent.OS'], 'Linux' ) )
          displayName: Build Rakudo
        - script: |
            export SEGFAULT_SIGNALS="all"
            catchsegv perl Configure.pl --prefix=../$(INSTALL_DIR) $(RAKUDO_OPTIONS) --make-install
          workingDirectory: '$(Pipeline.Workspace)/rakudo'
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Linux' ) )
          displayName: Build Rakudo (Linux)

        # TODO: Should use "install moved" instead of "install-moved". But `prove` currently fails with an executable path that contains a space.
        - pwsh: |
            mv $(INSTALL_DIR) $(INSTALL_DIR)-moved
            echo "##vso[task.setvariable variable=INSTALL_DIR]$(INSTALL_DIR)-moved"
          workingDirectory: $(Pipeline.Workspace)
          condition: and(succeeded(), eq( variables['RELOCATABLE'], 'yes' ) )
          displayName: Move installation

        # Test NQP
        - script: prove -j2 -r -e ../$(INSTALL_DIR)/bin/nqp t/nqp t/hll t/qregex t/p5regex t/qast t/moar t/serialization t/nativecall t/concurrency
          workingDirectory: '$(Pipeline.Workspace)/nqp'
          condition: and(succeeded(), ne( variables['Agent.OS'], 'Linux' ) )
          displayName: Test NQP
        - script: |
            export SEGFAULT_SIGNALS="all"
            catchsegv prove -j2 -r -e ../$(INSTALL_DIR)/bin/nqp t/nqp t/hll t/qregex t/p5regex t/qast t/moar t/serialization t/nativecall t/concurrency
          workingDirectory: '$(Pipeline.Workspace)/nqp'
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Linux' ) )
          displayName: Test NQP (Linux)

        # Test Rakudo
        - pwsh: |
            ${{ variables.PWSH_DEV }}
            $install_path = Resolve-Path ../$(INSTALL_DIR)/bin/
            prove -j2 -e "$($install_path.Path)raku" -vlr t
          workingDirectory: '$(Pipeline.Workspace)/rakudo'
          condition: and(succeeded(), ne( variables['Agent.OS'], 'Linux' ) )
          displayName: Test Rakudo
        - script: |
            export SEGFAULT_SIGNALS="all"
            catchsegv prove -j2 -e ../$(INSTALL_DIR)/bin/raku -vlr t
          workingDirectory: '$(Pipeline.Workspace)/rakudo'
          condition: and(succeeded(), eq( variables['Agent.OS'], 'Linux' ) )
          displayName: Test Rakudo (Linux)

        - publish: $(Pipeline.Workspace)/$(INSTALL_DIR)
          condition: and(succeeded(), eq( variables['RELOCATABLE'], 'yes' ))
          displayName: Publish build artifact

#        - script: |
#            git clone --depth 1 'https://github.com/samcv/MoarVM-cover.git' &&
#            cp -v MoarVM-cover/html-cover.sh . &&
#            cp -v MoarVM-cover/nqp-profile ../nqp/ &&
#            cp -v MoarVM-cover/merge-profraw.sh ../nqp/ &&
#            ./html-cover.sh 2
#          condition: and(succeeded(), eq( variables['COVERAGE'], 'yes' ))
#          displayName: Create coverage report

        - script: |
            valgrind --leak-check=full ../$(INSTALL_DIR)/bin/raku --full-cleanup -e '' 2>valgrind.log
            cat valgrind.log
            grep 'in use at exit: 0 bytes in 0 blocks' valgrind.log
          condition: and(succeeded(), eq( variables['CHECK_LEAKS'], 'yes' ), ne( variables['COVERAGE'], 'yes' ), eq( variables['Agent.OS'], 'Linux' ))
          displayName: Check for memory leaks
