parameters:
  - name: VSCODE_QUALITY
    type: string
  - name: VSCODE_RUN_UNIT_TESTS
    type: boolean
  - name: VSCODE_RUN_INTEGRATION_TESTS
    type: boolean
  - name: VSCODE_RUN_SMOKE_TESTS
    type: boolean

steps:
  - script: |
      set -e
      VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \
        yarn npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install"
    displayName: Download Electron and Playwright

  - ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
    - script: |
        set -e
        sudo apt-get update
        sudo apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 libgbm1
        sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb
        sudo chmod +x /etc/init.d/xvfb
        sudo update-rc.d xvfb defaults
        sudo service xvfb start
      displayName: Setup build environment

  - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
    - script: |
        set -e
        APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
        ELECTRON_ROOT=.build/electron
        sudo chown root $APP_ROOT/chrome-sandbox
        sudo chown root $ELECTRON_ROOT/chrome-sandbox
        sudo chmod 4755 $APP_ROOT/chrome-sandbox
        sudo chmod 4755 $ELECTRON_ROOT/chrome-sandbox
        stat $APP_ROOT/chrome-sandbox
        stat $ELECTRON_ROOT/chrome-sandbox
      displayName: Change setuid helper binary permission

  - ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
    - ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
      - script: |
          set -e
          DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests"
        displayName: Run unit tests (Electron)
        timeoutInMinutes: 15

      - script: |
          set -e
          yarn test-node
        displayName: Run unit tests (node.js)
        timeoutInMinutes: 15

      - script: |
          set -e
          DEBUG=*browser* yarn test-browser-no-install --browser chromium --tfs "Browser Unit Tests"
        displayName: Run unit tests (Browser, Chromium)
        timeoutInMinutes: 15

    - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
      - script: |
          set -e
          ./scripts/test.sh --build --tfs "Unit Tests"
        displayName: Run unit tests (Electron)
        timeoutInMinutes: 15

      - script: |
          set -e
          yarn test-node --build
        displayName: Run unit tests (node.js)
        timeoutInMinutes: 15

      - script: |
          set -e
          DEBUG=*browser* yarn test-browser-no-install --build --browser chromium --tfs "Browser Unit Tests"
        displayName: Run unit tests (Browser, Chromium)
        timeoutInMinutes: 15

  - ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
    - script: |
        set -e
        yarn gulp \
          compile-extension:configuration-editing \
          compile-extension:css-language-features-server \
          compile-extension:emmet \
          compile-extension:git \
          compile-extension:github-authentication \
          compile-extension:html-language-features-server \
          compile-extension:ipynb \
          compile-extension:json-language-features-server \
          compile-extension:markdown-language-features-server \
          compile-extension:markdown-language-features \
          compile-extension-media \
          compile-extension:microsoft-authentication \
          compile-extension:typescript-language-features \
          compile-extension:vscode-api-tests \
          compile-extension:vscode-colorize-tests \
          compile-extension:vscode-test-resolver
      displayName: Build integration tests

  - ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
    - ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
      - script: |
          set -e
          DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests"
        displayName: Run integration tests (Electron)
        timeoutInMinutes: 20

      - script: |
          set -e
          ./scripts/test-web-integration.sh --browser chromium
        displayName: Run integration tests (Browser, Chromium)
        timeoutInMinutes: 20

      - script: |
          set -e
          ./scripts/test-remote-integration.sh
        displayName: Run integration tests (Remote)
        timeoutInMinutes: 20

    - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
      - script: |
          # Figure out the full absolute path of the product we just built
          # including the remote server and configure the integration tests
          # to run with these builds instead of running out of sources.
          set -e
          APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
          APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName")
          INTEGRATION_TEST_APP_NAME="$APP_NAME" \
          INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \
          VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \
          ./scripts/test-integration.sh --build --tfs "Integration Tests"
        displayName: Run integration tests (Electron)
        timeoutInMinutes: 20

      - script: |
          set -e
          VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \
          ./scripts/test-web-integration.sh --browser chromium
        displayName: Run integration tests (Browser, Chromium)
        timeoutInMinutes: 20

      - script: |
          set -e
          APP_ROOT=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
          APP_NAME=$(node -p "require(\"$APP_ROOT/resources/app/product.json\").applicationName")
          INTEGRATION_TEST_APP_NAME="$APP_NAME" \
          INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME" \
          VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \
          ./scripts/test-remote-integration.sh
        displayName: Run integration tests (Remote)
        timeoutInMinutes: 20

  - ${{ if eq(parameters.VSCODE_RUN_SMOKE_TESTS, true) }}:
    - script: |
        set -e
        ps -ef
        cat /proc/sys/fs/inotify/max_user_watches
        lsof | wc -l
      displayName: Diagnostics before smoke test run (processes, max_user_watches, number of opened file handles)
      continueOnError: true
      condition: succeededOrFailed()

    - ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
      - script: |
          set -e
          yarn --cwd test/smoke compile
        displayName: Compile smoke tests

      - script: |
          set -e
          yarn gulp \
            compile-extension:markdown-language-features \
            compile-extension-media
        displayName: Build extensions for smoke tests

      - script: |
          set -e
          yarn smoketest-no-compile --tracing
        timeoutInMinutes: 20
        displayName: Run smoke tests (Electron)

      - script: |
          set -e
          yarn smoketest-no-compile --web --tracing --headless --electronArgs="--disable-dev-shm-usage"
        timeoutInMinutes: 20
        displayName: Run smoke tests (Browser, Chromium)

      - script: |
          set -e
          yarn gulp compile-extension:vscode-test-resolver
          yarn smoketest-no-compile --remote --tracing
        timeoutInMinutes: 20
        displayName: Run smoke tests (Remote)

    - ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
      - script: |
          set -e
          APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
          yarn smoketest-no-compile --tracing --build "$APP_PATH"
        timeoutInMinutes: 20
        displayName: Run smoke tests (Electron)

      - script: |
          set -e
          VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-web-linux-$(VSCODE_ARCH)" \
          yarn smoketest-no-compile --web --tracing --headless --electronArgs="--disable-dev-shm-usage"
        timeoutInMinutes: 20
        displayName: Run smoke tests (Browser, Chromium)

      - script: |
          set -e
          yarn gulp compile-extension:vscode-test-resolver
          APP_PATH=$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)
          VSCODE_REMOTE_SERVER_PATH="$(agent.builddirectory)/vscode-reh-linux-$(VSCODE_ARCH)" \
          yarn smoketest-no-compile --tracing --remote --build "$APP_PATH"
        timeoutInMinutes: 20
        displayName: Run smoke tests (Remote)

    - script: |
        set -e
        ps -ef
        cat /proc/sys/fs/inotify/max_user_watches
        lsof | wc -l
      displayName: Diagnostics after smoke test run (processes, max_user_watches, number of opened file handles)
      continueOnError: true
      condition: succeededOrFailed()

  - ${{ if or(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
    - task: PublishPipelineArtifact@0
      inputs:
        targetPath: .build/crashes
        ${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
          artifactName: crash-dump-linux-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
        ${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
          artifactName: crash-dump-linux-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
        ${{ else }}:
          artifactName: crash-dump-linux-$(VSCODE_ARCH)-$(System.JobAttempt)
      displayName: "Publish Crash Reports"
      continueOnError: true
      condition: failed()

    # In order to properly symbolify above crash reports
    # (if any), we need the compiled native modules too
    - task: PublishPipelineArtifact@0
      inputs:
        targetPath: node_modules
        ${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
          artifactName: node-modules-linux-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
        ${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
          artifactName: node-modules-linux-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
        ${{ else }}:
          artifactName: node-modules-linux-$(VSCODE_ARCH)-$(System.JobAttempt)
      displayName: "Publish Node Modules"
      continueOnError: true
      condition: failed()

    - task: PublishPipelineArtifact@0
      inputs:
        targetPath: .build/logs
        ${{ if and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true), eq(parameters.VSCODE_RUN_SMOKE_TESTS, false)) }}:
          artifactName: logs-linux-$(VSCODE_ARCH)-integration-$(System.JobAttempt)
        ${{ elseif and(eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, false), eq(parameters.VSCODE_RUN_SMOKE_TESTS, true)) }}:
          artifactName: logs-linux-$(VSCODE_ARCH)-smoke-$(System.JobAttempt)
        ${{ else }}:
          artifactName: logs-linux-$(VSCODE_ARCH)-$(System.JobAttempt)
      displayName: "Publish Log Files"
      continueOnError: true
      condition: succeededOrFailed()

  - task: PublishTestResults@2
    displayName: Publish Tests Results
    inputs:
      testResultsFiles: "*-results.xml"
      searchFolder: "$(Build.ArtifactStagingDirectory)/test-results"
    condition: succeededOrFailed()
