#!/bin/sh

# Copyright (C) 1994-2016 Lawrence Livermore National Security, LLC.
# LLNL-CODE-425250.
# All rights reserved.
# 
# This file is part of Silo. For details, see silo.llnl.gov.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the disclaimer below.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the disclaimer (as noted
#      below) in the documentation and/or other materials provided with
#      the distribution.
#    * Neither the name of the LLNS/LLNL nor the names of its
#      contributors may be used to endorse or promote products derived
#      from this software without specific prior written permission.
# 
# THIS SOFTWARE  IS PROVIDED BY  THE COPYRIGHT HOLDERS  AND CONTRIBUTORS
# "AS  IS" AND  ANY EXPRESS  OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT
# LIMITED TO, THE IMPLIED  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A  PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN  NO  EVENT SHALL  LAWRENCE
# LIVERMORE  NATIONAL SECURITY, LLC,  THE U.S.  DEPARTMENT OF  ENERGY OR
# CONTRIBUTORS BE LIABLE FOR  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR  CONSEQUENTIAL DAMAGES  (INCLUDING, BUT NOT  LIMITED TO,
# PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS  OF USE,  DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER  IN CONTRACT, STRICT LIABILITY,  OR TORT (INCLUDING
# NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT  OF THE USE  OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 
# This work was produced at Lawrence Livermore National Laboratory under
# Contract  No.   DE-AC52-07NA27344 with  the  DOE.  Neither the  United
# States Government  nor Lawrence  Livermore National Security,  LLC nor
# any of  their employees,  makes any warranty,  express or  implied, or
# assumes   any   liability   or   responsibility  for   the   accuracy,
# completeness, or usefulness of any information, apparatus, product, or
# process  disclosed, or  represents  that its  use  would not  infringe
# privately-owned   rights.  Any  reference   herein  to   any  specific
# commercial products,  process, or  services by trade  name, trademark,
# manufacturer or otherwise does not necessarily constitute or imply its
# endorsement,  recommendation,   or  favoring  by   the  United  States
# Government or Lawrence Livermore National Security, LLC. The views and
# opinions  of authors  expressed  herein do  not  necessarily state  or
# reflect those  of the United  States Government or  Lawrence Livermore
# National  Security, LLC,  and shall  not  be used  for advertising  or
# product endorsement purposes.

# -----------------------------------------------------------------------------
# Test checksumming capability in silo by generating checksummed data
# file, copying it, corrupting the copy and then reading it with browser
# with and without checksumming turned enabled.
#
# Programmer: Mark C. Miller
# Creation:   February 20, 2007
#
# -----------------------------------------------------------------------------
#
# Find dir where this script lives and source the shell utils script there.
#
# dirname -- "$0" gets the script directory even if this script is run via a
#     relative path like ../../foo/bar/gorfo.sh.
# The CDPATH= nulls that env. variable and prevents cd from printing anything
#     if CDPATH is set in the environment.
# pwd gives the absolute path after the cd has occurred. This all happens in
#     a subshell so the cwd of the current script is unchanged.
#
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
. $script_dir/silo_sh_utils.sh

#
# Ensure the multi_test executable is available
#
multi_test=$(find_file -x tests/bin/multi_test tests/multi_test ./multi_test ../../multi_test)
[ $? -eq 0 ] || exit 1

#
# Ensure we have Silo's 'browser' tool available
#
browser=$(find_file -x bin/browser tools/browser/browser tools/browser/.libs/browser ../tools/browser/browser ../../../tools/browser/browser)
[ $? -eq 0 ] || exit 1

#
# Create data with checksums (only on HDF5 driver) and save files
#
rm -rf h5_check_files
mkdir h5_check_files
(cd h5_check_files; $multi_test DB_HDF5 check 1>/dev/null 2>&1)

#
# Determine the offset of an hdf5 dataset in the silo file.
# We do this because we can't indescriminently corrupt the file.
# Silo's checksumming is done only on the dataset raw data.
# So, we have to make sure that we corrupt the file somewhere within
# some dataset raw data. We're aiming to corrupt the raw data for
# the facelist object, "fl1" in block 2 in the file by using octal
# dump (od). First, we find a sequence of 4 integers associated with
# that data, 167, 179, 323, 311. 6 facelist objects in multi_ucd3d.h5
# contain this sequence; blocks 2, 11, 14, 23, 26 and 35. And, no other
# raw data contains this sequence. We use octal dump (od) and treat
# the *entire* contents of the file as type d4 (decimal, 4-byte ints)
# and then grep for the sequence of ints we know should exist in the
# file. But, this approach has two issues both having to do with the
# skip at which od begins to a) treat each sequence of 4 bytes as a
# decimal integer and b) treat each sequence of 4 such integers as a
# single line it outputs. In either case, the wrong skip can defeat
# grep logic. However, for the sequence of 4, 4-byte integers, there
# are only 16 unique skips we need to try before we either find a
# match or conclude none exists. So, we loop over successive skips 
# starting from 0 each 1 byte further down the file until we find what
# we're looking for. We then take the *minimum* offset we find as that
# will be associated with the first "fl1" object raw data written to
# the file for block 2.
#
minoffset=$(ls -l h5_check_files/multi_ucd3d.h5 | tr '[:blank:]' ' ' | tr -s ' ' | cut -d' ' -f5)
skip=0
while [ $skip -lt 16 ]; do
    offset=$(od -j $skip -A d -t d4 h5_check_files/multi_ucd3d.h5 | tr '[:blank:]' ' ' | tr -s ' ' | grep '167 179 323 311' | cut -d' ' -f1 | head -n 1)
    if [ -n "$offset" ] && [ $offset -lt $minoffset ]; then
        minoffset=$offset
    fi
    skip=$(expr $skip + 1)
done
size=$(ls -l h5_check_files/multi_ucd3d.h5 | tr -s ' ' | cut -d' ' -f5)

#
# Corrupt a checksumed file by splicing together the first
# part of the original file with the 4 integer (4 byte) zeros
# and the last part of the file (minus the part we've zeroed)
#
rm -f multi_ucd3d_corrupt.h5
head -c $minoffset h5_check_files/multi_ucd3d.h5 > multi_ucd3d_corrupt.h5
dd if=/dev/zero bs=16 count=1 >> multi_ucd3d_corrupt.h5 2>/dev/null
leftover=$(expr $size - $minoffset - 16)
tail -c $leftover h5_check_files/multi_ucd3d.h5 >> multi_ucd3d_corrupt.h5

#
# First, run browser with checksumming not turned on and make sure
# we just see the zero'd data we expect.
#
result=0
brOut=$($browser -q -e 'block2/fl1.nodelist[523:528]' multi_ucd3d_corrupt.h5)
if [ -z "$(echo $brOut | grep '{299, 0, 0, 0, 0, 179}')" ]; then
    result=1
fi

#
# Now, run browser with checksumming turned on and make sure we
# detect a checksumming error.
#
brOut=$($browser -q -c -e block2/fl1 multi_ucd3d_corrupt.h5 2>&1)
if [ -z "$(echo $brOut | grep 'Checksum failure')" ]; then
    result=1
fi

#
# Cleanup
#
rm -rf h5_check_files
rm -f multi_ucd3d_corrupt.h5

exit $result 
