#!/bin/bash
#
# Copyright (C) 2012-2015 SUSE Linux GmbH
#
# Author:
# Frank Sundermeyer <fsundermeyer at opensuse dot org>
#
# Testing DAPS: profiling
#
# * Is the profiling command successfully executed?
# * Is the profiling directory created?
# * Does the profiling directory contain all files?
#   - Does it contain files not belonging to the set?
# * Have the entities been resolved?
# * Does the profiled XML validate?
# * Is a file that has changed since last profiling updated?
#   - Have files that not have been modified been updated?
# * Are all files updated when entity-decl.ent has changed?
# * In case the XML sources contain a profiling urn:
#   - Does the XML contain the correct content?

_PROFILEDIR=""

source lib/common_functions

if [[ 0 -eq $_NOPROFILE ]]; then
    header "Profiling with profile URN"
else
    header "Profiling without profile URN"
fi

# ---------
# Test Setup
#

# Initiate
# this function is run _before_ the tests are executed
#
function oneTimeSetUp() {
    # Clean up the build directory
    clean_build_dir all
    # get the profiling directory
    _PROFILEDIR=$($_DAPSEXEC --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR 2>/dev/null)
    if [ $? -ne 0 ]; then
	exit_on_error " The initial DAPS call to determine the profiling directory failed. Skipping profiling tests"
    fi
}

# Post
# this function is run _after_ the tests are executed
#
function oneTimeTearDown() {
    stats
    # Clean up the build directory
    clean_build_dir all
}

#---------------------------------------------------------------
# TESTS
#---------------------------------------------------------------

#--------------------------------
# Is the profiling command successfully executed?
#
function test_profiling () {
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile >/dev/null 2>&1
    assertTrue \
        ' └─ The profiling command itself failed' \
        "$?"
}

#--------------------------------
# Is the profiling directory created?
#
function test_profilingPROFILEDIR () {
    assertTrue \
        " └─ The profiling directory '$_PROFILEDIR' does not exist" \
        "[ -d $_PROFILEDIR ]"
}

#--------------------------------
# Does the profiling directory contain all files?
# Does it contain files not belonging to the set?
#
function test_profilingFilelist () {
    local _FILE _MISSING
    for _FILE in $_PROF_SET_FILES; do
        [[ -f "${_PROFILEDIR}/$_FILE" ]] || _MISSING="$_MISSING $_FILE"
    done
    assertNull \
        " └─ File(s) '$_MISSING' is/are missing $_PROFILEDIR" \
        "$_MISSING"
    # $_NO_SET_FILE is not part of the set and therefore must not
    # be profiled
    assertFalse \
        "$_NO_SET_FILE, which is not part of the set has been profiled" \
        '[ -f ${_PROFILEDIR}/$_NO_SET_FILE ]'
}

#--------------------------------
# Have the entities been resolved?
#
function test_profilingEntities () {
    egrep -q "&ent[0-9];" ${_PROFILEDIR}/*.xml 2>/dev/null
    assertFalse \
        ' └─ Not all entities have been resolved' \
        "$?"
}

#--------------------------------
# Does the profiled XML validate?
#
function test_profilingValidate() {
    xmllint --noent --postvalid --noout --nowarning --xinclude \
        ${_PROFILEDIR}/$(basename $_MAIN_PROFILING) >/dev/null 2>&1
    assertTrue \
        ' └─ Profiled XML does not validate' \
        "$?"
}

#--------------------------------
# Is a file that has changed since last profiling updated?
# Have files that not have been modified been updated?
#
function test_profilingUpdateXML() {
    local _FILE _OLDDATE_FILES _OLDDATE_MAIN _NEWDATE_FILES _NEWDATE_MAIN
    # get date for $MAIN from profiling dir (unix timestamp)
    _OLDDATE_MAIN=$(stat -c %Y ${_PROFILEDIR}/$(basename $_MAIN_PROFILING) 2>/dev/null)
    # "update" $MAIN
    sleep 1
    touch $_MAIN_PROFILING
    # the timestamps of the other files should not have changed
    # because they haven't been updated and therefor do not need to be
    # profiled again. In order to keep the test as simple as possible, we
    # add the timestamps of all other files
    _OLDDATE_FILES=0
    _NEWDATE_FILES=0
    for _FILE in $_PROF_SET_FILES; do
        if [[ $_FILE == $(basename $_MAIN_PROFILING) ]]; then continue; fi
        _OLDDATE_FILES=$(expr $_OLDDATE_FILES + $(stat -c %Y ${_PROFILEDIR}/$_FILE 2>/dev/null))
    done
    # rerun profiling
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile >/dev/null 2>&1
    assertTrue \
        " └─ Re-running profiling after touching $_MAIN_PROFILING failed" \
        "$?"
    # get new date
    _NEWDATE_MAIN=$(stat -c %Y ${_PROFILEDIR}/$(basename $_MAIN_PROFILING) 2>/dev/null)
    assertNotEquals \
        ' └─ $MAIN has not been updated by profiling although it had changed' \
        "$_OLDDATE_MAIN" "$_NEWDATE_MAIN"
    for _FILE in $_PROF_SET_FILES; do
        if [[ $_FILE == $(basename $_MAIN_PROFILING) ]]; then continue; fi
        _NEWDATE_FILES=$(expr $_NEWDATE_FILES + $(stat -c %Y ${_PROFILEDIR}/$_FILE 2>/dev/null))
    done
    assertEquals \
        ' └─  Files have been updated although they did not change' \
        "$_OLDDATE_FILES" "$_NEWDATE_FILES"
}

#--------------------------------
# Are all files updated when entity-decl.ent has changed?
#
function test_profilingUpdateEntities() {
    local _FILE
    declare -A _OLD_FILEDATES _NEW_FILEDATES
    for _FILE in $_PROF_SET_FILES; do
	_OLD_FILEDATES[$_FILE]=$(stat -c %Y ${_PROFILEDIR}/$_FILE 2>/dev/null)
    done
    sleep 1
    # update Entity declaration files
    touch ${_DOC_DIR}/xml/*.ent
    # rerun profiling
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile >/dev/null
    for _FILE in $_PROF_SET_FILES; do
	_NEW_FILEDATES[$_FILE]=$(stat -c %Y ${_PROFILEDIR}/$_FILE 2>/dev/null)
	assertNotEquals \
	    " └─  File $_FILE has not been updated although the entities changed:" \
        "${_OLD_FILEDATES[$_FILE]}" "${_NEW_FILEDATES[$_FILE]}"
    done
}

#--------------------------------
# Is the content correctly profiled?
#
function test_profilingContent () {
    local _COUNT _PROFILEDIR

    # skip tests if MAIN does not contain a profiling URN
    [[ 1 -eq $_NOPROFILE ]] && startSkipping

    # First test: no profiled paras should appear in the profiled XML
    #             because no profiling attributes are set
    clean_build_dir profiles
    _PROFILEDIR=$($_DAPSEXEC -v0 --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR)
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile >/dev/null 2>&1
    _COUNT=$(egrep "(arch|condition|os|vendor)=(arch|condition|os|vendor)[12]" \
        ${_PROFILEDIR}/*.xml 2>/dev/null | wc -l)
    assertEquals \
        ' └─ Content has been filtered from XML although no profiling attribute was set' \
        "$_COUNT" "8"

    # Second test: no profiled paras should appear in the profiled XML
    #              because profiling parameters have been set to a value that
    #              has no match in the XML
    clean_build_dir profiles
    _PROFILEDIR=$($_DAPSEXEC -v0 --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR PROFARCH=foo PROFCONDITION=foo PROFOS=foo PROFVENDOR=foo)
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile PROFARCH=foo PROFCONDITION=foo PROFOS=foo PROFVENDOR=foo >/dev/null 2>&1
    egrep "(arch|condition|os|vendor)=(arch|condition|os|vendor)[12]" \
        ${_PROFILEDIR}/*.xml >/dev/null 2>&1
    assertFalse \
        ' └─ Profiled XML contains content that should have been filtered (all profiling variables have been set to a value that has no match in the XML)' \
        "$?"

    # Third test: arch2 should be filtered out
    #
    clean_build_dir profiles
    _PROFILEDIR=$($_DAPSEXEC -v0 --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR PROFARCH=arch1)
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile PROFARCH=arch1 >/dev/null
    grep -q "arch=arch2" ${_PROFILEDIR}/*.xml 2>/dev/null
    assertFalse \
        ' └─ Profiled XML contains arch2 content that should have been filtered' \
        "$?"

    # Fourth test: condition1 should be filtered out
    #
    clean_build_dir profiles
    _PROFILEDIR=$($_DAPSEXEC -v0 --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR PROFCONDITION=condition2)
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile PROFCONDITION=condition2 >/dev/null
    grep -q "condition=condition1" ${_PROFILEDIR}/*.xml 2>/dev/null
    assertFalse \
        ' └─ Profiled XML contains condition1 content that should have been filtered' \
        "$?"

    # Fifth test: os2 should be filtered out
    #
    clean_build_dir profiles
    _PROFILEDIR=$($_DAPSEXEC -v0 --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR PROFOS=os1)
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile PROFOS=os1 >/dev/null
    grep -q "os=os2" ${_PROFILEDIR}/*.xml 2>/dev/null
    assertFalse \
        ' └─ Profiled XML contains os2 content that should have been filtered' \
        "$?"

    # Sixth test: vendor1 should be filtered out
    #
    clean_build_dir profiles
    _PROFILEDIR=$($_DAPSEXEC -v0 --main $_MAIN_PROFILING showvariable VARIABLE=PROFILEDIR PROFVENDOR=vendor2)
    $_DAPSEXEC -v0 --main $_MAIN_PROFILING profile PROFVENDOR=vendor2 >/dev/null
    grep -q "vendor=vendor1" ${_PROFILEDIR}/*.xml 2>/dev/null
    assertFalse \
        ' └─ Profiled XML contains vendor1 content that should have been filtered' \
        "$?"
}

# source shUnit2 test
source $_SHUNIT2SRC
