#ifndef fr_end_of_frame_hh
#define fr_end_of_frame_hh

#include <cmath>
#include <typeinfo>
#include <type_traits>

#include <boost/test/included/unit_test.hpp>

#include "ldastoolsal/ldas_types.h"

#include "framecpp/Common/FrameSpec.hh"
#include "framecpp/Common/FrameSpec.tcc"

#include "framecpp/Universal/FrEndOfFrame.hh"

namespace testing
{
    namespace fr_end_of_frame
    {
        template < int T_FRAME_SPEC_VERSION >
        using fr_end_of_frame_type =
            typename fr_object_impl< T_FRAME_SPEC_VERSION,
                                     FR_END_OF_FRAME_TYPE >::type;
        template < int T_FRAME_SPEC_VERSION >
        using fr_end_of_frame_previous_type =
            typename fr_object_previous_impl< T_FRAME_SPEC_VERSION,
                                              FR_END_OF_FRAME_TYPE >::type;

        //======================================
        // F U N C T I O N:  version
        //======================================
        // -----
        /// \brief Track where the transitions take place
        // -----
        typedef base_version_constant< 3 > version_root_type;

        template < int T_FRAME_SPEC_VERSION >
        constexpr bool
        is_root( )
        {
            return ( T_FRAME_SPEC_VERSION == version_root_type::value );
        }

        // ---------------
        // version_changes
        //
        // Track where changes to this data structure appear in the frame
        // specification
        // ---------------
        template < int T_FRAME_SPEC_VERSION >
        constexpr int
        version_changes( )
        {
            return ( std::conditional< T_FRAME_SPEC_VERSION >= 8,
                                       base_version_constant< 8 >::type,
                                       typename std::conditional<
                                           T_FRAME_SPEC_VERSION >= 6,
                                           base_version_constant< 6 >::type,
                                           typename std::conditional<
                                               T_FRAME_SPEC_VERSION >= 4,
                                               base_version_constant< 4 >::type,
                                               typename std::enable_if<
                                                   T_FRAME_SPEC_VERSION >=
                                                       version_root_type::value,
                                                   version_root_type::type >
                                               // conditional - 4
                                               >::type
                                           // conditional - 6
                                           >::type
                                       // conditional - 8
                                       >::type
                     // return value
                     ::type::value );
        }

        template < int T_FRAME_SPEC_VERSION >
        constexpr VERSION
                  version( )
        {
            return ( frame_spec_to_version_mapper<
                     version_changes< T_FRAME_SPEC_VERSION >( ) >( ) );
        }

        template < int T_FRAME_SPEC_VERSION >
        constexpr bool
        is_change_version( )
        {
            return ( testing::is_change_version<
                     T_FRAME_SPEC_VERSION,
                     version_changes< T_FRAME_SPEC_VERSION >( ) >( ) );
        }

        // ============
        // version_info
        //
        // Custumization point on how each change to the spec should be handled
        // ============
        template < int T_FRAME_SPEC_VERSION, VERSION T_VERSION >
        struct version_info;

        template < int T_FRAME_SPEC_VERSION >
        struct version_info< T_FRAME_SPEC_VERSION, VERSION::V3 >
        {
            constexpr static int frame_spec_version{ T_FRAME_SPEC_VERSION };

            typedef INT_4U run_type;
            typedef INT_4U frame_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrEndOfFrame
                run_type   run{ 1 };
                frame_type frame{ 2 };

                bool
                compare(
                    const fr_end_of_frame_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrEndOfFrame
                        ( Actual.GetRun( ) == run ) &&
                        ( Actual.GetFrame( ) == frame )
                        // FrEndOfFrame end
                    );
                }
                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    run = 0;
                    frame = 0;
                }
            };

            static bool
            validate_constructors( )
            {
                bool retval{ true };

                try
                {
                    // -------------------
                    // Default constructor
                    // -------------------
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        expected.run, expected.frame );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > source_obj(
                        expected.run, expected.frame );
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        source_obj );

                    std::cerr << "DEBUG: Copy constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_end_of_frame_type< frame_spec_version > obj;

                return ( // FrEndOfFrame
                    check_data_type< run_type >( obj.GetRun( ) ) &&
                    check_data_type< frame_type >( obj.GetFrame( ) )
                    // FrEndOfFrame - end
                );
            }
        };

        template < int T_FRAME_SPEC_VERSION >
        struct version_info< T_FRAME_SPEC_VERSION, VERSION::V4 >
        {
            constexpr static int frame_spec_version{ T_FRAME_SPEC_VERSION };

            using current_type = fr_end_of_frame_type< frame_spec_version >;
            using previous_type =
                fr_end_of_frame_previous_type< frame_spec_version >;

            typedef INT_4S run_type;
            typedef INT_4U frame_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrEndOfFrame
                run_type   run{ 1 };
                frame_type frame{ 2 };

                bool
                compare(
                    const fr_end_of_frame_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrEndOfFrame
                        ( Actual.GetRun( ) == run ) &&
                        ( Actual.GetFrame( ) == frame )
                        // FrEndOfFrame end
                    );
                }
                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    run = 0;
                    frame = 0;
                }
            };

            static bool
            validate_constructors( )
            {
                bool retval{ true };

                // --------------------
                // Default constructor
                // --------------------
                try
                {
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // ---------------------
                // Explicit constructor
                // ---------------------
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        expected.run, expected.frame );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----------------
                // Copy constructor
                // -----------------
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > source_obj(
                        expected.run, expected.frame

                    );
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        source_obj );

                    std::cerr << "DEBUG: Copy constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_end_of_frame_type< frame_spec_version > obj;

                return ( // FrEndOfFrame
                    check_data_type< run_type >( obj.GetRun( ) ) &&
                    check_data_type< frame_type >( obj.GetFrame( ) )
                    // FrEndOfFrame - end
                );
            }

            static bool
            compare_down_convert( object_type< frame_spec_version > Source,
                                  object_type< frame_spec_version > Derived )
            {
                bool retval{ true };

                try
                {
                    // -----
                    // Cast to concreate type
                    // -----
                    auto source_obj =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_obj =
                        boost::dynamic_pointer_cast< previous_type >( Derived );
                    // -----
                    // Do comparison
                    // -----

                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_obj.get( ) ) !=
                          static_cast< const void* >( derived_obj.get( ) ) ) &&
                        // FrEndOfFrame
                        ( source_obj->GetRun( ) ==
                          typename current_type::run_type(
                              derived_obj->GetRun( ) ) ) &&
                        ( source_obj->GetFrame( ) == derived_obj->GetFrame( ) )
                        // FrEndOfFrame end
                    );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }

            static bool
            compare_up_convert( object_type< frame_spec_version > Source,
                                object_type< frame_spec_version > Derived )
            {
                bool retval{ true };

                try
                {
                    // -----
                    // Cast to concreate type
                    // -----
                    auto derived_obj =
                        boost::dynamic_pointer_cast< current_type >( Derived );

                    return ( compare_down_convert( Derived, Source )
                             // FrEndOfFrame - new - begin
                             // FrEndOfFrame - new - end
                    );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }
        };

        template < int T_FRAME_SPEC_VERSION >
        struct version_info< T_FRAME_SPEC_VERSION, VERSION::V6 >
        {
            constexpr static int frame_spec_version{ T_FRAME_SPEC_VERSION };

            using current_type = fr_end_of_frame_type< frame_spec_version >;
            using previous_type =
                fr_end_of_frame_previous_type< frame_spec_version >;

            constexpr static INT_4U current{ frame_spec_version };
            constexpr static auto   previous = previous_version( current );

            typedef INT_4S run_type;
            typedef INT_4U frame_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrEndOfFrame
                run_type   run{ 1 };
                frame_type frame{ 2 };

                bool
                compare(
                    const fr_end_of_frame_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrEndOfFrame
                        ( Actual.GetRun( ) == run ) &&
                        ( Actual.GetFrame( ) == frame )
                        // FrEndOfFrame end
                    );
                }
                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    run = 0;
                    frame = 0;
                }
            };

            static bool
            validate_constructors( )
            {
                bool retval{ true };

                // -------------------
                // Default constructor
                // -------------------
                try
                {
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        expected.run, expected.frame );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > source_obj(
                        expected.run, expected.frame

                    );
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        source_obj );

                    std::cerr << "DEBUG: Copy constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_end_of_frame_type< frame_spec_version > obj;

                return ( // FrEndOfFrame
                    check_data_type< run_type >( obj.GetRun( ) ) &&
                    check_data_type< frame_type >( obj.GetFrame( ) )
                    // FrEndOfFrame - end
                );
            }

            static bool
            compare_down_convert( object_type< frame_spec_version > Source,
                                  object_type< frame_spec_version > Derived )
            {
                bool retval{ true };

                try
                {
                    // -----
                    // Cast to concreate type
                    // -----
                    auto source_obj =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_obj =
                        boost::dynamic_pointer_cast< previous_type >( Derived );

                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_obj.get( ) ) !=
                          static_cast< const void* >( derived_obj.get( ) ) )
                        // Address check - end
                        &&
                        // FrEndOfFrame
                        ( source_obj->GetRun( ) == derived_obj->GetRun( ) ) &&
                        ( source_obj->GetFrame( ) == derived_obj->GetFrame( ) )
                        // FrEndOfFrame end
                    );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }

            static bool
            compare_up_convert( object_type< frame_spec_version > Source,
                                object_type< frame_spec_version > Derived )
            {
                bool retval{ true };

                try
                {
                    // -----
                    // Cast to concreate type
                    // -----
                    auto derived_obj =
                        boost::dynamic_pointer_cast< current_type >( Derived );

                    return ( compare_down_convert( Derived, Source )
                             // Previous - end
                             // New fields - begin
                             // Nothing new
                             // New fields - end
                    );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }
        };

        template < int T_FRAME_SPEC_VERSION >
        struct version_info< T_FRAME_SPEC_VERSION, VERSION::V8 >
        {
            constexpr static int frame_spec_version{ T_FRAME_SPEC_VERSION };

            using current_type = fr_end_of_frame_type< frame_spec_version >;
            using previous_type =
                fr_end_of_frame_previous_type< frame_spec_version >;

            constexpr static INT_4U current{ frame_spec_version };
            constexpr static auto   previous = previous_version( current );

            typedef INT_4S run_type;
            typedef INT_4U frame_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrEndOfFrame
                run_type   run{ 1 };
                frame_type frame{ 2 };

                bool
                compare(
                    const fr_end_of_frame_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrEndOfFrame
                        ( Actual.GetRun( ) == run ) &&
                        ( Actual.GetFrame( ) == frame )
                        // FrEndOfFrame end
                    );
                }
                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default
                    // constructor
                    run = 0;
                    frame = 0;
                }
            };

            static bool
            validate_constructors( )
            {
                bool retval{ true };

                // -------------------
                // Default constructor
                // -------------------
                try
                {
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // ---------------------
                // Explicit constructor
                // ---------------------
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        expected.run, expected.frame );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----------------
                // Copy constructor
                // -----------------
                try
                {
                    expected_type                                expected;
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > source_obj(
                        expected.run, expected.frame

                    );
                    fr_end_of_frame_type< T_FRAME_SPEC_VERSION > obj(
                        source_obj );

                    std::cerr << "DEBUG: Copy constructor "
                              << expected.compare( obj ) << std::endl;
                    retval = retval && expected.compare( obj );
                }
                catch ( ... )
                {
                    retval = false;
                }

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_end_of_frame_type< frame_spec_version > obj;

                return ( // FrEndOfFrame
                    check_data_type< run_type >( obj.GetRun( ) ) &&
                    check_data_type< frame_type >( obj.GetFrame( ) )
                    // FrEndOfFrame - end
                );
            }

            static bool
            compare_down_convert( object_type< frame_spec_version > Source,
                                  object_type< frame_spec_version > Derived )
            {
                bool retval{ true };

                try
                {
                    // -----
                    // Cast to concreate type
                    // -----
                    auto source_obj =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_obj =
                        boost::dynamic_pointer_cast< previous_type >( Derived );
                    // -----
                    // Do comparison
                    // -----
                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_obj.get( ) ) !=
                          static_cast< const void* >( derived_obj.get( ) ) )
                        // Address check - end
                        &&
                        // FrEndOfFrame
                        ( source_obj->GetRun( ) == derived_obj->GetRun( ) ) &&
                        ( source_obj->GetFrame( ) == derived_obj->GetFrame( ) )
                        // FrEndOfFrame end
                    );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }

            static bool
            compare_up_convert( object_type< frame_spec_version > Source,
                                object_type< frame_spec_version > Derived )
            {
                bool retval{ true };

                try
                {
                    // -----
                    // Cast to concreate type
                    // -----
                    return ( compare_down_convert( Derived, Source ) );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }
        };

        //======================================
        // F U N C T I O N:  mk_fr_end_of_frame
        //======================================

        template < int T_FRAME_SPEC_VERSION, VERSION T_VERSION >
        struct mk_fr_end_of_frame_helper;

        template < int T_FRAME_SPEC_VERSION >
        struct mk_fr_end_of_frame_helper< T_FRAME_SPEC_VERSION, VERSION::V3 >
        {
            using retval_type = fr_end_of_frame_type< T_FRAME_SPEC_VERSION >;

            static retval_type*
            create( )
            {
                std::cerr << "DEBUG: Creating new instance for version 3G"
                          << std::endl;
                return ( new retval_type( 1, 2 ) );
            };
        };

        template < int T_FRAME_SPEC_VERSION >
        struct mk_fr_end_of_frame_helper< T_FRAME_SPEC_VERSION, VERSION::V4 >
        {
            using retval_type = fr_end_of_frame_type< T_FRAME_SPEC_VERSION >;

            static retval_type*
            create( )
            {
                return ( new retval_type( 1, 2 ) );
            };
        };

        template < int T_FRAME_SPEC_VERSION >
        struct mk_fr_end_of_frame_helper< T_FRAME_SPEC_VERSION, VERSION::V6 >
        {
            using retval_type = fr_end_of_frame_type< T_FRAME_SPEC_VERSION >;

            static retval_type*
            create( )
            {
                return ( new retval_type( 1, 2 ) );
            };
        };

        template < int T_FRAME_SPEC_VERSION >
        struct mk_fr_end_of_frame_helper< T_FRAME_SPEC_VERSION, VERSION::V8 >
        {
            using retval_type = fr_end_of_frame_type< T_FRAME_SPEC_VERSION >;

            static retval_type*
            create( )
            {
                return ( new retval_type( 1, 2 ) );
            };
        };

        template < int T_FRAME_SPEC_VERSION >
        typename FR_END_OF_FRAME_TYPE< T_FRAME_SPEC_VERSION >::type*
        mk_fr_end_of_frame( )
        {
            return ( mk_fr_end_of_frame_helper<
                     T_FRAME_SPEC_VERSION,
                     version< T_FRAME_SPEC_VERSION >( ) >::create( ) );
        }

        //======================================
        // F U N C T I O N:  verify_data_types
        //======================================

        template < int T_FRAME_SPEC_VERSION >
        bool
        verify_data_types( )
        {
            return (
                version_info<
                    T_FRAME_SPEC_VERSION,
                    version< version_changes< T_FRAME_SPEC_VERSION >( ) >( ) >::
                    validate_data_types( ) );
        }

        //========================================
        // F U N C T I O N:   verify_constructors
        //========================================

        template < int T_FRAME_SPEC_VERSION >
        bool
        verify_constructors( )
        {
            return ( version_info< T_FRAME_SPEC_VERSION,
                                   version< T_FRAME_SPEC_VERSION >( ) >::
                         validate_constructors( ) );
        }

        //======================================
        // F U N C T I O N:   verify_convert
        //======================================

        // -----
        // -----
        template < int T_FRAME_SPEC_VERSION, CONVERT T_CONVERSION >
        struct verify_convert_helper;

        // -----
        /// Specialization to handle T_FRAME_SPEC_VERSION 3 as this is the root
        /// of the frame specification
        // -----
        template < int T_FRAME_SPEC_VERSION >
        struct verify_convert_helper< T_FRAME_SPEC_VERSION, CONVERT::ROOT >
        {
            static bool
            check( )
            {
                return ( convert_check_root< T_FRAME_SPEC_VERSION >(
                    mk_fr_end_of_frame< T_FRAME_SPEC_VERSION > ) );
            }
        };

        // -----
        /// Specialization to handle no conversion as the base and derived
        /// versions are the same
        // -----
        template < int T_FRAME_SPEC_VERSION >
        struct verify_convert_helper< T_FRAME_SPEC_VERSION, CONVERT::SAME >
        {
            static bool
            check( )
            {
                return ( convert_check_same< T_FRAME_SPEC_VERSION >(
                    mk_fr_end_of_frame< T_FRAME_SPEC_VERSION >,
                    mk_fr_end_of_frame< previous_version(
                        T_FRAME_SPEC_VERSION ) > ) );
            }
        };

        // -----
        /// Specialization to handle no conversion as the base and derived
        /// versions are the same
        // -----
        template < int T_FRAME_SPEC_VERSION, CONVERT T_CONVERSION >
        struct verify_convert_helper
        {
            static bool
            check( )
            {
                constexpr INT_4U current{ T_FRAME_SPEC_VERSION };
                constexpr auto   previous = previous_version( current );

                bool retval{ true };

                std::cerr << "DEBUG: convert: current: " << current
                          << " previous: " << previous << std::endl;
                // -----
                // Down convert
                // -----
                try
                {
                    // With no conversion, the object returned should be at the
                    // same address
                    std::cerr << "DEBUG: Created FrEndOfFrame source object"
                              << std::endl;
                    object_type< T_FRAME_SPEC_VERSION > source_obj{
                        mk_fr_end_of_frame< current >( )
                    };
                    auto derived_obj = source_obj->DemoteObject(
                        previous, source_obj, nullptr );
                    retval = retval &&
                        version_info< T_FRAME_SPEC_VERSION,
                                      frame_spec_to_version_mapper<
                                          convert_to_frame_spec_mapper<
                                              T_CONVERSION >( ) >( ) >::
                            compare_down_convert( source_obj, derived_obj );
                }
                catch ( ... )
                {
                    retval = false;
                }

                // -----
                // Up convert
                // -----
                try
                {
                    // With no conversion, the object returned should be at the
                    // same address
                    object_type< T_FRAME_SPEC_VERSION > source_obj{
                        mk_fr_end_of_frame< previous >( )
                    };
                    auto derived_obj = source_obj->PromoteObject(
                        current, previous, source_obj, nullptr );
                    retval = retval &&
                        version_info< T_FRAME_SPEC_VERSION,
                                      frame_spec_to_version_mapper<
                                          convert_to_frame_spec_mapper<
                                              T_CONVERSION >( ) >( ) >::
                            compare_up_convert( source_obj, derived_obj );
                }
                catch ( ... )
                {
                    retval = false;
                }

                return ( retval );
            }
        };

        template < int T_FRAME_SPEC_VERSION >
        bool
        verify_convert( )
        {
            return ( verify_convert_helper<
                     T_FRAME_SPEC_VERSION,
                     conversion<
                         T_FRAME_SPEC_VERSION,
                         is_root< T_FRAME_SPEC_VERSION >( ),
                         is_change_version< T_FRAME_SPEC_VERSION >( ) >( ) >::
                         check( ) );
        }

        //======================================
        // F U N C T I O N:   do_standard_tests
        //======================================
        template < int FrameSpecT >
        void
        do_standard_tests( )
        {
            BOOST_TEST_MESSAGE( "Checking basic correctness of frame structure "
                                "FrEndOfFrame at version "
                                << FrameSpecT );
            BOOST_CHECK( verify_data_types< FrameSpecT >( ) );
            BOOST_CHECK( verify_constructors< FrameSpecT >( ) );
            BOOST_CHECK( verify_convert< FrameSpecT >( ) );
        }
    } // namespace fr_end_of_frame
} // namespace testing

void
fr_end_of_frame( )
{
    testing::fr_end_of_frame::do_standard_tests< 3 >( );
    testing::fr_end_of_frame::do_standard_tests< 4 >( );
    testing::fr_end_of_frame::do_standard_tests< 6 >( );
    testing::fr_end_of_frame::do_standard_tests< 7 >( );
    testing::fr_end_of_frame::do_standard_tests< 8 >( );
}

#endif /* fr_end_of_frame_hh */
