--- /dev/null
+ARG BUILDER_IMAGE=signalwire/freeswitch-public-ci-base:bookworm-amd64
+
+FROM ${BUILDER_IMAGE}
+
+ARG MAINTAINER_EMAIL="andrey@signalwire.com"
+
+LABEL org.opencontainers.image.authors="${MAINTAINER_EMAIL}"
+
+SHELL ["/bin/bash", "-c"]
+
+COPY --from=sofia-sip / /usr/src/sofia-sip
+COPY --from=freeswitch / /usr/src/freeswitch
+
+RUN cd /usr/src/freeswitch && \
+ ./ci.sh -t unit-test -a configure -c sofia-sip -p "/usr/src/sofia-sip" && \
+ ./ci.sh -t unit-test -a build -c sofia-sip -p "/usr/src/sofia-sip" && \
+ ./ci.sh -t unit-test -a install -c sofia-sip -p "/usr/src/sofia-sip" && \
+ ./ci.sh -t unit-test -a configure -c freeswitch -p "/usr/src/freeswitch" && \
+ ./ci.sh -t unit-test -a build -c freeswitch -p "/usr/src/freeswitch" && \
+ ./ci.sh -t unit-test -a install -c freeswitch -p "/usr/src/freeswitch"
+
+WORKDIR /usr/src/freeswitch/tests/unit
+
+ENTRYPOINT ["/usr/src/freeswitch/tests/unit/run-tests.sh"]
push:
branches:
- master
+ - v1.10
pull_request:
types:
- opened
- synchronize
+ workflow_dispatch:
+ inputs:
+ freeswitch_ref:
+ description: 'FreeSWITCH repository ref'
+ required: false
+ type: string
+ sofia-sip_ref:
+ description: 'Sofia-Sip repository ref'
+ required: false
+ type: string
+ dind:
+ description: 'Run tests using Docker-in-Docker'
+ required: false
+ type: boolean
+ default: false
+
+env:
+ CI_BASE_STATIC_IMAGE: signalwire/freeswitch-public-ci-base:bookworm-amd64
+ DOCKER_BUILD_SUMMARY: false
+ DOCKER_BUILD_CHECKS_ANNOTATIONS: false
+ DOCKER_BUILD_RECORD_UPLOAD: false
jobs:
unit-tests-pre-config:
+ if: ${{ !inputs.dind }}
+ name: "Unit-tests pre-config"
runs-on: ubuntu-latest
env:
TOTAL_GROUPS: 2
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
+ container-image: ${{ steps.set-vars.outputs.container-image }}
+ working-directory: ${{ steps.set-vars.outputs.working-directory }}
+ tests-only: ${{ steps.set-vars.outputs.tests-only }}
steps:
- id: set-matrix
shell: bash
include: [range(1; $groups + 1) | {group: ., total: $groups}]
}')
echo "matrix=$MATRIX" | tee -a $GITHUB_OUTPUT
+ - id: set-vars
+ shell: bash
+ run: |
+ echo "tests-only=false" >> $GITHUB_OUTPUT
+ echo "working-directory=freeswitch/tests/unit" >> $GITHUB_OUTPUT
+ echo "container-image=$CI_BASE_STATIC_IMAGE" >> $GITHUB_OUTPUT
unit-tests:
- needs: unit-tests-pre-config
+ if: ${{ !inputs.dind }}
+ name: "Unit-tests (group ${{ matrix.group }})"
+ needs:
+ - unit-tests-pre-config
strategy:
+ fail-fast: false
matrix: ${{ fromJson(needs.unit-tests-pre-config.outputs.matrix) }}
- name: "unit-tests (group ${{ matrix.group }})"
uses: ./.github/workflows/unit-test.yml
with:
total-groups: ${{ matrix.total }}
current-group: ${{ matrix.group }}
+ container-image: ${{ needs.unit-tests-pre-config.outputs.container-image }}
+ working-directory: ${{ needs.unit-tests-pre-config.outputs.working-directory }}
+ tests-only: ${{ fromJson(needs.unit-tests-pre-config.outputs.tests-only) }}
secrets: inherit
- scan-build:
+ validate-unit-tests:
+ if: ${{ always() && !inputs.dind }}
+ name: "Validate Unit-tests"
+ needs: unit-tests
runs-on: ubuntu-latest
- container:
- image: signalwire/freeswitch-public-base:bookworm
- credentials:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- options: --privileged
- env:
- REPOTOKEN: ${{ secrets.REPOTOKEN }}
- DEBIAN_FRONTEND: noninteractive
-
steps:
- - name: Install dependencies
- shell: bash
+ - name: Check unit tests status
run: |
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf && \
- apt-get update && \
- apt-get -y remove \
- libsofia-sip-ua0 \
- libspandsp-dev && \
- apt-get -y install \
- autoconf \
- libsofia-sip-ua-dev \
- libspandsp3-dev && \
- rm -rf /etc/apt/auth.conf
-
- - name: Checkout code
- uses: actions/checkout@v4
- with:
- path: /__w/freeswitch/freeswitch
+ if [ "${{ needs.unit-tests.result }}" != "success" ]; then
+ exit 1
+ fi
- - name: Bootstrap
- shell: bash
- working-directory: /__w/freeswitch/freeswitch
- run: |
- ./bootstrap.sh -j || exit 1
+ unit-tests-dind:
+ if: ${{ inputs.dind }}
+ name: "Unit-tests D-in-D"
+ uses: ./.github/workflows/unit-test-dind.yml
+ with:
+ freeswitch_ref: ${{ inputs.freeswitch_ref }}
+ sofia-sip_ref: ${{ inputs.sofia-sip_ref }}
+ secrets: inherit
- - name: Scan-build FreeSwitch
- shell: bash
- working-directory: /__w/freeswitch/freeswitch
- run: |
- cp build/modules.conf.most modules.conf && \
- echo 'codecs/mod_openh264' >> modules.conf && \
- sed -i \
- -e '/mod_mariadb/s/^#//g' \
- -e '/mod_v8/s/^#//g' \
- -e '/mod_ilbc/s/^/#/g' \
- -e '/mod_isac/s/^/#/g' \
- -e '/mod_mp4/s/^/#/g' \
- -e '/mod_mongo/s/^/#/g' \
- -e '/mod_pocketsphinx/s/^/#/g' \
- -e '/mod_sangoma_codec/s/^/#/g' \
- -e '/mod_siren/s/^/#/g' \
- -e '/mod_avmd/s/^/#/g' \
- -e '/mod_basic/s/^/#/g' \
- -e '/mod_cdr_mongodb/s/^/#/g' \
- -e '/mod_cv/s/^/#/g' \
- -e '/mod_erlang_event/s/^/#/g' \
- -e '/mod_perl/s/^/#/g' \
- -e '/mod_rtmp/s/^/#/g' \
- -e '/mod_unimrcp/s/^/#/g' \
- -e '/mod_xml_rpc/s/^/#/g' \
- modules.conf && \
- ./configure && \
- ./scan_build.sh
+ scan-build:
+ name: "Scan Build"
+ uses: ./.github/workflows/scan-build.yml
+ secrets: inherit
--- /dev/null
+name: Scan build (Static Analysis)
+
+on:
+ workflow_call:
+ inputs:
+ freeswitch_ref:
+ description: 'FreeSWITCH repository ref'
+ required: false
+ type: string
+ sofia-sip_ref:
+ description: 'Sofia-Sip repository ref'
+ required: false
+ type: string
+
+jobs:
+ scan-build:
+ runs-on: ubuntu-latest
+ container:
+ image: signalwire/freeswitch-public-ci-base:bookworm-amd64
+ options: --privileged
+ env:
+ DEBIAN_FRONTEND: noninteractive
+
+ steps:
+ - name: Checkout Sofia-Sip
+ if: inputs.sofia-sip_ref == ''
+ uses: actions/checkout@v4
+ with:
+ repository: freeswitch/sofia-sip
+ path: sofia-sip
+
+ - name: Checkout Sofia-Sip (via ref)
+ if: inputs.sofia-sip_ref != ''
+ uses: actions/checkout@v4
+ with:
+ repository: freeswitch/sofia-sip
+ ref: ${{ inputs.sofia-sip_ref }}
+ path: sofia-sip
+
+ - name: Checkout FreeSWITCH (via ref)
+ if: inputs.freeswitch_ref != ''
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.freeswitch_ref }}
+ path: freeswitch
+
+ - name: Checkout FreeSWITCH
+ if: inputs.freeswitch_ref == ''
+ uses: actions/checkout@v4
+ with:
+ path: freeswitch
+
+ - name: Configure, Build and Install Sofia-Sip
+ shell: bash
+ working-directory: freeswitch
+ run: |
+ ./ci.sh -t scan-build -a configure -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip"
+ ./ci.sh -t scan-build -a build -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip"
+ ./ci.sh -t scan-build -a install -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip"
+
+ - name: Configure FreeSWITCH
+ shell: bash
+ working-directory: freeswitch
+ run: |
+ ./ci.sh -t scan-build -a configure -c freeswitch -p "$GITHUB_WORKSPACE/freeswitch"
+
+ - name: Run scan-build analysis
+ shell: bash
+ working-directory: freeswitch
+ run: |
+ ./ci.sh -t scan-build -a build -c freeswitch -p "$GITHUB_WORKSPACE/freeswitch"
+
+ - name: Check analysis results
+ if: always()
+ shell: bash
+ working-directory: freeswitch
+ run: |
+ ./ci.sh -t scan-build -a validate -c freeswitch -p "$GITHUB_WORKSPACE/freeswitch"
+
+ - name: Upload Scan-Build logs
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: scan-build-logs
+ path: freeswitch/scan-build
+ retention-days: 3
+ if-no-files-found: ignore
+ compression-level: 9
+
+ - name: Notify run tests result to slack
+ if: |
+ failure() &&
+ github.event_name == 'push' &&
+ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/v1.10')
+ uses: signalwire/actions-template/.github/actions/slack@main
+ with:
+ CHANNEL: ${{ secrets.SLACK_DEVOPS_CI_CHANNEL }}
+ MESSAGE: Scan-Build ${{ github.repository }} > <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.run_id }}>. Static analysis failed.
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
--- /dev/null
+name: Unit-tests D-in-D
+
+on:
+ workflow_call:
+ inputs:
+ freeswitch_ref:
+ description: 'FreeSWITCH repository ref'
+ required: false
+ type: string
+ sofia-sip_ref:
+ description: 'Sofia-Sip repository ref'
+ required: false
+ type: string
+
+env:
+ MAX_CONTAINERS: 8
+ NUM_CPU_PER_CONTAINER: 1
+ DOCKER_BUILD_SUMMARY: false
+ DOCKER_BUILD_CHECKS_ANNOTATIONS: false
+ DOCKER_BUILD_RECORD_UPLOAD: false
+
+jobs:
+ unit-tests:
+ runs-on: ubuntu-latest
+ container:
+ image: signalwire/freeswitch-public-ci-base:bookworm-amd64
+ options: --privileged
+ env:
+ DEBIAN_FRONTEND: noninteractive
+ ASAN_OPTIONS: log_path=stdout:disable_coredump=0:unmap_shadow_on_exit=1:fast_unwind_on_malloc=0
+
+ steps:
+ - name: Checkout Sofia-Sip (via ref)
+ if: inputs.sofia-sip_ref != ''
+ uses: actions/checkout@v4
+ with:
+ repository: freeswitch/sofia-sip
+ ref: ${{ inputs.sofia-sip_ref }}
+ path: sofia-sip
+
+ - name: Checkout Sofia-Sip
+ if: inputs.sofia-sip_ref == ''
+ uses: actions/checkout@v4
+ with:
+ repository: freeswitch/sofia-sip
+ path: sofia-sip
+
+ - name: Checkout FreeSWITCH (via ref)
+ if: inputs.freeswitch_ref != ''
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.freeswitch_ref }}
+ path: freeswitch
+
+ - name: Checkout FreeSWITCH
+ if: inputs.freeswitch_ref == ''
+ uses: actions/checkout@v4
+ with:
+ path: freeswitch
+
+ - name: Run Unit-Test containers and collect artifacts
+ id: unit_tests
+ shell: bash
+ run: |
+ echo "logs_path=${GITHUB_WORKSPACE}/freeswitch/tests/unit/logs" >> $GITHUB_OUTPUT
+
+ "${GITHUB_WORKSPACE}/freeswitch/tests/unit/run-tests-docker.sh" \
+ --base-image signalwire/freeswitch-public-ci-base:bookworm-amd64 \
+ --cpus ${{ env.NUM_CPU_PER_CONTAINER }} \
+ --image-tag ci.local \
+ --max-containers ${{ env.MAX_CONTAINERS }} \
+ --output-dir "${GITHUB_WORKSPACE}/freeswitch/tests/unit/logs" \
+ --sofia-sip-path "${GITHUB_WORKSPACE}/sofia-sip" \
+ --freeswitch-path "${GITHUB_WORKSPACE}/freeswitch"
+
+ test -d "/cores" && ls -lah /cores
+
+ cd "${GITHUB_WORKSPACE}/freeswitch/tests/unit/" && \
+ ./collect-test-logs.sh --dir logs --print
+
+ - name: Upload Unit-Test logs
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-results-${{ github.sha }}-${{ github.run_number }}
+ path: ${{ steps.unit_tests.outputs.logs_path }}
+ retention-days: 3
+ if-no-files-found: ignore
+ compression-level: 9
+
+ - name: Notify run tests result to slack
+ if: |
+ failure() &&
+ github.event_name == 'push' &&
+ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/v1.10')
+ uses: signalwire/actions-template/.github/actions/slack@main
+ with:
+ CHANNEL: ${{ secrets.SLACK_DEVOPS_CI_CHANNEL }}
+ MESSAGE: Unit-Tests ${{ github.repository }} > <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.run_id }}>. Some tests are failing.
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
description: 'Total number of test groups'
required: true
type: number
+ default: 1
current-group:
description: 'Current test group number'
required: true
type: number
+ default: 1
+ freeswitch_ref:
+ description: 'FreeSWITCH repository ref'
+ required: false
+ type: string
+ sofia-sip_ref:
+ description: 'Sofia-Sip repository ref'
+ required: false
+ type: string
+ container-image:
+ description: 'Container image to use for running tests'
+ required: false
+ type: string
+ default: 'signalwire/freeswitch-public-ci-base:bookworm-amd64'
+ working-directory:
+ description: 'Working directory for running tests'
+ required: false
+ type: string
+ default: 'freeswitch/tests/unit'
+ tests-only:
+ description: 'Run only tests, skip other tasks'
+ required: false
+ type: boolean
+ default: false
jobs:
unit-test:
runs-on: ubuntu-latest
container:
- image: signalwire/freeswitch-public-base:bookworm
- credentials:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
+ image: ${{ inputs.container-image }}
options: --privileged
env:
DEBIAN_FRONTEND: noninteractive
- name: Override core_pattern
shell: bash
run: |
- cat /proc/sys/kernel/core_pattern
echo '/cores/core.%s.%E.%e.%p.%t' > /proc/sys/kernel/core_pattern
cat /proc/sys/kernel/core_pattern
- - name: Install dependencies
- shell: bash
- env:
- REPOTOKEN: ${{ secrets.REPOTOKEN }}
- run: |
- echo "machine freeswitch.signalwire.com password $REPOTOKEN" > /etc/apt/auth.conf && \
- apt-get update && \
- apt-get -y remove \
- libsofia-sip-ua0 \
- libspandsp-dev && \
- apt-get -y install \
- libspandsp3-dev && \
- rm -rf /etc/apt/auth.conf
-
- - name: Checkout code
+ - name: Checkout Sofia-Sip (via ref)
+ if: ${{ !inputs.tests-only && inputs.sofia-sip_ref != '' }}
uses: actions/checkout@v4
with:
- path: /__w/freeswitch/freeswitch
-
- - name: Bootstrap
- shell: bash
- working-directory: /__w/freeswitch/freeswitch
- run: |
- ./bootstrap.sh -j || exit 1
+ repository: freeswitch/sofia-sip
+ ref: ${{ inputs.sofia-sip_ref }}
+ path: sofia-sip
- name: Checkout Sofia-Sip
+ if: ${{ !inputs.tests-only && inputs.sofia-sip_ref == '' }}
uses: actions/checkout@v4
with:
repository: freeswitch/sofia-sip
- path: /__w/freeswitch/freeswitch/sofia-sip
+ path: sofia-sip
+
+ - name: Checkout FreeSWITCH (via ref)
+ if: ${{ !inputs.tests-only && inputs.freeswitch_ref != '' }}
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.freeswitch_ref }}
+ path: freeswitch
+
+ - name: Checkout FreeSWITCH
+ if: ${{ !inputs.tests-only && inputs.freeswitch_ref == '' }}
+ uses: actions/checkout@v4
+ with:
+ path: freeswitch
- - name: Build sofia-sip
+ - name: Configure, Build and Install Sofia-Sip
+ if: ${{ !inputs.tests-only }}
shell: bash
- working-directory: /__w/freeswitch/freeswitch/sofia-sip
+ working-directory: freeswitch
run: |
- ./autogen.sh && \
- ./configure.gnu && \
- make -j$(nproc --all) install
+ ./ci.sh -t unit-test -a configure -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip"
+ ./ci.sh -t unit-test -a build -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip"
+ ./ci.sh -t unit-test -a install -c sofia-sip -p "$GITHUB_WORKSPACE/sofia-sip"
- - name: Build FreeSwitch
+ - name: Configure, Build and Install FreeSWITCH
+ if: ${{ !inputs.tests-only }}
shell: bash
- working-directory: /__w/freeswitch/freeswitch
+ working-directory: freeswitch
run: |
- echo 'codecs/mod_openh264' >> modules.conf && \
- sed -i \
- -e '/applications\/mod_http_cache/s/^#//g' \
- -e '/event_handlers\/mod_rayo/s/^#//g' \
- -e '/formats\/mod_opusfile/s/^#//g' \
- -e '/languages\/mod_lua/s/^#//g' \
- modules.conf && \
- ./configure \
- --enable-address-sanitizer \
- --enable-fake-dlclose && \
- make -j$(nproc --all) |& tee ./unit-tests-build-result.txt
+ ./ci.sh -t unit-test -a configure -c freeswitch -p "$GITHUB_WORKSPACE/freeswitch"
+ ./ci.sh -t unit-test -a build -c freeswitch -p "$GITHUB_WORKSPACE/freeswitch"
+ ./ci.sh -t unit-test -a install -c freeswitch -p "$GITHUB_WORKSPACE/freeswitch"
- echo ${PIPESTATUS[0]} > ./build-status.txt
- if ! test "$(cat ./build-status.txt | tr -d '[:space:]')" -eq 0; then
- exit "$(cat ./build-status.txt | tr -d '[:space:]')"
- fi
- make install
+ - name: Run unit tests
+ shell: bash
+ working-directory: ${{ inputs.working-directory }}
+ run: |
+ ./run-tests.sh ${{ inputs.total-groups }} ${{ inputs.current-group }} --output-dir logs || exit 1
- - name: Run tests
+ - name: Collect unit test logs
+ if: always()
shell: bash
- working-directory: /__w/freeswitch/freeswitch/tests/unit
+ working-directory: ${{ inputs.working-directory }}
run: |
- ./run-tests.sh ${{ inputs.total-groups }} ${{ inputs.current-group }}
- mkdir logs && (mv log_run-tests_*.html logs || true) && (mv backtrace_*.txt logs || true)
- ./collect-test-logs.sh
+ test -d "/cores" && ls -lah /cores
+ ./collect-test-logs.sh --dir logs --print
- - name: Notify result
+ - name: Upload Unit-Test logs
if: failure()
- uses: signalwire/actions-template/.github/actions/notify-ci-result@main
+ uses: actions/upload-artifact@v4
with:
- for: "run_tests"
- test_logs_path: /__w/freeswitch/freeswitch/tests/unit
- test_artifacts_suffix: "-${{ inputs.current-group }}"
+ name: test-results-${{ github.sha }}-${{ github.run_number }}-${{ inputs.current-group }}-of-${{ inputs.total-groups }}
+ path: ${{ inputs.working-directory }}/logs
+ retention-days: 3
+ if-no-files-found: ignore
+ compression-level: 9
+
+ - name: Notify run tests result to slack
+ if: |
+ failure() &&
+ github.event_name == 'push' &&
+ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/v1.10')
+ uses: signalwire/actions-template/.github/actions/slack@main
+ with:
+ CHANNEL: ${{ secrets.SLACK_DEVOPS_CI_CHANNEL }}
+ MESSAGE: Unit-Tests ${{ github.repository }} > <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|${{ github.run_id }}>. Some tests are failing.
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
--- /dev/null
+name: Windows
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+ push:
+ branches: [master, release]
+jobs:
+ x64:
+ runs-on: windows-2019
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Add msbuild to PATH
+ uses: microsoft/setup-msbuild@v2
+
+ - name: Build
+ run: msbuild Freeswitch.2017.sln -t:build -verbosity:minimal -property:Configuration=Release -property:Platform=x64
+
+ - name: Upload Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: MSI Package
+ path: D:\a\freeswitch\freeswitch\x64\*.msi
+ if: contains(github.event.pull_request.title, ':upload-artifacts') || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/v1.10'
print_tests:
@set +e; \
- test -z "$(TESTS)" || for i in $(TESTS); do echo $(subdir)/$$i; done;
-
\ No newline at end of file
+ test -z "$(TESTS)" || for i in $(TESTS); do echo $(subdir)/$$i; done; echo;
--- /dev/null
+#!/usr/bin/env bash
+
+### shfmt -w -s -ci -sr -kp -fn ci.sh
+
+#------------------------------------------------------------------------------
+# CI Script
+# Helper script for running CI jobs
+#------------------------------------------------------------------------------
+
+# Function to display usage information
+display_usage()
+{
+ echo "Usage: $0 -t <type> -a <action> -c <code> -p <path>"
+ echo "Options:"
+ echo " -t Type (unit-test, scan-build)"
+ echo " -a Action (configure, build, install, validate)"
+ echo " -c Code (sofia-sip, freeswitch)"
+ echo " -p Path to code"
+ exit 1
+}
+
+# Parse command line arguments
+while getopts "t:p:a:c:h" opt; do
+ case $opt in
+ t) TYPE="$OPTARG" ;;
+ a) ACTION="$OPTARG" ;;
+ c) CODE="$OPTARG" ;;
+ p) PATH_TO_CODE="$OPTARG" ;;
+ h) display_usage ;;
+ ?) display_usage ;;
+ esac
+done
+
+# Function to handle sofia-sip configuration
+configure_sofia_sip()
+{
+ ./autogen.sh && ./configure.gnu || exit 1
+}
+
+# Function to handle sofia-sip build
+build_sofia_sip()
+{
+ make -j$(nproc) || exit 1
+}
+
+# Function to handle sofia-sip installation
+install_sofia_sip()
+{
+ make install || exit 1
+}
+
+# Function to handle sofia-sip validation
+validate_sofia_sip()
+{
+ exit 0
+}
+
+# Function to handle freeswitch configuration
+configure_freeswitch()
+{
+ local type="$1"
+
+ ./bootstrap.sh -j || exit 1
+
+ case "$type" in
+ "unit-test")
+ echo 'codecs/mod_openh264' >> modules.conf
+ sed -i \
+ -e '/applications\/mod_http_cache/s/^#//g' \
+ -e '/event_handlers\/mod_rayo/s/^#//g' \
+ -e '/formats\/mod_opusfile/s/^#//g' \
+ -e '/languages\/mod_lua/s/^#//g' \
+ modules.conf
+
+ export ASAN_OPTIONS=log_path=stdout:disable_coredump=0:unmap_shadow_on_exit=1:fast_unwind_on_malloc=0
+
+ ./configure \
+ --enable-address-sanitizer \
+ --enable-fake-dlclose ||
+ exit 1
+
+ ;;
+ "scan-build")
+ cp build/modules.conf.most modules.conf
+
+ # "Enable"/"Uncomment" mods
+ echo 'codecs/mod_openh264' >> modules.conf
+ sed -i \
+ -e '/mod_mariadb/s/^#//g' \
+ -e '/mod_v8/s/^#//g' \
+ modules.conf
+
+ # "Disable"/"Comment out" mods
+ sed -i \
+ -e '/mod_ilbc/s/^/#/g' \
+ -e '/mod_isac/s/^/#/g' \
+ -e '/mod_mp4/s/^/#/g' \
+ -e '/mod_mongo/s/^/#/g' \
+ -e '/mod_pocketsphinx/s/^/#/g' \
+ -e '/mod_sangoma_codec/s/^/#/g' \
+ -e '/mod_siren/s/^/#/g' \
+ -e '/mod_avmd/s/^/#/g' \
+ -e '/mod_basic/s/^/#/g' \
+ -e '/mod_cdr_mongodb/s/^/#/g' \
+ -e '/mod_cv/s/^/#/g' \
+ -e '/mod_erlang_event/s/^/#/g' \
+ -e '/mod_perl/s/^/#/g' \
+ -e '/mod_rtmp/s/^/#/g' \
+ -e '/mod_unimrcp/s/^/#/g' \
+ -e '/mod_xml_rpc/s/^/#/g' \
+ modules.conf
+
+ ./configure || exit 1
+
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+}
+
+# Function to handle freeswitch build
+build_freeswitch()
+{
+ local type="$1"
+
+ set -o pipefail
+
+ case "$type" in
+ "unit-test")
+ make --no-keep-going -j$(nproc --all) |& tee ./unit-tests-build-result.txt
+ build_status=${PIPESTATUS[0]}
+ if [[ $build_status != "0" ]]; then
+ exit $build_status
+ fi
+
+ ;;
+ "scan-build")
+ if ! command -v scan-build-14 > /dev/null 2>&1; then
+ echo "Error: scan-build-14 command not found. Please ensure clang static analyzer is installed." >&2
+ exit 1
+ fi
+
+ mkdir -p scan-build
+
+ scan-build-14 \
+ --force-analyze-debug-code \
+ --status-bugs \
+ -o ./scan-build/ \
+ make --no-keep-going -j$(nproc --all) |& tee ./scan-build-result.txt
+ build_status=${PIPESTATUS[0]}
+
+ if ! grep -siq "scan-build: No bugs found" ./scan-build-result.txt; then
+ echo "scan-build: bugs found!"
+ exit 1
+ fi
+
+ if [[ $build_status != "0" ]]; then
+ echo "scan-build: compilation failed!"
+ exit $build_status
+ fi
+
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+}
+
+# Function to handle freeswitch installation
+install_freeswitch()
+{
+ make install || exit 1
+}
+
+# Function to handle freeswitch validation
+validate_freeswitch()
+{
+ local type="$1"
+
+ case "$type" in
+ "unit-test")
+ exit 0
+ ;;
+ "scan-build")
+ REPORT_PATH=$(find scan-build* -mindepth 1 -type d)
+ if [ -n "$REPORT_PATH" ]; then
+ echo "Found analysis report at: $REPORT_PATH"
+
+ if command -v html2text > /dev/null 2>&1; then
+ echo "Report contents:"
+ html2text "$REPORT_PATH"/*.html || true
+ fi
+
+ echo "Number of issues found:"
+ grep -c "<!--BUGDESC" "$REPORT_PATH"/*.html || true
+
+ exit $([ -d "$REPORT_PATH" ])
+ else
+ echo "No analysis report found"
+ exit 0
+ fi
+
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+}
+
+# Change to the code directory
+if [ -n "$PATH_TO_CODE" ]; then
+ cd "$PATH_TO_CODE" || exit 1
+fi
+
+# Execute appropriate flow based on code, type, and action
+case "$CODE" in
+ "sofia-sip")
+ case "$ACTION" in
+ "configure")
+ configure_sofia_sip "$TYPE"
+ ;;
+ "build")
+ build_sofia_sip "$TYPE"
+ ;;
+ "install")
+ install_sofia_sip "$TYPE"
+ ;;
+ "validate")
+ validate_sofia_sip "$TYPE"
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+ ;;
+ "freeswitch")
+ case "$ACTION" in
+ "configure")
+ configure_freeswitch "$TYPE"
+ ;;
+ "build")
+ build_freeswitch "$TYPE"
+ ;;
+ "install")
+ install_freeswitch "$TYPE"
+ ;;
+ "validate")
+ validate_freeswitch "$TYPE"
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+ ;;
+ *)
+ exit 1
+ ;;
+esac
+++ /dev/null
-#!/bin/bash
-mkdir -p scan-build
-scan-build-14 --force-analyze-debug-code -o ./scan-build/ make -j`nproc --all` |& tee ./scan-build-result.txt
-exitstatus=${PIPESTATUS[0]}
-echo "*** Exit status is $exitstatus"
-export SubString="scan-build: No bugs found"
-export COMPILATION_FAILED="false"
-export BUGS_FOUND="false"
-if [[ "0" != "$exitstatus" ]] ; then
- export COMPILATION_FAILED="true"
- echo MESSAGE="compilation failed" >> $GITHUB_OUTPUT
-fi
-export RESULTFILE="$PWD/scan-build-result.txt"
-# cat $RESULTFILE
-if ! grep -sq "$SubString" $RESULTFILE; then
- export BUGS_FOUND="true"
- echo MESSAGE="found bugs" >> $GITHUB_OUTPUT
-fi
-export REPORT=$PWD/`find scan-build* -mindepth 1 -type d`
-echo "COMPILATION_FAILED: $COMPILATION_FAILED"
-echo "BUGS_FOUND: $BUGS_FOUND"
-echo "COMPILATION_FAILED=$COMPILATION_FAILED" >> $GITHUB_OUTPUT
-echo "BUGS_FOUND=$BUGS_FOUND" >> $GITHUB_OUTPUT
-echo "REPORT=$REPORT" >> $GITHUB_OUTPUT
-if [[ "0" != "$exitstatus" ]] || ! grep -sq "$SubString" $RESULTFILE; then
- exit 1
-fi
-exit 0
-#!/bin/bash
+#!/usr/bin/env bash
+### shfmt -w -s -ci -sr -kp -fn tests/unit/collect-test-logs.sh
+
+#------------------------------------------------------------------------------
+# Collects test logs and generates an HTML report
+# of failed unit tests with links to backtraces
+#------------------------------------------------------------------------------
+
+# Configuration with default value
+LOG_DIR="./logs"
+PRINT_TO_CONSOLE=0
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -p | --print)
+ if ! command -v html2text > /dev/null 2>&1; then
+ echo "Error: html2text is required for printing HTML contents"
+ echo "Please install html2text and try again"
+ exit 1
+ fi
+ PRINT_TO_CONSOLE=1
+ shift
+ ;;
+ -d | --dir)
+ if [ -z "$2" ]; then
+ echo "Error: Log directory path is required for -d|--dir option"
+ exit 1
+ fi
+ LOG_DIR="$2"
+ shift 2
+ ;;
+ *)
+ echo "Unknown option: $1"
+ echo "Usage: $0 [-p|--print] [-d|--dir DIR]"
+ exit 1
+ ;;
+ esac
+done
+
+# Initialize HTML
echo "Collecting test logs"
-LOG_DIR=./logs
-html="<html><h3>There are failed unit-tests:</h3><table>"
-logs=$(find $LOG_DIR -type f -iname "*.html" -print | sort)
+html="<html><head><title>Failed Unit Tests Report</title></head><body><h3>There are failed unit-tests:</h3><table>"
+
+# Find all HTML log files and sort them
+logs=$(find "$LOG_DIR" -type f -iname "*.html" -print | sort)
logs_found=0
olddirname=""
-for name in $logs
-do
- logname=$(basename $name)
- testname=$(echo $logname | awk -F 'log_run-tests_' '{print $2}' | awk -F '.html' '{print $1}')
+
+# Process each log file
+for name in $logs; do
+ # Extract test information
+ logname=$(basename "$name")
+ testname=$(echo "$logname" | awk -F 'log_run-tests_' '{print $2}' | awk -F '.html' '{print $1}')
testpath="${testname//!/\/}"
- dirname=$(dirname $testpath)
- test=$(basename $testpath)
+ dirname=$(dirname "$testpath")
+ test=$(basename "$testpath")
+
+ # Add directory header if it's new
if [ "$olddirname" != "$dirname" ]; then
- html+="<tr align=\"left\"><th><br>$dirname</th></tr>" ;
- olddirname=$dirname ;
+ html+="<tr align=\"left\"><th><br>$dirname</th></tr>"
+ olddirname=$dirname
fi
- html+="<tr align=\"left\"><td><a href="$logname">$test</a>"
+
+ # Add test entry
+ html+="<tr align=\"left\"><td><a href=\"$logname\">$test</a>"
+
+ # Check for backtrace
backtrace="backtrace_$testname.txt"
if test -f "${LOG_DIR}/$backtrace"; then
+ if [ $PRINT_TO_CONSOLE -eq 1 ]; then
+ echo "Core dumped, backtrace:"
+ cat $backtrace
+ echo
+ fi
+
html+=". Core dumped, backtrace is available <a href=\"$backtrace\">here</a>"
fi
+
html+="</td></tr>"
logs_found=1
+
+ # Print current log file if requested
+ if [ $PRINT_TO_CONSOLE -eq 1 ]; then
+ echo "=== Contents of $name ==="
+ html2text "$name"
+ echo "=== End of $name ==="
+ echo
+ fi
done
+# Generate report if logs were found
if [ $logs_found -ne 0 ]; then
- html+="</table></html>"
- echo $html > $LOG_DIR/artifacts.html
+ html+="</table></body></html>"
+ echo "$html" > "$LOG_DIR/artifacts.html"
exit 1
fi
--- /dev/null
+#!/usr/bin/env bash
+
+### shfmt -w -s -ci -sr -kp -fn tests/unit/run-tests-docker.sh
+
+#------------------------------------------------------------------------------
+# Docker Test Runner
+# Parallel test execution in Docker with configurable CPU and container counts
+#------------------------------------------------------------------------------
+
+# Exit on error
+set -e
+
+# Global exit status
+GLOBAL_EXIT_STATUS=0
+
+# Default values
+SOFIA_SIP_PATH=""
+FREESWITCH_PATH=""
+IMAGE_TAG="ci.local"
+BASE_IMAGE=""
+MAX_CONTAINERS="1"
+CPUS_PER_CONTAINER="1"
+CONTAINER_IDS_FILE=$(mktemp)
+OUTPUT_DIR=""
+
+# Parse command line arguments
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --sofia-sip-path)
+ SOFIA_SIP_PATH="$2"
+ shift
+ ;;
+ --freeswitch-path)
+ FREESWITCH_PATH="$2"
+ shift
+ ;;
+ --image-tag)
+ IMAGE_TAG="$2"
+ shift
+ ;;
+ --base-image)
+ BASE_IMAGE="$2"
+ shift
+ ;;
+ --max-containers)
+ MAX_CONTAINERS="$2"
+ shift
+ ;;
+ --cpus)
+ CPUS_PER_CONTAINER="$2"
+ shift
+ ;;
+ --output-dir)
+ OUTPUT_DIR="$2"
+ shift
+ ;;
+ *)
+ echo "Unknown parameter: $1"
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+# Validate paths exist
+if [ ! -d "$SOFIA_SIP_PATH" ]; then
+ echo "Error: Sofia-SIP path does not exist: $SOFIA_SIP_PATH"
+ exit 1
+fi
+
+if [ ! -d "$FREESWITCH_PATH" ]; then
+ echo "Error: FreeSWITCH path does not exist: $FREESWITCH_PATH"
+ exit 1
+fi
+
+# Validate output directory is provided (required for test results)
+if [ -z "$OUTPUT_DIR" ]; then
+ echo "Error: Output directory must be specified with --output-dir"
+ exit 1
+fi
+
+# Create output directory
+mkdir -p "$OUTPUT_DIR"
+
+# Define build log file
+BUILD_LOG="$OUTPUT_DIR/docker_build.log"
+
+echo "Starting Docker build..."
+
+# Build Docker image and redirect output to log file
+if ! docker build \
+ --build-arg BUILDER_IMAGE="$BASE_IMAGE" \
+ --build-context sofia-sip="$SOFIA_SIP_PATH" \
+ --build-context freeswitch="$FREESWITCH_PATH" \
+ --file "$FREESWITCH_PATH/.github/docker/debian/bookworm/amd64/CI/Dockerfile" \
+ --tag "$IMAGE_TAG" \
+ "$FREESWITCH_PATH/.github/docker/debian" > "$BUILD_LOG" 2>&1; then
+ echo "Docker build failed! Build log:"
+ cat "$BUILD_LOG"
+ exit 1
+fi
+
+echo "Build completed successfully! Build log saved to: $BUILD_LOG"
+
+# Get working directory from image
+CONTAINER_WORKDIR=$(docker inspect "$IMAGE_TAG" --format='{{.Config.WorkingDir}}')
+if [ -z "$CONTAINER_WORKDIR" ]; then
+ echo "Error: Could not determine container working directory"
+ exit 1
+fi
+
+# Start test containers with output directory mounted
+echo "Starting $MAX_CONTAINERS containers..."
+
+for i in $(seq 1 "$MAX_CONTAINERS"); do
+ CTID=$(docker run --privileged \
+ --cpus "$CPUS_PER_CONTAINER" \
+ --volume "$OUTPUT_DIR:$CONTAINER_WORKDIR/$OUTPUT_DIR" \
+ --detach \
+ "$IMAGE_TAG" \
+ --output-dir "$OUTPUT_DIR" \
+ $MAX_CONTAINERS $i)
+ echo "$CTID $i" >> "$CONTAINER_IDS_FILE"
+ echo "Started container: $CTID (index: $i)"
+done
+
+echo "All containers started successfully!"
+
+# Wait for containers to finish and collect results
+echo "Waiting for containers to finish..."
+while read -r line; do
+ CTID=$(echo "$line" | cut -d' ' -f1)
+ INDEX=$(echo "$line" | cut -d' ' -f2)
+
+ docker wait "$CTID" > /dev/null 2>&1
+ EXIT_CODE=$(docker inspect "$CTID" --format='{{.State.ExitCode}}')
+
+ # Save container logs to output directory
+ docker logs "$CTID" > "$OUTPUT_DIR/$CTID.log" 2>&1
+ echo "Container logs saved to: $OUTPUT_DIR/$CTID.log"
+
+ if [ "$EXIT_CODE" -ne 0 ]; then
+ echo "Container $CTID (index: $INDEX) failed with exit code: $EXIT_CODE"
+ GLOBAL_EXIT_STATUS=1
+
+ tail -n 50 "$OUTPUT_DIR/$CTID.log"
+ else
+ echo "Container $CTID (index: $INDEX) completed successfully"
+ fi
+
+done < "$CONTAINER_IDS_FILE"
+
+# Clean up temporary files
+rm -f "$CONTAINER_IDS_FILE"
+
+echo "Test outputs have been saved to: $OUTPUT_DIR"
+
+# Exit with global status
+if [ "$GLOBAL_EXIT_STATUS" -eq 0 ]; then
+ echo "All containers completed successfully!"
+else
+ echo "One or more containers failed!"
+fi
+
+exit $GLOBAL_EXIT_STATUS
-#!/bin/bash
+#!/usr/bin/env bash
-# "print_tests" returns relative paths to all the tests
-TESTS=$(make -s -C ../.. print_tests)
+### shfmt -w -s -ci -sr -kp -fn tests/unit/run-tests.sh
-chunks=${1:-1}
-chunk_number=${2:-1}
+#------------------------------------------------------------------------------
+# Test Runner Script
+# Runs tests in chunks, distributing them across processors
+# Supports moving test artifacts to specified output directory
+#------------------------------------------------------------------------------
-IFS=$'\n' read -d '' -r -a lines <<< "$TESTS"
+# Exit on error, undefined vars, and propagate pipe failures
+set -euo pipefail
-result=""
-for ((i=chunk_number-1; i<${#lines[@]}; i+=chunks))
-do
- result+="${lines[$i]}"$'\n'
+# Global variable for test failures
+declare -i TESTS_FAILED=0
+
+# Function to show usage
+show_usage()
+{
+ echo "Usage: $0 [chunks] [chunk_number] [options]"
+ echo " chunks : Number of chunks to split tests into (default: 1)"
+ echo " chunk_number : Which chunk to run (default: 1)"
+ echo "Options:"
+ echo " --dry-run : Show test distribution without running tests"
+ echo " --output-dir : Directory to store test artifacts (will be created if needed)"
+ echo " -h|--help : Show this help message"
+ exit 1
+}
+
+# Function to validate numeric input
+validate_number()
+{
+ local val=$1
+ local name=$2
+
+ if ! [[ $val =~ ^[0-9]+$ ]]; then
+ echo "Error: $name must be a positive number, got: $val"
+ exit 1
+ fi
+
+ if [ "$val" -lt 1 ]; then
+ echo "Error: $name must be greater than 0, got: $val"
+ exit 1
+ fi
+}
+
+# Function to format duration in human-readable form
+format_duration()
+{
+ local duration=$1
+ local minutes=$((duration / 60))
+ local seconds=$((duration % 60))
+ printf "%02d:%02d" $minutes $seconds
+}
+
+# Function to move test artifacts to output directory
+move_artifacts()
+{
+ local output_dir=$1
+
+ # Create output directory if it doesn't exist
+ mkdir -p "$output_dir"
+
+ # Move HTML logs and backtrace files if they exist
+ # Using || true to prevent script failure if no files match
+ (mv log_run-tests_*.html "$output_dir" 2> /dev/null || true)
+ (mv backtrace_*.txt "$output_dir" 2> /dev/null || true)
+
+ # Check if any files were moved
+ if [ -n "$(ls -A "$output_dir" 2> /dev/null)" ]; then
+ echo "Test artifacts moved to: $output_dir"
+ else
+ echo "No test artifacts found to move"
+ fi
+}
+
+# Parse command line arguments
+chunks=1
+chunk_number=1
+dry_run=false
+output_dir=""
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --dry-run)
+ dry_run=true
+ shift
+ ;;
+ --output-dir)
+ if [ -n "${2:-}" ]; then
+ output_dir="$2"
+ shift 2
+ else
+ echo "Error: --output-dir requires a directory path"
+ exit 1
+ fi
+ ;;
+ -h | --help)
+ show_usage
+ ;;
+ *)
+ if [[ $chunks -eq 1 ]]; then
+ chunks=$1
+ elif [[ $chunk_number -eq 1 ]]; then
+ chunk_number=$1
+ else
+ echo "Error: Unknown argument $1"
+ show_usage
+ fi
+ shift
+ ;;
+ esac
+done
+
+# Validate numeric inputs
+validate_number "$chunks" "chunks"
+validate_number "$chunk_number" "chunk_number"
+
+# Validate chunk parameters
+if [ "$chunk_number" -gt "$chunks" ]; then
+ echo "Error: chunk_number ($chunk_number) cannot be greater than total chunks ($chunks)"
+ exit 1
+fi
+
+# Get list of tests from make
+echo "Fetching test list..."
+TESTS=$(make -s -C ../.. print_tests 2>/dev/null) || {
+ echo "Error: Failed to fetch test list"
+ exit 1
+}
+
+# Split tests into array
+IFS=$'\n' read -d '' -r -a all_tests <<< "$TESTS" || true # || true to handle last line without newline
+
+# Check if any tests were found
+if [ ${#all_tests[@]} -eq 0 ]; then
+ echo "Error: No tests found!"
+ exit 1
+fi
+
+# Get total number of tests from array length
+total_tests=${#all_tests[@]}
+
+# Select tests for this chunk
+chunk_tests=()
+for ((i = chunk_number - 1; i < total_tests; i += chunks)); do
+ chunk_tests+=("${all_tests[$i]}")
+done
+
+# Size of this chunk
+chunk_size=${#chunk_tests[@]}
+
+# Print execution information
+echo ""
+echo "Test Distribution Information:"
+echo "Total tests found: $total_tests"
+echo "Chunk size: $chunk_size"
+echo "Running chunk $chunk_number/$chunks"
+if [ -n "$output_dir" ]; then
+ echo "Artifacts will be stored in: $output_dir"
+fi
+echo ""
+echo "Tests to be executed:"
+for i in "${!chunk_tests[@]}"; do
+ printf "%3d) %s\n" "$((i + 1))" "${chunk_tests[$i]}"
done
+echo ""
+
+# Exit here if dry run
+if [ "$dry_run" = true ]; then
+ echo "Dry run complete. Use without --dry-run to execute tests."
+ exit 0
+fi
+
+# Record start time
+start_time=$(date +%s)
-TESTS=$result
+# Run tests sequentially within the chunk
+if ! make -f run-tests.mk TEST_LIST="${chunk_tests[*]}"; then
+ TESTS_FAILED=1
+fi
-echo "-----------------------------------------------------------------";
-echo "Starting tests on $(nproc --all) processors";
-echo "Tests found: ${TESTS}";
-echo "-----------------------------------------------------------------";
+# Move artifacts if output directory was specified
+if [ -n "$output_dir" ]; then
+ move_artifacts "$output_dir"
+fi
-make -f run-tests.mk TEST_LIST=$TESTS
+# Record end time and calculate duration
+end_time=$(date +%s)
+duration=$((end_time - start_time))
-echo "Timing results:"
-cat test_times.log
+# Print timing results and statistics
+echo ""
+echo "Execution Summary for chunk $chunk_number/$chunks:"
+echo "Started at : $(date -d @$start_time '+%Y-%m-%d %H:%M:%S')"
+echo "Finished at: $(date -d @$end_time '+%Y-%m-%d %H:%M:%S')"
+echo "Duration : $(format_duration $duration)"
+echo "Status : $([ $TESTS_FAILED -eq 0 ] && echo "SUCCESS" || echo "FAILED")"
+echo ""
-echo "Done running tests!"
+# Exit with appropriate status code
+exit $TESTS_FAILED
-#!/bin/bash
+#!/usr/bin/env bash
+### shfmt -w -s -ci -sr -kp -fn tests/unit/run-tests.sh
+
+#------------------------------------------------------------------------------
+# Test Execution Script
+# Executes unit tests and handles test logs and core dumps
+#------------------------------------------------------------------------------
+
+# Initialize timing
start_time=$(date +%s)
# All output will be collected here
# All relative paths are based on the tree's root
FSBASEDIR=$(realpath "$PWD/../../")
+# Set system limits
ulimit -c unlimited
ulimit -a
+# Get test identifier from argument
i=$1
-echo "----------------------------------" ;
-echo "Starting test: $i" ;
-echo "----------------------------------" ;
+echo ""
+echo "Starting test: $i"
+echo ""
# Change folder to where the test is
currenttestpath="$FSBASEDIR/$i"
-cd $(dirname "$currenttestpath")
+cd "$(dirname "$currenttestpath")"
# Tests are unique per module, so need to distinguish them by their directory
relativedir=$(dirname "$i")
echo "Relative dir is $relativedir"
+# Set up log file path
file=$(basename -- "$currenttestpath")
-log="$TESTSUNITPATH/log_run-tests_${relativedir//\//!}!$file.html";
+log="$TESTSUNITPATH/log_run-tests_${relativedir//\//!}!$file.html"
# Execute the test
echo "Start executing $currenttestpath"
-$currenttestpath 2>&1 | tee >(ansi2html > $log) ;
-exitstatus=${PIPESTATUS[0]} ;
+$currenttestpath 2>&1 | tee >(ansi2html > "$log")
+exitstatus=${PIPESTATUS[0]}
echo "End executing $currenttestpath"
+
+# Record execution time
end_time=$(date +%s)
duration=$((end_time - start_time))
echo "Test $1 took $duration seconds" >> test_times.log
echo "Exit status is $exitstatus"
-if [ "0" -eq $exitstatus ] ; then
- rm $log ;
+# Handle test results
+if [ "0" -eq "$exitstatus" ]; then
+ rm "$log"
else
- echo "*** ./$i exit status is $exitstatus" ;
- corefilesearch=/cores/core.*.!__w!freeswitch!freeswitch!${relativedir//\//!}!.libs!$file.* ;
- echo $corefilesearch ;
+ echo "*** ./$i exit status is $exitstatus"
+
+ # Search for core dumps
+ corefilesearch="/cores/core.*.!__w!freeswitch!freeswitch!${relativedir//\//!}!.libs!$file.*"
+ echo "$corefilesearch"
+
if ls $corefilesearch 1> /dev/null 2>&1; then
- echo "coredump found";
- coredump=$(ls $corefilesearch) ;
- echo $coredump;
- echo "set logging file $TESTSUNITPATH/backtrace_${i//\//!}.txt" ;
- gdb -ex "set logging file $TESTSUNITPATH/backtrace_${i//\//!}.txt" -ex "set logging on" -ex "set pagination off" -ex "bt full" -ex "bt" -ex "info threads" -ex "thread apply all bt" -ex "thread apply all bt full" -ex "quit" /__w/freeswitch/freeswitch/$relativedir/.libs/$file $coredump ;
- fi ;
- echo "*** $log was saved" ;
-fi ;
-echo "----------------" ;
+ echo "coredump found"
+ coredump=$(ls $corefilesearch)
+ echo "$coredump"
+
+ # Generate backtrace using GDB
+ gdb \
+ -ex "set logging file $TESTSUNITPATH/backtrace_${i//\//!}.txt" \
+ -ex "set logging on" \
+ -ex "set pagination off" \
+ -ex "bt full" \
+ -ex "bt" \
+ -ex "info threads" \
+ -ex "thread apply all bt" \
+ -ex "thread apply all bt full" \
+ -ex "quit" \
+ "$FSBASEDIR/$relativedir/.libs/$file" \
+ "$coredump"
+ fi
+
+ echo "*** $log was saved"
+
+ exit $exitstatus
+fi
+
+echo ""