//
// LDASTools frameCPP - A library implementing the LIGO/Virgo frame
// specification
//
// Copyright (C) 2018 California Institute of Technology
//
// LDASTools frameCPP is free software; you may redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 (GPLv2) of the
// License or at your discretion, any later version.
//
// LDASTools frameCPP is distributed in the hope that it will be useful, but
// without any warranty or even the implied warranty of merchantability
// or fitness for a particular purpose. See the GNU General Public
// License (GPLv2) for more details.
//
// Neither the names of the California Institute of Technology (Caltech),
// The Massachusetts Institute of Technology (M.I.T), The Laser
// Interferometer Gravitational-Wave Observatory (LIGO), nor the names
// of its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// You should have received a copy of the licensing terms for this
// software included in the file LICENSE located in the top-level
// directory of this package. If you did not, you can view a copy at
// http://dcc.ligo.org/M1500244/LICENSE
//

#define BOOST_TEST_MAIN
#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE
#include <boost/test/included/unit_test.hpp>

#include "ldastoolsal/Exec.hh"

using LDASTools::AL::Exec;

static const char* CMD_FRAMECPP_VERIFY = "./framecpp_verify";
static const char* CMD_FRAMECPP_DUMP_OBJECTS = "./framecpp_dump_objects";

#if WORKING || 1
BOOST_AUTO_TEST_CASE( test_pr3430 )
{
    try
    {
        Exec cmd( CMD_FRAMECPP_VERIFY, "--verbose", Exec::COMMAND_END );
        static int const EXPECTED_EXIT_CODE{ 12 };

        cmd.Spawn( );

        //-------------------------------------------------------------------
        // Look at what was written to standard out.
        //-------------------------------------------------------------------
        BOOST_TEST_MESSAGE( "PR3430 - usage error : exit status: "
                            << EXPECTED_EXIT_CODE
                            << " =?= " << cmd.ExitCode( ) );
        BOOST_CHECK( EXPECTED_EXIT_CODE == cmd.ExitCode( ) );
    }
    catch ( ... )
    {
        BOOST_TEST_MESSAGE( "failed because of exception being thrown" );
        BOOST_CHECK( false );
    }
}
#endif /* WORKING */

// Issue #287 — pre-4.0.x callers used `framecpp_verify --verbose <file>`
// (bare-flag form). Boost.program_options was greedily consuming the
// positional `.gwf` filename as the integer value for `--verbose`, returning
// the parse-error exit code 1. With the argv rewrite for bare `--verbose`,
// the verifier should now exit with a verifier status (file-related error or
// success), not exit code 1 from boost.
BOOST_AUTO_TEST_CASE( test_issue_287_verbose_bare_flag )
{
    try
    {
        Exec cmd( CMD_FRAMECPP_VERIFY,
                  "--verbose",
                  "nonexistent_file.gwf",
                  Exec::COMMAND_END );

        cmd.Spawn( );

        BOOST_TEST_MESSAGE( "issue #287 - bare --verbose <file> : exit status: "
                            << cmd.ExitCode( ) );
        // The fix means boost must no longer fail on `--verbose nonexistent.gwf`
        // with the boost parse-error exit code (1). Any other exit (file IO
        // error from the verifier, or 0 on a real file) is acceptable here.
        BOOST_CHECK( cmd.IfExited( ) && cmd.ExitCode( ) != 1 );
    }
    catch ( ... )
    {
        BOOST_TEST_MESSAGE( "failed because of exception being thrown" );
        BOOST_CHECK( false );
    }
}

#if WORKING || 1
BOOST_AUTO_TEST_CASE( test_pr3437 )
{
    //---------------------------------------------------------------------
    // Testing of PR 3437 - framecpp_verify fails on E1 data
    //---------------------------------------------------------------------
    const char* TEST_GWF_FILENAME =
        "/archive/frames/E1/L0/LHO/H-R-63891/H-R-638911999-1.gwf";

    std::ifstream gwf_existance( TEST_GWF_FILENAME );
    if ( gwf_existance.good( ) )
    {

        try
        {
            Exec cmd( CMD_FRAMECPP_VERIFY,
                      "--verbose",
                      "--force",
                      "--no-metadata-check",
                      "--relax-eof-checksum",
                      TEST_GWF_FILENAME,
                      Exec::COMMAND_END );

            cmd.Spawn( );

            BOOST_TEST_MESSAGE( "framecpp_verify reads E1 data from file "
                                << TEST_GWF_FILENAME << " ["
                                << " exit code: " << cmd.ExitCode( )
                                << " signal: " << cmd.Signal( )
                                << " core dump: " << cmd.CoreDump( ) << " ]" );
            BOOST_CHECK( cmd.IfExited( ) && ( cmd.ExitCode( ) == 0 ) );
        }
        catch ( ... )
        {
            BOOST_TEST_MESSAGE( "failed because of exception being thrown" );
            BOOST_CHECK( false );
        }
    }
}
#endif /* WORKING */

BOOST_AUTO_TEST_CASE( framecpp_dump_objects )
{
    static const char* cmd = CMD_FRAMECPP_DUMP_OBJECTS;

    Exec e( cmd, "--silent-data", cmd, Exec::COMMAND_END );

    e.Spawn( );
    BOOST_TEST_MESSAGE( "PR3439 - processing non-frame files"
                        << " ["
                        << " exit code: " << e.ExitCode( )
                        << " signal: " << e.Signal( )
                        << " core dump: " << e.CoreDump( ) << " ]" );
    BOOST_CHECK( e.IfExited( ) && ( e.ExitCode( ) != 0 ) );
}

BOOST_AUTO_TEST_CASE( test_time_trial )
{
    //---------------------------------------------------------------------
    // Verify that programs complete in a timely mannor.
    //---------------------------------------------------------------------
    const char* gwf = "Z-R_std_test_frame_ver8-600000000-1.gwf";
#define V 0
#define VC 0
#define V2 1
#if V
    Exec verify(
        "./framecpp_verify", "--checksum-file-only", gwf, Exec::COMMAND_END );
#endif /* 0 */
#if VC
    Exec verify_checksum( "./framecpp_verify_checksums",
                          "--no-checksum-structure",
                          "--no-checksum-frame",
                          gwf,
                          Exec::COMMAND_END );
#endif /* 0 */
#if V2
    Exec verify2(
        "./framecpp_verify", "--checksum-file-only", gwf, Exec::COMMAND_END );
#endif /* 0 */

#if V
    verify.Spawn( );
#endif /* 0 */
#if VC
    verify_checksum.Spawn( );
#endif /* 0 */
#if V2
    verify2.Spawn( );
#endif /* 0 */

#if V
    BOOST_TEST_MESSAGE( verify.Command( ) );
#endif /* 0 */
#if VC
    BOOST_TEST_MESSAGE( verify_checksum.Command );
#endif /* 0 */
#if V
    BOOST_TEST_MESSAGE( " verify: " << verify.TimeCPU( ) << " seconds" );
#endif /* 0 */
#if VC
    BOOST_TEST_MESSAGE( " verify_checksum: " << verify_checksum.TimeCPU( )
                                             << " seconds" );
#endif /* 0 */
#if V2
    BOOST_TEST_MESSAGE( " verify2: " << verify2.TimeCPU( ) << " seconds" );
#endif /* 0 */
}
