parameters:
- name: toolset
  type: string
  values:
    - make
- name: uhdSrcDir
  type: string
- name: uhdArtifactSource
  type: string
- name: uhdFpgaArtifactSource
  type: string
- name: fpga_imgs_source
  type: string
- name: redisHost
  type: string
- name: dutMatrix
  type: object
- name: vivado_dir
  type: string
  default: ''
- name: extra_rf_test_args
  type: string
  default: ''

jobs:
- job: build_uhd_run_hardware_test
  displayName: Build uhd and run hardware test
  timeoutInMinutes: 90
  strategy:
    matrix: ${{ parameters.dutMatrix }}
  pool:
    name: 'de-dre-lab'
    demands: uhd_ats -equals $(pipelineAgent)
  variables:
  - group: sdr-pipeline-vars
  workspace:
    clean: outputs

  steps:
  - checkout: ettus-rts
    clean: true

  - checkout: self
    clean: true

  - script: |
      if [ "${{ parameters.uhdArtifactSource }}" = "current" ]; then
        echo '##vso[task.setvariable variable=uhd_artifact_directory]'$(Agent.BuildDirectory)
      else
        echo '##vso[task.setvariable variable=uhd_artifact_directory]'$(Agent.BuildDirectory)/${{ parameters.uhdArtifactSource }}
      fi
    displayName: Set uhddev pipeline artifact location

  - script: |
      if [ "${{ parameters.uhdFpgaArtifactSource }}" = "current" ]; then
        echo '##vso[task.setvariable variable=uhd_fpga_artifact_directory]'$(Agent.BuildDirectory)
        echo "uhd_fpga_artifact_directory=$(Agent.BuildDirectory)"
      else
        echo '##vso[task.setvariable variable=uhd_fpga_artifact_directory]'$(Agent.BuildDirectory)/${{ parameters.uhdFpgaArtifactSource }}
        echo "uhd_fpga_artifact_directory=$(Agent.BuildDirectory)/${{ parameters.uhdFpgaArtifactSource }}"
      fi
    displayName: Set uhddev FPGA pipeline artifact location
    condition: and(succeeded(), contains('${{ parameters.fpga_imgs_source }}', 'Pipeline'))

  #- script: |
      #rm -rf $(uhd_fpga_artifact_directory)
    #displayName: Cleanup from prior run
    #condition: and(succeeded(), contains('${{ parameters.fpga_imgs_source }}', 'Pipeline'))

  - download: ${{ parameters.uhdArtifactSource }}
    artifact: uhddev-$(testOS)-${{ parameters.toolset }}
    displayName: Download uhddev-$(testOS)-${{ parameters.toolset }} artifact

  - task: ExtractFiles@1
    inputs:
      archiveFilePatterns: $(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}/uhddev-$(testOS)-${{ parameters.toolset }}.tar.gz
      destinationFolder: $(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}
      cleanDestinationFolder: false
      overwriteExistingFiles: true
    displayName: Extract uhddev-$(testOS)-${{ parameters.toolset }} artifact

  - download: ${{ parameters.uhdArtifactSource }}
    artifact: gnuradio-grettus-$(testOS)-${{ parameters.toolset }}
    displayName: Download gnuradio-grettus-$(testOS)-${{ parameters.toolset }} artifact

  - task: ExtractFiles@1
    inputs:
      archiveFilePatterns: $(uhd_artifact_directory)/gnuradio-grettus-$(testOS)-${{ parameters.toolset }}/gnuradio-grettus-$(testOS)-${{ parameters.toolset }}.tar.gz
      destinationFolder: $(uhd_artifact_directory)/gnuradio-grettus-$(testOS)-${{ parameters.toolset }}
      cleanDestinationFolder: false
      overwriteExistingFiles: true
    displayName: Extract gnuradio-grettus-$(testOS)-${{ parameters.toolset }} artifact

  - download: ${{ parameters.uhdArtifactSource }}
    artifact: $(devType)-images
    # Only sync the bz2 sdimg since the bmap
    # is incompatible with mender
    patterns: |
      **/*.bz2
      fitImage-manufacturing
    displayName: Download $(devType)-images artifact
    condition: and(succeeded(), eq(variables.devType, 'n3xx'))

  - download: ${{ parameters.uhdFpgaArtifactSource }}
    patterns: |
      usrp_$(devModel)*.bit
      usrp_$(devModel)*.dts
    displayName: Download FPGA artifacts
    condition: and(succeeded(), contains('${{ parameters.fpga_imgs_source }}', 'Pipeline'))

  - script: |
      mkdir -p $(Build.BinariesDirectory)/uhddev/build/fpga_images/
      cd $(uhd_fpga_artifact_directory)
      mv `find . -maxdepth 2 -name "*.bit" -o -name "*.dts"` $(Build.BinariesDirectory)/uhddev/build/fpga_images/
    displayName: Copy FPGA images to expected directory
    condition: and(succeeded(), contains('${{ parameters.fpga_imgs_source }}', 'Pipeline'))


  - script: |
      mkdir -p $(Build.BinariesDirectory)/uhddev/build/fpga_images
      cd $(Build.BinariesDirectory)/uhddev/build
      rm -rf fpga_images/*
      python3 $(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}/uhddev/build/utils/uhd_images_downloader.py -t $(devModel) -i fpga_images \
        -b $(sdr-fileserver)
      if [ "$(devType)" = "b200" ]; then
        python3 $(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}/uhddev/utils/uhd_images_downloader.py -t b2xx_common -i fpga_images \
          -b $(sdr-fileserver)
      fi
    displayName: Download FPGA Images
    condition: and(succeeded(), not(contains('${{ parameters.fpga_imgs_source }}', 'Pipeline')))


  - script: |
        export UHD_INSTALL_PATH=$(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}/uhddev/build-installed
        export PATH=$UHD_INSTALL_PATH/bin:$PATH
        if [ -d "$UHD_INSTALL_PATH/lib64" ]; then
          export LD_LIBRARY_PATH=$UHD_INSTALL_PATH/lib64:$LD_LIBRARY_PATH
        else
          export LD_LIBRARY_PATH=$UHD_INSTALL_PATH/lib:$LD_LIBRARY_PATH
        fi
        CAL_FILE="${HOME}/.local/share/uhd/cal/tx_dc_$(db0Serial).cal"
        if [ ! -f $CAL_FILE ]; then
          echo "$CAL_FILE not found. Running uhd_cal_tx_dc_offset..."
          uhd_cal_tx_dc_offset --args addr=$(devAddr) --subdev A:0
        else
          echo "$CAL_FILE already exists. Skipping calibration."
        fi
        CAL_FILE="${HOME}/.local/share/uhd/cal/tx_iq_$(db0Serial).cal"
        if [ ! -f $CAL_FILE ]; then
          echo "$CAL_FILE not found. Running uhd_cal_tx_iq_balance..."
          uhd_cal_tx_iq_balance --args addr=$(devAddr) --subdev A:0
        else
          echo "$CAL_FILE already exists. Skipping calibration."
        fi
        CAL_FILE="${HOME}/.local/share/uhd/cal/rx_iq_$(db0Serial).cal"
        if [ ! -f $CAL_FILE ]; then
          echo "$CAL_FILE not found. Running uhd_cal_rx_iq_balance..."
          uhd_cal_rx_iq_balance --args addr=$(devAddr) --subdev A:0
        else
          echo "$CAL_FILE already exists. Skipping calibration."
        fi
    displayName: Run corrections utilities for DB0
    condition: and(eq(variables.supportsCorrections, true), ne(variables.db0Serial, ''))

  - script: |
        export UHD_INSTALL_PATH=$(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}/uhddev/build-installed
        export PATH=$UHD_INSTALL_PATH/bin:$PATH
        if [ -d "$UHD_INSTALL_PATH/lib64" ]; then
          export LD_LIBRARY_PATH=$UHD_INSTALL_PATH/lib64:$LD_LIBRARY_PATH
        else
          export LD_LIBRARY_PATH=$UHD_INSTALL_PATH/lib:$LD_LIBRARY_PATH
        fi
        CAL_FILE="${HOME}/.local/share/uhd/cal/tx_dc_$(db1Serial).cal"
        if [ ! -f $CAL_FILE ]; then
          echo "$CAL_FILE not found. Running uhd_cal_tx_dc_offset..."
          uhd_cal_tx_dc_offset --args addr=$(devAddr) --subdev B:0
        else
          echo "$CAL_FILE already exists. Skipping calibration."
        fi
        CAL_FILE="${HOME}/.local/share/uhd/cal/tx_iq_$(db1Serial).cal"
        if [ ! -f $CAL_FILE ]; then
          echo "$CAL_FILE not found. Running uhd_cal_tx_iq_balance..."
          uhd_cal_tx_iq_balance --args addr=$(devAddr) --subdev B:0
        else
          echo "$CAL_FILE already exists. Skipping calibration."
        fi
        CAL_FILE="${HOME}/.local/share/uhd/cal/rx_iq_$(db1Serial).cal"
        if [ ! -f $CAL_FILE ]; then
          echo "$CAL_FILE not found. Running uhd_cal_rx_iq_balance..."
          uhd_cal_rx_iq_balance --args addr=$(devAddr) --subdev B:0
        else
          echo "$CAL_FILE already exists. Skipping calibration."
        fi
    displayName: Run corrections utilities for DB1
    condition: and(eq(variables.supportsCorrections, true), ne(variables.db1Serial, ''))

  - script: |
      mkdir -p $(Common.TestResultsDirectory)/pytest
      cd $(Common.TestResultsDirectory)/pytest

      export UHD_INSTALL_PATH=$(uhd_artifact_directory)/uhddev-$(testOS)-${{ parameters.toolset }}/uhddev/build-installed
      export GNURADIO_GRETTUS_INSTALL_PATH=$(uhd_artifact_directory)/gnuradio-grettus-$(testOS)-${{ parameters.toolset }}/gnuradio/build-installed
      export GNURADIO_GRETTUS_VOLK_INSTALL_PATH=$(uhd_artifact_directory)/gnuradio-grettus-$(testOS)-${{ parameters.toolset }}/volk/build-installed
      export PATH=$UHD_INSTALL_PATH/bin:$PATH
      export PATH=$GNURADIO_GRETTUS_INSTALL_PATH/bin:$PATH
      export PYTHON_VERSION=$(python3 -c "import sys; print('python'+str(sys.version_info.major) + '.' + str(sys.version_info.minor))")
      export UHD_IMAGES_DIR=$(Build.BinariesDirectory)/uhddev/build/fpga_images

      if [ -d "$UHD_INSTALL_PATH/lib64" ]; then
        export PATH=$UHD_INSTALL_PATH/lib64/uhd/examples:$PATH
        export LD_LIBRARY_PATH=$UHD_INSTALL_PATH/lib64:$LD_LIBRARY_PATH
        export LD_LIBRARY_PATH=$GNURADIO_GRETTUS_INSTALL_PATH/lib64:$LD_LIBRARY_PATH
        export LD_LIBRARY_PATH=$GNURADIO_GRETTUS_VOLK_INSTALL_PATH/lib64:$LD_LIBRARY_PATH
        export PYTHONPATH=$UHD_INSTALL_PATH/lib64/$PYTHON_VERSION/site-packages:$PYTHONPATH
        export PYTHONPATH=$GNURADIO_GRETTUS_INSTALL_PATH/lib64/$PYTHON_VERSION/site-packages:$PYTHONPATH
      else
        export PATH=$UHD_INSTALL_PATH/lib/uhd/examples:$PATH
        export LD_LIBRARY_PATH=$UHD_INSTALL_PATH/lib:$LD_LIBRARY_PATH
        export LD_LIBRARY_PATH=$GNURADIO_GRETTUS_INSTALL_PATH/lib:$LD_LIBRARY_PATH
        export LD_LIBRARY_PATH=$GNURADIO_GRETTUS_VOLK_INSTALL_PATH/lib:$LD_LIBRARY_PATH
        export PYTHONPATH=$UHD_INSTALL_PATH/lib/$PYTHON_VERSION/site-packages:$PYTHONPATH
        export PYTHONPATH=$GNURADIO_GRETTUS_INSTALL_PATH/lib/$PYTHON_VERSION/site-packages:$PYTHONPATH
      fi

      source $(Build.SourcesDirectory)/ettus-rts/config/remote/python_tests/setup_venv.sh
      pip3 install -r $(Build.SourcesDirectory)/uhddev/.ci/utils/requirements_312.txt

      if [ "$(devType)" = "n3xx" ]; then
        python3 ${{ parameters.uhdSrcDir }}/.ci/utils/mutex_hardware.py \
          --sdimage_sdmux $(devType),$(devModel),$(uhd_artifact_directory)/$(devType)-images/$(devSDImage),$(Build.SourcesDirectory)/ettus-rts/$(devLabgridConfig),$(devHostname) \
          --fpgas $(devFpga) \
          --sfp_addrs $(sfpAddrs) \
          --working_dir "$(Build.SourcesDirectory)/ettus-rts/config/remote/python_tests/pytests/" \
          "${{ parameters.redisHost }}" "$(devName)" \
          "uhd_usrp_probe --args addr=$(devAddr)" \
          "python3 ../automated_main.py --ats_config $(pytestAtsConfig) --dut $(pytestDUT) \
            --results_path $(Common.TestResultsDirectory)/pytest/{fpga} ${{ parameters.extra_rf_test_args }}"
      elif [ "$(devType)" = "x300" ]; then
        cd $(Build.SourcesDirectory)/ettus-rts/config/remote/python_tests
        python3 ${{ parameters.uhdSrcDir }}/.ci/utils/mutex_hardware.py \
          --jtag_x3xx $(devType),$(devModel),$(jtagServer),$(jtagSerial),$(Build.BinariesDirectory)/uhddev/build/fpga_images/,${{ parameters.vivado_dir }} \
          --fpgas $(devFpga) \
          --sfp_addrs $(sfpAddrs) \
          --working_dir "$(Build.SourcesDirectory)/ettus-rts/config/remote/python_tests/pytests/" \
          "${{ parameters.redisHost }}" "$(devName)" \
          "uhd_usrp_probe --args addr=$(devAddr)" \
          "python3 ../automated_main.py --ats_config $(pytestAtsConfig) --dut $(pytestDUT) \
            --results_path $(Common.TestResultsDirectory)/pytest/{fpga} ${{ parameters.extra_rf_test_args }}"
      fi
    continueOnError: true
    condition: succeeded()
    displayName: Run pytests on $(devName)

  - script: |
      cd $(Common.TestResultsDirectory)/devtest
      python3 ${{ parameters.uhdSrcDir }}/.ci/utils/format_devtest_junitxml.py \
        --fpgas $(devFpga) \
        $(Common.TestResultsDirectory)/pytest \
        $(Common.TestResultsDirectory)/pytest/pytestresults.xml
    continueOnError: true
    displayName: Format devtest xml
    condition: always()

  - task: PublishTestResults@2
    inputs:
      testResultsFormat: 'JUnit'
      testResultsFiles: '$(Common.TestResultsDirectory)/pytest/pytestresults.xml'
      testRunTitle: $(devName) pytest
      buildConfiguration: 'Release'
      mergeTestResults: true
    condition: always()
    displayName: Upload pytest results

  - script: |
      echo "A previous step failed. See steps with warnings."
      echo "Marking the overall build status as a failure."
      exit 1
    condition: in(variables['Agent.JobStatus'],  'SucceededWithIssues')
    displayName: Mark build as failure
