name: Tests

on:
  push:
    branches:
      - master
  pull_request_target:
    types: [opened, synchronize, reopened]

jobs:
  test-all:
    name: Test PHP ${{ matrix.php-version }} using broker [${{ matrix.mqtt-broker }}]

    runs-on: ubuntu-latest

    strategy:
      matrix:
        php-version: ['7.4', '8.0', '8.1']
        mqtt-broker: ['mosquitto-1.6', 'mosquitto-2.0', 'hivemq', 'emqx', 'rabbitmq']
        include:
          - php-version: '8.1'
            mqtt-broker: 'mosquitto-2.0'
            run-sonarqube-analysis: true

    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Setup Java 11 (for keytool)
        uses: actions/setup-java@v3
        with:
          distribution: 'zulu'
          java-version: '11'
          java-package: 'jre'

      - name: Setup PHP ${{ matrix.php-version }}
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-version }}
          tools: phpunit:9.5.0
          coverage: pcov

      - name: Setup problem matchers for PHP
        run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"

      - name: Setup problem matchers for PHPUnit
        run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

      - name: Get Composer Cache Directory
        id: composer-cache
        run: |
          echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

      - name: Cache Composer dependencies
        uses: actions/cache@v3
        with:
          path: ${{ steps.composer-cache.outputs.dir }}
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: ${{ runner.os }}-composer-

      - name: Install Composer dependencies
        run: composer install --prefer-dist

      - name: Generate certificates for tests
        run: |
          sh create-certificates.sh
          chmod u+rx,g+rx ${{ github.workspace }}/.ci/tls
          chmod a+r ${{ github.workspace }}/.ci/tls/*

      - name: Start Mosquitto 1.6 message broker
        if: matrix.mqtt-broker == 'mosquitto-1.6'
        uses: Namoshek/mosquitto-github-action@v1
        with:
          version: '1.6'
          ports: '1883:1883 1884:1884 8883:8883 8884:8884'
          certificates: ${{ github.workspace }}/.ci/tls
          config: ${{ github.workspace }}/.ci/mosquitto.conf
          password-file: ${{ github.workspace}}/.ci/mosquitto.passwd

      - name: Start Mosquitto 2.0 message broker
        if: matrix.mqtt-broker == 'mosquitto-2.0'
        uses: Namoshek/mosquitto-github-action@v1
        with:
          version: '2.0'
          ports: '1883:1883 1884:1884 8883:8883 8884:8884'
          certificates: ${{ github.workspace }}/.ci/tls
          config: ${{ github.workspace }}/.ci/mosquitto.conf
          password-file: ${{ github.workspace}}/.ci/mosquitto.passwd

      - name: Start HiveMQ message broker
        if: matrix.mqtt-broker == 'hivemq'
        uses: Namoshek/hivemq4-github-action@v1
        with:
          version: '4.8.5'
          ports: '1883:1883 8883:8883 8884:8884'
          certificates: ${{ github.workspace }}/.ci/tls
          config: ${{ github.workspace }}/.ci/hivemq.xml

      - name: Start EMQ X message broker
        if: matrix.mqtt-broker == 'emqx'
        uses: Namoshek/emqx-github-action@v1.0.2
        with:
          version: '4.4.3'
          ports: '1883:1883'
          config: ${{ github.workspace }}/.ci/emqx.conf

      - name: Start RabbitMQ message broker
        if: matrix.mqtt-broker == 'rabbitmq'
        uses: namoshek/rabbitmq-github-action@v1.1.0
        with:
          version: '3.8.9'
          ports: '1883:1883'
          config: ${{ github.workspace }}/.ci/rabbitmq.conf
          plugins: 'rabbitmq_mqtt'

      - name: Wait a bit until MQTT broker has started
        run: sleep 45

      - name: Run phpunit tests
        run: composer test
        env:
          MQTT_BROKER_HOST: 'localhost'
          MQTT_BROKER_PORT: 1883
          MQTT_BROKER_PORT_WITH_AUTHENTICATION: ${{ (matrix.mqtt-broker == 'mosquitto-1.6' || matrix.mqtt-broker == 'mosquitto-2.0') && 1884 || 1883 }}
          MQTT_BROKER_TLS_PORT: 8883
          MQTT_BROKER_TLS_WITH_CLIENT_CERT_PORT: 8884
          MQTT_BROKER_USERNAME: ${{ (matrix.mqtt-broker == 'mosquitto-1.6' || matrix.mqtt-broker == 'mosquitto-2.0') && 'ci-test-user' || '' }}
          MQTT_BROKER_PASSWORD: ${{ (matrix.mqtt-broker == 'mosquitto-1.6' || matrix.mqtt-broker == 'mosquitto-2.0') && secrets.CI_MOSQUITTO_CI_TEST_USER_PASSWORD || '' }}
          SKIP_TLS_TESTS: ${{ matrix.mqtt-broker == 'emqx' || matrix.mqtt-broker == 'rabbitmq' }}

      - name: Dump Docker logs on failure
        if: failure()
        uses: jwalton/gh-docker-logs@v2

      - name: Prepare paths for SonarQube analysis
        if: matrix.run-sonarqube-analysis
        run: |
          sed -i "s|$GITHUB_WORKSPACE|/github/workspace|g" phpunit.coverage-clover.xml
          sed -i "s|$GITHUB_WORKSPACE|/github/workspace|g" phpunit.report-junit.xml

      - name: Run SonarQube analysis
        uses: sonarsource/sonarcloud-github-action@v1.9
        if: matrix.run-sonarqube-analysis
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
