Description: Enhance test sources
--- austin-1.0.1.orig/.travis.yml
+++ austin-1.0.1/.travis.yml
@@ -30,7 +30,6 @@ jobs:
       os: windows
 
 before_script:
-  # Linux Dependencies
   - if [[ "$TRAVIS_OS_NAME" == "linux" ]];
     then
       sudo add-apt-repository ppa:deadsnakes/ppa -y;
@@ -50,12 +49,6 @@ before_script:
       brew cask install anaconda         || true;
     fi
 
-  - if [[ "$TRAVIS_OS_NAME" == "windows" ]];
-    then
-      powershell Install-WindowsFeature Net-Framework-Core;
-      cinst -y wixtoolset;
-    fi
-
 script:
   - echo $TRAVIS_OS_NAME -- $TARGET
 
@@ -64,12 +57,16 @@ script:
       ./configure &&
       make &&
       sudo make check;
+
+      test -f /tmp/austin_tests.log && cat /tmp/austin_tests.log;
     fi
 
   - if [[ "$TRAVIS_OS_NAME" == "osx"     ]];
     then
       gcc -s -Wall -O3 -o src/austin src/*.c &&
       sudo bats test/macos/test.bats;
+
+      test -f /tmp/austin_tests.log && cat /tmp/austin_tests.log;
     fi
 
   - if [[ "$TRAVIS_OS_NAME" == "windows" ]];
@@ -78,6 +75,7 @@ script:
     fi
 
 after_success:
+  ./src/austin -V;
   ./src/austin --usage
 
 after_failure:
@@ -119,12 +117,6 @@ before_deploy:
       export ZIP_CMD="7z a -tzip";
       export ZIP_SUFFIX="win-${TARGET%%-*}.zip";
       export AUSTIN_EXE=austin.exe;
-
-      export WIN_MSI="austin-$VERSION-win64.msi";
-
-      sed -i "s/%VERSION%/$VERSION/g" wix/Austin.wxs;
-      candle wix/Austin.wxs -out wix/Austin.wixobj;
-      light -ext WixUIExtension wix/Austin.wixobj -out $WIN_MSI;
     fi
 
   - export ARTEFACT="austin-${VERSION}-${ZIP_SUFFIX}"
@@ -140,30 +132,8 @@ before_deploy:
   - git tag -a -f -m "Release $VERSION" $TRAVIS_TAG
 
 deploy:
-  - provider: releases
-    edge: true
-    token: $GITHUB_TOKEN
-    file: $ARTEFACT
-    overwrite: true
-
-  - provider: releases
-    edge: true
-    token: $GITHUB_TOKEN
-    file: $WIN_MSI
-    overwrite: true
-    on:
-      condition: "$TRAVIS_OS_NAME = windows"
-
-after_deploy:
-  - if [[ "$TRAVIS_OS_NAME" == "windows" ]];
-    then
-      export WIN_MSI_HASH=$( sha256sum $WIN_MSI | head -c 64 );
-
-      cd choco;
-
-      sed -i "s/%WIN_MSI_HASH%/$WIN_MSI_HASH/g" tools/chocolateyinstall.ps1;
-      /bin/find . -type f -exec sed -i "s/%VERSION%/$VERSION/g" {} \; ;
-      choco apikey --key $CHOCO_APIKEY --source https://push.chocolatey.org/;
-      choco pack;
-      choco push;
-    fi
+  provider: releases
+  edge: true
+  token: $GITHUB_TOKEN
+  file: $ARTEFACT
+  overwrite: true
--- /dev/null
+++ austin-1.0.1/test/common.bash
@@ -0,0 +1,227 @@
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# -----------------------------------------------------------------------------
+# -- Austin
+# -----------------------------------------------------------------------------
+
+AUSTIN=`test -f src/austin && echo "src/austin" || echo "austin"`
+
+
+# -----------------------------------------------------------------------------
+# -- Python
+# -----------------------------------------------------------------------------
+
+function check_python {
+  version="${1}"
+
+  if ! python$version -V; then skip "Python $version not found."; fi
+
+  PYTHON="python$version"
+}
+
+# -----------------------------------------------------------------------------
+# -- Logging
+# -----------------------------------------------------------------------------
+
+function log {
+  echo "${1}" | tee -a "/tmp/austin_tests.log"
+}
+
+# -----------------------------------------------------------------------------
+
+function step {
+  log "  :: ${1}"
+}
+
+
+# -----------------------------------------------------------------------------
+# -- Assertions
+# -----------------------------------------------------------------------------
+
+IGNORE=0
+FAIL=0
+REPEAT=0
+
+# -----------------------------------------------------------------------------
+
+function ignore {
+  IGNORE=1
+}
+
+# -----------------------------------------------------------------------------
+
+function check_ignored {
+  FAIL=1
+
+  if [ $IGNORE == 1 ] && [ $REPEAT == 0 ]
+  then
+    log "        The test it marked as 'ignore'"
+  fi
+  log
+  log "       Status: $status"
+  log
+  log "       Collected Output"
+  log "       ================"
+  log
+  for line in "${lines[@]}"
+  do
+    log "       $line"
+  done
+  log
+
+  if [ $IGNORE == 0 ] && [ $REPEAT == 0 ]; then false; fi
+}
+
+# -----------------------------------------------------------------------------
+
+function assert {
+  local message="${1}"
+  local condition="${2}"
+
+  if [ ! $condition ]
+  then
+    log "      Assertion failed:  \"${message}\""
+    check_ignored
+  fi
+
+  true
+}
+
+# -----------------------------------------------------------------------------
+
+function assert_success {
+  : "${output?}"
+  : "${status?}"
+
+  assert "Command was successful" "$status == 0"
+}
+
+# -----------------------------------------------------------------------------
+
+function assert_output {
+  local pattern="${1}"
+  : "${output?}"
+
+  if ! echo "$output" | grep -q "${pattern}"
+  then
+    log "      Assertion failed:  Output contains pattern '${pattern}'"
+    check_ignored
+  fi
+
+  true
+}
+
+# -----------------------------------------------------------------------------
+
+function assert_not_output {
+  local pattern="${1}"
+  : "${output?}"
+
+  if echo "$output" | grep -q "${pattern}"
+  then
+    log "      Assertion failed:  Output does not contain pattern '${pattern}'"
+    check_ignored
+  fi
+
+  true
+}
+
+# -----------------------------------------------------------------------------
+
+function assert_file {
+  local file="$1"
+  local pattern="${2}"
+
+  if ! cat "$file" | grep -q "${pattern}"
+  then
+    log "      Assertion failed:  File $file contains pattern '${pattern}'"
+    log
+    log "File content"
+    log "============"
+    log
+    log "$( head "$file" )"
+    log ". . ."
+    log "$( tail "$file" )"
+    log
+    check_ignored
+  fi
+
+  true
+}
+
+# -----------------------------------------------------------------------------
+
+function assert_not_file {
+  local file="$1"
+  local pattern="${2}"
+
+  if ! test -f $file
+  then
+    log "      Assertion failed:  File $file does not exist"
+    check_ignored
+  fi
+
+  if cat "$file" | grep -q "${pattern}"
+  then
+    log "      Assertion failed:  File $file does not contain pattern '${pattern}'"
+    log
+    log "File content"
+    log "============"
+    log
+    log "$( head "$file" )"
+    log ". . ."
+    log "$( tail "$file" )"
+    log
+    check_ignored
+  fi
+
+  true
+}
+
+# -----------------------------------------------------------------------------
+
+function repeat {
+  local times="${1}"
+  shift
+
+  REPEAT=1
+
+  for ((i=1;i<=times;i++))
+  do
+    log ">> Attempt $i of $times"
+    FAIL=0
+    $@
+    if [ $FAIL == 0 ]; then return; fi
+  done
+
+  REPEAT=0
+
+  log "<< Test failed on $times attempt(s)."
+
+  if [ $IGNORE == 1 ]
+  then
+    skip "Failed but marked as 'ignore'."
+  fi
+
+  false
+}
--- austin-1.0.1.orig/test/macos/test.bats
+++ austin-1.0.1/test/macos/test.bats
@@ -1,9 +1,33 @@
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "../common"
+
+
 test_case() {
   run bats test/macos/test_$1.bats
-  echo "$output"
-  [ $status = 0 ]
 }
 
+
 @test "Test Austin: fork" {
   test_case fork
 }
@@ -17,9 +41,7 @@ test_case() {
 }
 
 @test "Test Austin: valgrind" {
-  skip "We skip valgrind on Mac OS for now"
-  
+  ignore
   if ! which valgrind; then skip "Valgrind not found"; fi
-
   test_case valgrind
 }
--- austin-1.0.1.orig/test/macos/test_attach.bats
+++ austin-1.0.1/test/macos/test_attach.bats
@@ -1,81 +1,69 @@
-attach_austin() {
-  python_bin=$1
-  ignore=$2
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-  if ! $python_bin -V; then skip "$python_bin not found."; fi
-
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
+load "../common"
 
-    echo "  :: Time profiling"
-    $python_bin test/sleepy.py &
-    sleep 1
-    run sudo src/austin -i 10000 -t 10000 -p $!
 
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
+function attach_austin {
+  python_bin="${1}"
 
-    if ! echo "$output" | grep -q ";<module> (test/sleepy.py);L[[:digit:]]* "
-    then
-      echo "       Output: NOK"
-      continue
-    fi
-    echo "       Output: OK"
+  if ! $python_bin -V; then skip "$python_bin not found."; fi
 
-    # -------------------------------------------------------------------------
+  log "Attach [Python $version]"
 
-    echo "  :: Memory profiling"
+  # -------------------------------------------------------------------------
+  step "Time profiling"
+  # -------------------------------------------------------------------------
     $python_bin test/sleepy.py &
     sleep 1
-    run sudo src/austin -mi 100 -t 10000 -p $!
+    run sudo $AUSTIN -i 10000 -t 100 -p $!
 
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
+    assert_success
+    assert_output ";<module> (test/sleepy.py);L[[:digit:]]* "
 
-    if echo "$output" | grep -q "Thread "
-    then
-      echo "       Output: OK"
-      return
-    fi
-    echo "       Output: NOK"
-  done
-
-  if [ $ignore ]
-  then
-    echo "Test marked as 'Ignore' failed"
-  fi
-  echo
-  echo "Collected Output"
-  echo "================"
-  echo
-  echo "$output"
-  echo
-  
-  false
 }
 
 
 # -----------------------------------------------------------------------------
-
-
-# @test "Test Austin with the default Python 3" {
-#   /usr/bin/python3 -m venv /tmp/py3
-#   source /tmp/py3/bin/activate
-# 	attach_austin "python3"
-#   test -d /tmp/py3 && rm -rf /tmp/py3
-# }
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with default Python 3 from Homebrew" {
 	attach_austin "/usr/local/bin/python3"
 }
 
 @test "Test Austin with Python 3.8 from Homebrew (if available)" {
-  attach_austin "/usr/local/opt/python@3.8/bin/python3" ignore
+  ignore
+  repeat 3 attach_austin "/usr/local/opt/python@3.8/bin/python3"
 }
 
 @test "Test Austin with Python 3 from Anaconda (if available)" {
-  attach_austin "/usr/local/anaconda3/bin/python" ignore
+  ignore
+  repeat 3 attach_austin "/usr/local/anaconda3/bin/python"
 }
+
+# @test "Test Austin with the default Python 3" {
+#   /usr/bin/python3 -m venv /tmp/py3
+#   source /tmp/py3/bin/activate
+# 	attach_austin "python3"
+#   test -d /tmp/py3 && rm -rf /tmp/py3
+# }
--- austin-1.0.1.orig/test/macos/test_fork.bats
+++ austin-1.0.1/test/macos/test_fork.bats
@@ -1,98 +1,92 @@
-#!/usr/bin/env bats
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "../common"
+
+
+function invoke_austin {
+  python_bin="${1}"
 
-invoke_austin() {
-  python_bin=$1
-  ignore=$2
-  
   if ! $python_bin -V; then skip "$python_bin not found."; fi
 
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Standard profiling"
-    run sudo src/austin -i 1000 -t 10000 $python_bin test/target34.py
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q "keep_cpu_busy (test/target34.py);L" \
-    || echo "$output" | grep -q "Unwanted"
-    then
-      continue
-    fi
-    echo "       Output: OK"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Memory profiling"
-    run sudo src/austin -i 1000 -t 10000 -m $python_bin test/target34.py
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q "keep_cpu_busy (test/target34.py);L"
-    then
-      continue
-    fi
-    echo "       Output: OK"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Output file"
-    run sudo src/austin -i 10000 -t 10000 -o /tmp/austin_out.txt $python_bin test/target34.py
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q "Unwanted" \
-    || cat /tmp/austin_out.txt | grep -q "keep_cpu_busy (test/target34.py);L"
-    then
-      echo "       Output: OK"
-      return
-    fi
-  done
-
-  if [ $ignore ]
-  then
-    skip "Test failed but marked as 'Ignore'"
-  else
-    echo
-    echo "Collected Output"
-    echo "================"
-    echo
-    echo "$output"
-    echo
-    false
-  fi
-}
+    log "Fork [Python $version]"
 
+  # -------------------------------------------------------------------------
+  step "Standard profiling"
+  # -------------------------------------------------------------------------
+    run sudo $AUSTIN -i 1000 -t 10000 $python_bin test/target34.py
+
+    assert_success
+    assert_output "keep_cpu_busy (test/target34.py);L"
+    assert_not_output "Unwanted"
+
+  # -------------------------------------------------------------------------
+  step "Memory profiling"
+  # -------------------------------------------------------------------------
+    run sudo $AUSTIN -i 1000 -t 10000 -m $python_bin test/target34.py
+
+    assert_success
+    assert_output "keep_cpu_busy (test/target34.py);L"
+
+  # -------------------------------------------------------------------------
+  step "Output file"
+  # -------------------------------------------------------------------------
+    run sudo $AUSTIN -i 10000 -t 10000 -o /tmp/austin_out.txt $python_bin test/target34.py
+
+    assert_success
+    assert_output "Unwanted"
+    assert_not_output "keep_cpu_busy (test/target34.py);L"
+    assert_file "/tmp/austin_out.txt" "keep_cpu_busy (test/target34.py);L"
 
-# -----------------------------------------------------------------------------
+}
 
+# -----------------------------------------------------------------------------
 
 teardown() {
   if [ -f /tmp/austin_out.txt ]; then rm /tmp/austin_out.txt; fi
 }
 
 
-# @test "Test Austin with the default Python 3" {
-#   /usr/bin/python3 -m venv --copies --without-pip /tmp/py3
-#   source /tmp/py3/bin/activate
-# 	invoke_austin "python3"
-#   test -d /tmp/py3 && rm -rf /tmp/py3
-# }
+# -----------------------------------------------------------------------------
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with default Python 3 from Homebrew" {
-	invoke_austin "/usr/local/bin/python3"
+	repeat 3 invoke_austin "/usr/local/bin/python3"
 }
 
 @test "Test Austin with Python 3.8 from Homebrew (if available)" {
-  invoke_austin "/usr/local/opt/python@3.8/bin/python3" ignore
+  ignore
+  repeat 3 invoke_austin "/usr/local/opt/python@3.8/bin/python3"
 }
 
 @test "Test Austin with Python 3 from Anaconda (if available)" {
-  invoke_austin "/usr/local/anaconda3/bin/python" ignore
+  ignore
+  repeat 3 invoke_austin "/usr/local/anaconda3/bin/python"
 }
+
+# @test "Test Austin with the default Python 3" {
+#   /usr/bin/python3 -m venv --copies --without-pip /tmp/py3
+#   source /tmp/py3/bin/activate
+# 	invoke_austin "python3"
+#   test -d /tmp/py3 && rm -rf /tmp/py3
+# }
--- austin-1.0.1.orig/test/macos/test_fork_mp.bats
+++ austin-1.0.1/test/macos/test_fork_mp.bats
@@ -1,69 +1,72 @@
-invoke_austin() {
-  python_bin=$1
-  ignore=$2
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-  if ! $python_bin -V; then skip "$python_bin not found."; fi
+load "../common"
+
+
+function invoke_austin {
+  python_bin="${1}"
 
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
+  if ! $python_bin -V; then skip "$python_bin not found."; fi
 
-    # -------------------------------------------------------------------------
+  log "Fork Multi-processing [Python $version]"
 
-    echo "  :: Profiling of multi-process program"
-    run sudo src/austin -i 100000 -C $python_bin test/target_mp.py
+  # -------------------------------------------------------------------------
+  step "Profiling of multi-process program"
+  # -------------------------------------------------------------------------
+    run sudo $AUSTIN -i 100000 -C $python_bin test/target_mp.py
 
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
+    assert_success
 
-    echo "       - Check expected number of processes."
     expected=3
-    n_procs=$( echo "$output" | sed -E 's/Process ([0-9]+);.+/\1/' | sort | uniq | wc -l )
-    echo "         Expected at least $expected and got $n_procs"
-    if [ $n_procs -lt $expected ]; then continue; fi
-
-    echo "       - Check output contains frames."
-    if echo "$output" | grep -q "fact"
-    then
-      echo "       Output: OK"
-      return
-    fi
-    echo "       Output: NOK"
-  done
-
-  if [ $ignore ]
-  then
-    echo "Test marked as 'Ignore' failed"
-  fi
-  echo
-  echo "Collected Output"
-  echo "================"
-  echo
-  echo "$output"
-  echo
-  
-  false
-}
+    n_procs=$( echo "$output" | sed -E 's/P([0-9]+);.+/\1/' | sort | uniq | wc -l )
+    assert "At least 3 parallel processes" "$n_procs >= $expected"
 
+    assert_output "fact"
 
-# -----------------------------------------------------------------------------
+}
 
 
-# @test "Test Austin with the default Python 3" {
-#   /usr/bin/python3 -m venv /tmp/py3
-#   source /tmp/py3/bin/activate
-# 	invoke_austin "python3"
-#   test -d /tmp/py3 && rm -rf /tmp/py3
-# }
+# -----------------------------------------------------------------------------
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with default Python 3 from Homebrew" {
-	invoke_austin "/usr/local/bin/python3"
+	repeat 3 invoke_austin "/usr/local/bin/python3"
 }
 
 @test "Test Austin with Python 3.8 from Homebrew (if available)" {
-  invoke_austin "/usr/local/opt/python@3.8/bin/python3" ignore
+  ignore
+  repeat 3 invoke_austin "/usr/local/opt/python@3.8/bin/python3"
 }
 
 @test "Test Austin with Python 3 from Anaconda (if available)" {
-  invoke_austin "/usr/local/anaconda3/bin/python" ignore
-}
\ No newline at end of file
+  ignore
+  repeat 3 invoke_austin "/usr/local/anaconda3/bin/python"
+}
+
+# @test "Test Austin with the default Python 3" {
+#   /usr/bin/python3 -m venv /tmp/py3
+#   source /tmp/py3/bin/activate
+# 	invoke_austin "python3"
+#   test -d /tmp/py3 && rm -rf /tmp/py3
+# }
--- austin-1.0.1.orig/test/macos/test_valgrind.bats
+++ austin-1.0.1/test/macos/test_valgrind.bats
@@ -1,66 +1,80 @@
-invoke_austin() {
-  python_bin=$1
-  ignore=$2
-
-  if ! $python_bin -V; then skip "$python not found."; fi
-
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Valgrind test"
-    run sudo valgrind \
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "../common"
+
+
+function invoke_austin {
+  python_bin="${1}"
+
+  if ! $python_bin -V; then skip "$python_bin not found."; fi
+
+  log "Valgrind [Python $version]"
+
+  # -------------------------------------------------------------------------
+  step "Valgrind test"
+  # -------------------------------------------------------------------------
+    run valgrind \
       --error-exitcode=42 \
       --leak-check=full \
       --show-leak-kinds=all \
       --errors-for-leak-kinds=all \
       --track-fds=yes \
-      --track-origins=yes \
-      src/austin -i 100000 -t 10000 $python_bin test/target34.py
-    echo "       Exit code: $status"
-    echo "       Valgrind report: <"
-    echo "$output"
-  	if [ $status = 0 ]
+      $AUSTIN -i 100000 -t 10000 -o /dev/null $PYTHON test/target34.py
+
+    if [ ! $status == 0 ]
     then
-      return
+      log "       Valgrind Report"
+      log "       ==============="
+      for line in "${lines[@]}"
+      do
+        log "       $line"
+      done
+      check_ignored
     fi
-  done
-
-  if [ $ignore ]
-  then
-    echo "Test marked as 'Ignore' failed"
-  fi
-  echo
-  echo "Collected Output"
-  echo "================"
-  echo
-  echo "$output"
-  echo
-  
-  false
 }
 
 
 # -----------------------------------------------------------------------------
-
-
-# @test "Test Austin with the default Python 3" {
-#   /usr/bin/python3 -m venv /tmp/py3
-#   source /tmp/py3/bin/activate
-# 	invoke_austin "python3"
-#   test -d /tmp/py3 && rm -rf /tmp/py3
-# }
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with default Python 3 from Homebrew" {
-	invoke_austin "/usr/local/bin/python3"
+	repeat 3 invoke_austin "/usr/local/bin/python3"
 }
 
 @test "Test Austin with Python 3.8 from Homebrew (if available)" {
-  invoke_austin "/usr/local/opt/python@3.8/bin/python3" ignore
+  ignore
+  repeat 3 invoke_austin "/usr/local/opt/python@3.8/bin/python3"
 }
 
 @test "Test Austin with Python 3 from Anaconda (if available)" {
-  invoke_austin "/usr/local/anaconda3/bin/python" ignore
+  ignore
+  repeat 3 invoke_austin "/usr/local/anaconda3/bin/python"
 }
+
+# @test "Test Austin with the default Python 3" {
+#   /usr/bin/python3 -m venv /tmp/py3
+#   source /tmp/py3/bin/activate
+# 	invoke_austin "python3"
+#   test -d /tmp/py3 && rm -rf /tmp/py3
+# }
--- austin-1.0.1.orig/test/sleepy.py
+++ austin-1.0.1/test/sleepy.py
@@ -3,7 +3,7 @@
 # See file LICENCE or go to http://www.gnu.org/licenses/ for full license
 # details.
 #
-# Sibilla is a Python ORM for the Oracle Database.
+# Austin is a Python frame stack sampler for CPython.
 #
 # Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
 # All rights reserved.
@@ -25,11 +25,11 @@ import time
 
 def cpu_bound():
     a = []
-    for i in range(100000):
+    for i in range(1000000):
         a.append(i)
 
 
 if __name__ == "__main__":
     for n in range(2):
         cpu_bound()
-        time.sleep(1)
+        time.sleep(.7)
--- austin-1.0.1.orig/test/target.py
+++ austin-1.0.1/test/target.py
@@ -5,7 +5,7 @@
 # See file LICENCE or go to http://www.gnu.org/licenses/ for full license
 # details.
 #
-# Sibilla is a Python ORM for the Oracle Database.
+# Austin is a Python frame stack sampler for CPython.
 #
 # Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
 # All rights reserved.
--- austin-1.0.1.orig/test/target34.py
+++ austin-1.0.1/test/target34.py
@@ -5,7 +5,7 @@
 # See file LICENCE or go to http://www.gnu.org/licenses/ for full license
 # details.
 #
-# Sibilla is a Python ORM for the Oracle Database.
+# Austin is a Python frame stack sampler for CPython.
 #
 # Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
 # All rights reserved.
@@ -29,7 +29,7 @@ def keep_cpu_busy():
     a = []
     for i in range(2000000):
         a.append(i)
-        if i % 100000 == 0:
+        if i % 1000000 == 0:
             print("Unwanted output " + str(i))
 
 
--- austin-1.0.1.orig/test/target_mp.py
+++ austin-1.0.1/test/target_mp.py
@@ -3,7 +3,7 @@
 # See file LICENCE or go to http://www.gnu.org/licenses/ for full license
 # details.
 #
-# Sibilla is a Python ORM for the Oracle Database.
+# Austin is a Python frame stack sampler for CPython.
 #
 # Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
 # All rights reserved.
--- austin-1.0.1.orig/test/test.bats
+++ austin-1.0.1/test/test.bats
@@ -1,9 +1,30 @@
-#!/usr/bin/env bats
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "common"
+
 
 test_case() {
   run bats test/test_$1.bats
-  echo "$output"
-  [ $status = 0 ]
 }
 
 @test "Test Austin: fork" {
@@ -22,5 +43,6 @@ test_case() {
 }
 
 @test "Test Austin: valgrind" {
+  ignore
   test_case valgrind
 }
--- austin-1.0.1.orig/test/test_attach.bats
+++ austin-1.0.1/test/test_attach.bats
@@ -1,149 +1,94 @@
-attach_austin_2_3() {
-  if ! python$1 -V; then skip "Python $1 not found."; fi
-
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Standard profiling"
-    python$1 test/sleepy.py &
-    sleep 1
-    run src/austin -i 100000 -t 10000 -p $!
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q ";? (test/sleepy.py);L[[:digit:]]* "
-    then
-      continue
-    fi
-    echo "       Output: OK"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Memory profiling"
-    python$1 test/sleepy.py &
-    sleep 1
-    run src/austin -mi 100 -t 10000 -p $!
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if echo "$output" | grep -q "cpu_bound"
-    then
-      echo "       Output: OK"
-      return
-    fi
-  done
-
-  if [ $2 ]
-  then
-    skip "Test failed but marked as 'Ignore'"
-  else
-    echo
-    echo "Collected Output"
-    echo "================"
-    echo
-    echo "$output"
-    echo
-    false
-  fi
-}
-
-attach_austin() {
-  if ! python$1 -V; then skip "Python $1 not found."; fi
-
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Standard profiling"
-    python$1 test/sleepy.py &
-    sleep 1
-    run src/austin -i 10000 -t 10000 -p $!
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q ";<module> (test/sleepy.py);L[[:digit:]]* "
-    then
-      continue
-    fi
-    echo "       Output: OK"
-
-    # -------------------------------------------------------------------------
-
-    python$1 test/sleepy.py &
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "common"
+
+
+function attach_austin {
+  local version="${1}"
+
+  check_python $version
+
+  log "Attach [Python $version]"
+
+  # -------------------------------------------------------------------------
+  step "Standard profiling"
+  # -------------------------------------------------------------------------
+    $PYTHON test/sleepy.py &
     sleep 1
-    run src/austin -mi 100 -t 10000 -p $!
+    run $AUSTIN -i 100 -t 100 -p $!
 
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
+    assert_success
+    assert_output "(test/sleepy.py);L[[:digit:]]* "
 
-    if echo "$output" | grep -q "cpu_bound"
-    then
-      echo "       Output: OK"
-      return
-    fi
-  done
-
-  if [ $2 ]
-  then
-    skip "Test failed but marked as 'Ignore'"
-  else
-    echo "$output"
-    false
-  fi
 }
 
 
 # -----------------------------------------------------------------------------
-
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with Python 2.3" {
-	attach_austin_2_3 "2.3" ignore
+  ignore
+	repeat 3 attach_austin "2.3"
 }
 
 @test "Test Austin with Python 2.4" {
-	attach_austin_2_3 "2.4" ignore
+  ignore
+	repeat 3 attach_austin "2.4"
 }
 
 @test "Test Austin with Python 2.5" {
-	attach_austin "2.5"
+	repeat 3 attach_austin "2.5"
 }
 
 @test "Test Austin with Python 2.6" {
-	attach_austin "2.6"
+	repeat 3 attach_austin "2.6"
 }
 
 @test "Test Austin with Python 2.7" {
-	attach_austin "2.7"
+	repeat 3 attach_austin "2.7"
 }
 
 @test "Test Austin with Python 3.3" {
-	attach_austin "3.3"
+	repeat 3 attach_austin "3.3"
 }
 
 @test "Test Austin with Python 3.4" {
-	attach_austin "3.4"
+	repeat 3 attach_austin "3.4"
 }
 
 @test "Test Austin with Python 3.5" {
-	attach_austin "3.5"
+	repeat 3 attach_austin "3.5"
 }
 
 @test "Test Austin with Python 3.6" {
-  attach_austin "3.6"
+  repeat 3 attach_austin "3.6"
 }
 
 @test "Test Austin with Python 3.7" {
-  attach_austin "3.7"
+  repeat 3 attach_austin "3.7"
 }
 
 @test "Test Austin with Python 3.8" {
-  attach_austin "3.8"
+  repeat 3 attach_austin "3.8"
 }
--- austin-1.0.1.orig/test/test_fork.bats
+++ austin-1.0.1/test/test_fork.bats
@@ -1,120 +1,117 @@
-#!/usr/bin/env bats
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "common"
+
+
+function invoke_austin {
+  local version="${1}"
+
+  check_python $version
+
+  log "Fork [Python $version]"
+
+  # -------------------------------------------------------------------------
+  step "Standard profiling"
+  # -------------------------------------------------------------------------
+    run $AUSTIN -i 1000 -t 10000 $PYTHON test/target34.py
+
+    assert_success
+    assert_output "keep_cpu_busy (test/target34.py);L"
+    assert_not_output "Unwanted"
+
+  # -------------------------------------------------------------------------
+  step "Memory profiling"
+  # -------------------------------------------------------------------------
+    run $AUSTIN -i 1000 -t 10000 -m $PYTHON test/target34.py
+
+    assert_success
+    assert_output "keep_cpu_busy (test/target34.py);L"
+
+  # -------------------------------------------------------------------------
+  step "Output file"
+  # -------------------------------------------------------------------------
+    run $AUSTIN -i 10000 -t 10000 -o /tmp/austin_out.txt $PYTHON test/target34.py
+
+    assert_success
+    assert_output "Unwanted"
+    assert_not_output "keep_cpu_busy (test/target34.py);L"
+    assert_file "/tmp/austin_out.txt" "keep_cpu_busy (test/target34.py);L"
 
-invoke_austin() {
-  if ! python$1 -V; then skip "Python $1 not found."; fi
-
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Standard profiling"
-    run src/austin -i 1000 -t 10000 python$1 test/target34.py
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q "keep_cpu_busy (test/target34.py);L" \
-    || echo "$output" | grep -q "Unwanted"
-    then
-      continue
-    fi
-    echo "       Output: OK"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Memory profiling"
-    run src/austin -i 1000 -t 10000 -m python$1 test/target34.py
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q "keep_cpu_busy (test/target34.py);L"
-    then
-      continue
-    fi
-    echo "       Output: OK"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Output file"
-    run src/austin -i 10000 -t 10000 -o /tmp/austin_out.txt python$1 test/target34.py
-
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
-
-    if ! echo "$output" | grep -q "Unwanted" \
-    || cat /tmp/austin_out.txt | grep -q "keep_cpu_busy (test/target34.py);L"
-    then
-      echo "       Output: OK"
-      return
-    fi
-  done
-
-  if [ $2 ]
-  then
-    skip "Test failed but marked as 'Ignore'"
-  else
-    echo
-    echo "Collected Output"
-    echo "================"
-    echo
-    echo "$output"
-    echo
-    false
-  fi
 }
 
-
 # -----------------------------------------------------------------------------
 
-
-teardown() {
+function teardown {
   if [ -f /tmp/austin_out.txt ]; then rm /tmp/austin_out.txt; fi
 }
 
 
+# -----------------------------------------------------------------------------
+# -- Test Cases
+# -----------------------------------------------------------------------------
+
 @test "Test Austin with Python 2.3" {
-	invoke_austin "2.3" ignore
+  ignore
+	repeat 3 invoke_austin "2.3"
 }
 
 @test "Test Austin with Python 2.4" {
-	invoke_austin "2.4" ignore
+  ignore
+	repeat 3 invoke_austin "2.4"
 }
 
 @test "Test Austin with Python 2.5" {
-	invoke_austin "2.5"
+	repeat 3 invoke_austin "2.5"
 }
 
 @test "Test Austin with Python 2.6" {
-	invoke_austin "2.6"
+	repeat 3 invoke_austin "2.6"
 }
 
 @test "Test Austin with Python 2.7" {
-	invoke_austin "2.7"
+	repeat 3 invoke_austin "2.7"
 }
 
 @test "Test Austin with Python 3.3" {
-	invoke_austin "3.3"
+	repeat 3 invoke_austin "3.3"
 }
 
 @test "Test Austin with Python 3.4" {
-	invoke_austin "3.4"
+	repeat 3 invoke_austin "3.4"
 }
 
 @test "Test Austin with Python 3.5" {
-	invoke_austin "3.5"
+	repeat 3 invoke_austin "3.5"
 }
 
 @test "Test Austin with Python 3.6" {
-  invoke_austin "3.6"
+  repeat 3 invoke_austin "3.6"
 }
 
 @test "Test Austin with Python 3.7" {
-  invoke_austin "3.7"
+  repeat 3 invoke_austin "3.7"
 }
 
 @test "Test Austin with Python 3.8" {
-  invoke_austin "3.8"
+  repeat 3 invoke_austin "3.8"
 }
--- austin-1.0.1.orig/test/test_fork_mp.bats
+++ austin-1.0.1/test/test_fork_mp.bats
@@ -1,95 +1,98 @@
-#!/usr/bin/env bats
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "common"
+
+
+function invoke_austin {
+  local version="${1}"
+
+  check_python $version
+
+  log "Fork Multi-processing [Python $version]"
+
+  # -------------------------------------------------------------------------
+  step "Profiling of multi-process program"
+  # -------------------------------------------------------------------------
+    run $AUSTIN -i 10000 -C $PYTHON test/target_mp.py
 
-invoke_austin() {
-  if ! python$1 -V; then skip "Python $1 not found."; fi
+    assert_success
 
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Profiling of multi-process program"
-    run src/austin -i 10000 -C python$1 test/target_mp.py
+    expected=3
+    n_procs=$( echo "$output" | sed -r 's/P([0-9]+);.+/\1/' | sort | uniq | wc -l )
+    assert "At least 3 parallel processes" "$n_procs >= $expected"
 
-    echo "       Exit code: $status"
-    if [ $status != 0 ]; then continue; fi
+    assert_output "do (test/target_mp.py);L[[:digit:]]*;fact (test/target_mp.py);L"
 
-    echo "       - Check expected number of processes."
-    expected=3
-    n_procs=$( echo "$output" | sed -r 's/Process ([0-9]+);.+/\1/' | sort | uniq | wc -l )
-    echo "         Expected at least $expected and got $n_procs"
-    if [ $n_procs < $expected ]; then continue; fi
-
-    echo "       - Check output contains frames."
-    if echo "$output" | grep -q "do (test/target_mp.py);L[[:digit:]]*;fact (test/target_mp.py);L"
-    then
-      echo "       Output: OK"
-      return
-    fi
-  done
-
-  if [ $2 ]
-  then
-    skip "Test failed but marked as 'Ignore'"
-  else
-    echo
-    echo "Collected Output"
-    echo "================"
-    echo
-    echo "$output"
-    echo
-    false
-  fi
 }
 
 
 # -----------------------------------------------------------------------------
-
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with Python 2.3" {
   skip "Multiprocessing library introduced in Python 2.6"
-	invoke_austin "2.3"
+	repeat 3 invoke_austin "2.3"
 }
 
 @test "Test Austin with Python 2.4" {
   skip "Multiprocessing library introduced in Python 2.6"
-	invoke_austin "2.4"
+	repeat 3 invoke_austin "2.4"
 }
 
 @test "Test Austin with Python 2.5" {
   skip "Multiprocessing library introduced in Python 2.6"
-	invoke_austin "2.5"
+	repeat 3 invoke_austin "2.5"
 }
 
 @test "Test Austin with Python 2.6" {
-	invoke_austin "2.6"
+	repeat 3 invoke_austin "2.6"
 }
 
 @test "Test Austin with Python 2.7" {
-	invoke_austin "2.7"
+	repeat 3 invoke_austin "2.7"
 }
 
 @test "Test Austin with Python 3.3" {
-	invoke_austin "3.3"
+	repeat 3 invoke_austin "3.3"
 }
 
 @test "Test Austin with Python 3.4" {
-	invoke_austin "3.4"
+	repeat 3 invoke_austin "3.4"
 }
 
 @test "Test Austin with Python 3.5" {
-	invoke_austin "3.5"
+	repeat 3 invoke_austin "3.5"
 }
 
 @test "Test Austin with Python 3.6" {
-  invoke_austin "3.6"
+  repeat 3 invoke_austin "3.6"
 }
 
 @test "Test Austin with Python 3.7" {
-  invoke_austin "3.7"
+  repeat 3 invoke_austin "3.7"
 }
 
 @test "Test Austin with Python 3.8" {
-  invoke_austin "3.8"
+  repeat 3 invoke_austin "3.8"
 }
--- austin-1.0.1.orig/test/test_valgrind.bats
+++ austin-1.0.1/test/test_valgrind.bats
@@ -1,89 +1,105 @@
-#!/usr/bin/env bats
-
-invoke_austin() {
-  if ! python$1 -V; then skip "Python $1 not found."; fi
-
-  for i in {1..3}
-  do
-    echo "> Run $i of 3"
-
-    # -------------------------------------------------------------------------
-
-    echo "  :: Valgrind test"
+# This file is part of "austin" which is released under GPL.
+#
+# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
+# details.
+#
+# Austin is a Python frame stack sampler for CPython.
+#
+# Copyright (c) 2019 Gabriele N. Tornetta <phoenix1987@gmail.com>.
+# All rights reserved.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load "common"
+
+
+function invoke_austin {
+  local version="${1}"
+
+  check_python $version
+
+  log "Valgrind [Python $version]"
+
+  # -------------------------------------------------------------------------
+  step "Valgrind test"
+  # -------------------------------------------------------------------------
     run valgrind \
       --error-exitcode=42 \
       --leak-check=full \
       --show-leak-kinds=all \
       --errors-for-leak-kinds=all \
       --track-fds=yes \
-      src/austin -i 100000 -t 10000 python$1 test/target34.py
-    echo "       Exit code: $status"
-    echo "       Valgrind report: <"
-    echo "$output"
-  	if [ $status = 0 ]
+      $AUSTIN -i 100000 -t 10000 -o /dev/null $PYTHON test/target34.py
+
+    if [ ! $status == 0 ]
     then
-      return
+      log "       Valgrind Report"
+      log "       ==============="
+      for line in "${lines[@]}"
+      do
+        log "       $line"
+      done
+      check_ignored
     fi
-  done
-
-  if [ $2 ]
-  then
-    skip "Test failed but marked as 'Ignore'"
-  else
-    echo
-    echo "Collected Output"
-    echo "================"
-    echo
-    echo "$output"
-    echo
-    false
-  fi
 }
 
 
 # -----------------------------------------------------------------------------
-
+# -- Test Cases
+# -----------------------------------------------------------------------------
 
 @test "Test Austin with Python 2.3" {
-	invoke_austin "2.3" ignore
+  ignore
+	repeat 3 invoke_austin "2.3"
 }
 
 @test "Test Austin with Python 2.4" {
-	invoke_austin "2.4" ignore
+  ignore
+	repeat 3 invoke_austin "2.4"
 }
 
 @test "Test Austin with Python 2.5" {
-	invoke_austin "2.5"
+	repeat 3 invoke_austin "2.5"
 }
 
 @test "Test Austin with Python 2.6" {
-	invoke_austin "2.6"
+	repeat 3 invoke_austin "2.6"
 }
 
 @test "Test Austin with Python 2.7" {
-	invoke_austin "2.7"
+	repeat 3 invoke_austin "2.7"
 }
 
 @test "Test Austin with Python 3.3" {
-	invoke_austin "3.3"
+	repeat 3 invoke_austin "3.3"
 }
 
 @test "Test Austin with Python 3.4" {
-	invoke_austin "3.4"
+	repeat 3 invoke_austin "3.4"
 }
 
 @test "Test Austin with Python 3.5" {
-	invoke_austin "3.5"
+	repeat 3 invoke_austin "3.5"
 }
 
 @test "Test Austin with Python 3.6" {
-  invoke_austin "3.6"
+  repeat 3 invoke_austin "3.6"
 }
 
 @test "Test Austin with Python 3.7" {
-  invoke_austin "3.7"
+  repeat 3 invoke_austin "3.7"
 }
 
 @test "Test Austin with Python 3.8" {
-  invoke_austin "3.8"
+  repeat 3 invoke_austin "3.8"
 }
