...

Text file src/k8s.io/kubernetes/third_party/forked/shell2junit/sh2ju.sh

Documentation: k8s.io/kubernetes/third_party/forked/shell2junit

     1#!/usr/bin/env bash
     2### Copyright 2010 Manuel Carrasco MoƱino. (manolo at apache.org)
     3###
     4### Licensed under the Apache License, Version 2.0.
     5### You may obtain a copy of it at
     6### http://www.apache.org/licenses/LICENSE-2.0
     7
     8###
     9### A library for shell scripts which creates reports in jUnit format.
    10### These reports can be used in Jenkins, or any other CI.
    11###
    12### Usage:
    13###     - Include this file in your shell script
    14###     - Use juLog to call your command any time you want to produce a new report
    15###        Usage:   juLog <options> command arguments
    16###           options:
    17###             -class="MyClass" : a class name which will be shown in the junit report
    18###             -name="TestName" : the test name which will be shown in the junit report
    19###             -error="RegExp"  : a regexp which sets the test as failure when the output matches it
    20###             -ierror="RegExp" : same as -error but case insensitive
    21###             -fail="RegExp"   : Any line from stderr which contains this pattern becomes part of
    22###                                the failure messsage, without the text matching that pattern.
    23###                                Example: -failure="^ERROR: "
    24###                                Default is to use the entire stderr as failure message.
    25###             -output="Path"   : path to output directory, defaults to "./results"
    26###     - Junit reports are left in the folder 'result' under the directory where the script is executed.
    27###     - Configure Jenkins to parse junit files from the generated folder
    28###
    29
    30asserts=00; errors=0; total=0; content=""
    31date="$(which gdate 2>/dev/null || which date)"
    32
    33# default output folder
    34juDIR="$(pwd)/results"
    35
    36# The name of the suite is calculated based in your script name
    37suite=""
    38
    39if LANG=C sed --help 2>&1 | grep -q GNU; then
    40  SED="sed"
    41elif which gsed &>/dev/null; then
    42  SED="gsed"
    43else
    44  echo "Failed to find GNU sed as sed or gsed. If you are on Mac: brew install gnu-sed." >&2
    45  exit 1
    46fi
    47
    48# A wrapper for the eval method witch allows catching seg-faults and use tee
    49errfile=/tmp/evErr.$$.log
    50function eVal() {
    51  (eval "$1")
    52  # stdout and stderr may currently be inverted (see below) so echo may write to stderr
    53  echo "$?" 2>&1 | tr -d "\n" > "${errfile}"
    54}
    55
    56# Method to clean old tests
    57function juLogClean() {
    58  echo "+++ Removing old junit reports from: ${juDIR} "
    59  rm -f "${juDIR}"/junit-*
    60}
    61
    62# Execute a command and record its results
    63function juLog() {
    64  suite="";
    65  errfile=/tmp/evErr.$$.log
    66  date="$(which gdate 2>/dev/null || which date)"
    67  asserts=00; errors=0; total=0; content=""
    68  local failureRe=""
    69
    70  # parse arguments
    71  ya=""; icase=""
    72  while [[ -z "$ya" ]]; do
    73    case "$1" in
    74      -name=*)   name="$(echo "$1" | ${SED} -e 's/-name=//')";   shift;;
    75      -class=*)  class="$(echo "$1" | ${SED} -e 's/-class=//')";   shift;;
    76      -ierror=*) ereg="$(echo "$1" | ${SED} -e 's/-ierror=//')"; icase="-i"; shift;;
    77      -error=*)  ereg="$(echo "$1" | ${SED} -e 's/-error=//')";  shift;;
    78      -fail=*)  failureRe="$(echo "$1" | ${SED} -e 's/-fail=//')";  shift;;
    79      -output=*) juDIR="$(echo "$1" | ${SED} -e 's/-output=//')";  shift;;
    80      *)         ya=1;;
    81    esac
    82  done
    83
    84  # create output directory
    85  mkdir -p "${juDIR}" || exit
    86  # use first arg as name if it was not given
    87  if [[ -z "${name}" ]]; then
    88    name="${asserts}-$1"
    89    shift
    90  fi
    91
    92  if [[ "${class}" = "" ]]; then
    93    class="default"
    94  fi
    95
    96  suite=${class}
    97
    98  # calculate command to eval
    99  [[ -z "$1" ]] && return
   100  cmd="$1"; shift
   101  while [[ -n "${1:-}" ]]
   102  do
   103     cmd="${cmd} \"$1\""
   104     shift
   105  done
   106
   107  # eval the command sending output to a file
   108  outf=/var/tmp/ju$$.txt
   109  errf=/var/tmp/ju$$-err.txt
   110  :>${outf}
   111  echo ""                         | tee -a ${outf}
   112  echo "+++ Running case: ${class}.${name} " | tee -a ${outf}
   113  echo "+++ working dir: $(pwd)"           | tee -a ${outf}
   114  echo "+++ command: ${cmd}"            | tee -a ${outf}
   115  ini="$(${date} +%s.%N)"
   116  # execute the command, temporarily swapping stderr and stdout so they can be tee'd to separate files,
   117  # then swapping them back again so that the streams are written correctly for the invoking process
   118  ( (eVal "${cmd}" | tee -a ${outf}) 3>&1 1>&2 2>&3 | tee ${errf}) 3>&1 1>&2 2>&3
   119  evErr="$(cat ${errfile})"
   120  rm -f ${errfile}
   121  end="$(${date} +%s.%N)"
   122  echo "+++ exit code: ${evErr}"        | tee -a ${outf}
   123
   124  # set the appropriate error, based in the exit code and the regex
   125  [[ ${evErr} -ne 0 ]] && err=1 || err=0
   126  out="$(${SED} -e 's/^\([^+]\)/| \1/g' "$outf")"
   127  if [ "${err}" -eq 0 ] && [ -n "${ereg:-}" ]; then
   128      H=$(echo "${out}" | grep -E ${icase} "${ereg}")
   129      [[ -n "${H}" ]] && err=1
   130  fi
   131  [[ ${err} -ne 0 ]] && echo "+++ error: ${err}"         | tee -a ${outf}
   132  rm -f ${outf}
   133
   134  errMsg=$(cat ${errf})
   135  rm -f ${errf}
   136  # calculate vars
   137  asserts=$((asserts+1))
   138  errors=$((errors+err))
   139  time=$(echo "${end} ${ini}" | awk '{print $1 - $2}')
   140  total=$(echo "${total} ${time}" | awk '{print $1 + $2}')
   141
   142  # write the junit xml report
   143  ## failure tag
   144  local failure=""
   145  if [[ ${err} -ne 0 ]]; then
   146      local failureMsg
   147      if [ -n "${failureRe}" ]; then
   148          failureMsg="$(echo "${errMsg}" | grep -e "${failureRe}" | ${SED} -e "s;${failureRe};;")"
   149          if [ -z "${failureMsg}" ]; then
   150              failureMsg="see stderr for details"
   151          fi
   152      else
   153          failureMsg="${errMsg}"
   154      fi
   155      failure="
   156      <failure type=\"ScriptError\"><![CDATA[
   157${failureMsg}
   158]]></failure>
   159  "
   160  fi
   161  ## testcase tag
   162  content="${content}
   163    <testcase assertions=\"1\" name=\"${name}\" time=\"${time}\" classname=\"${class}\">
   164    ${failure}
   165    <system-err><![CDATA[${errMsg}]]></system-err>
   166    </testcase>
   167  "
   168  ## testsuite block
   169
   170  if [[ -e "${juDIR}/junit_${suite}.xml" ]]; then
   171    # file exists. first update the failures count
   172    failCount=$(${SED} -n "s/.*testsuite.*failures=\"\([0-9]*\)\".*/\1/p" "${juDIR}/junit_${suite}.xml")
   173    errors=$((failCount+errors))
   174    ${SED} -i "0,/failures=\"${failCount}\"/ s/failures=\"${failCount}\"/failures=\"${errors}\"/" "${juDIR}/junit_${suite}.xml"
   175    ${SED} -i "0,/errors=\"${failCount}\"/ s/errors=\"${failCount}\"/errors=\"${errors}\"/" "${juDIR}/junit_${suite}.xml"
   176
   177    # file exists. Need to append to it. If we remove the testsuite end tag, we can just add it in after.
   178    ${SED} -i "s^</testsuite>^^g" "${juDIR}/junit_${suite}.xml" ## remove testSuite so we can add it later
   179    ${SED} -i "s^</testsuites>^^g" "${juDIR}/junit_${suite}.xml"
   180    cat <<EOF >> "$juDIR/junit_$suite.xml"
   181     ${content:-}
   182    </testsuite>
   183</testsuites>
   184EOF
   185
   186  else
   187    # no file exists. Adding a new file
   188    cat <<EOF > "${juDIR}/junit_${suite}.xml"
   189<?xml version="1.0" encoding="UTF-8"?>
   190<testsuites>
   191    <testsuite failures="${errors}" assertions="${assertions:-}" name="${suite}" tests="1" errors="${errors}" time="${total}">
   192    ${content:-}
   193    </testsuite>
   194</testsuites>
   195EOF
   196  fi
   197
   198  return "${err}"
   199}

View as plain text