#ifndef fr_vect_hh
#define fr_vect_hh

#include <algorithm>
#include <typeinfo>
#include <type_traits>

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

#include "ldastoolsal/ldas_types.h"

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

#include "ramp.hh"

namespace testing
{
    namespace fr_vect
    {
        INSTANTIATE_STRUCT_UNIVERSAL( FrVect, FR_VECT_TYPE );

        template < int T_FRAME_SPEC_VERSION >
        using fr_vect_type =
            typename fr_object_impl< T_FRAME_SPEC_VERSION, FR_VECT_TYPE >::type;
        template < int T_FRAME_SPEC_VERSION >
        using fr_vect_previous_type =
            typename fr_object_previous_impl< T_FRAME_SPEC_VERSION,
                                              FR_VECT_TYPE >::type;
        template < int T_FRAME_SPEC_VERSION >
        using dimension_type = typename fr_object_impl< T_FRAME_SPEC_VERSION,
                                                        DIMENSION_TYPE >::type;

        typedef REAL_8 vect_data_type;

        static std::string          NAME( "vect_name" );
        static std::string          COMMENT( "vect comment" );
        static std::string          UNIT_Y( "fr_vect_unitY" );
        static const vect_data_type START = 0.0;
        static const vect_data_type STOP = 512.0;
        static const vect_data_type INC = 2.0;
        static const int            SAMPLES = ( ( STOP - START ) / INC );

        vect_data_type DATA[ SAMPLES ];

        //======================================
        // 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 >= 9,
                                  base_version_constant< 9 >::type,
                                  typename 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
                                  // conditional - 9
                                  >::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 std::string name_type;
            typedef INT_2U      compress_type;
            typedef INT_2U      type_type;
            typedef INT_4U      nData_type;
            typedef INT_4U      nBytes_type;
            typedef char*       data_type;
            typedef INT_4U      nDim_type;
            typedef INT_4U      nx_type;
            typedef REAL_8      dx_type;
            typedef std::string unitX_type;
            typedef std::string unitY_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrVect
                name_type     name{ name_type( "name" ) };
                compress_type compress{ 0 };
                type_type     type{ 0 };
                nData_type    nData{ 0 };
                nBytes_type   nBytes{ 0 };
                unitY_type    unitY{ unitY_type( "unitY" ) };
                data_type     data{ nullptr };
                // Dimension information
                nx_type    nx{ 0 };
                dx_type    dx{ 0.0 };
                unitX_type unitX{ unitX_type( "unitX" ) };

                // ---------
                // meta data
                // ---------
                nDim_type                 nDim{ 1 };
                FrameCPP::byte_order_type byte_order{
                    FrameCPP::BYTE_ORDER_HOST
                };
                bool undefined_literals{ false };

                bool
                compare( const fr_vect_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrVect
                        ( Actual.GetName( ).compare( name ) == 0 ) &&
                        ( Actual.GetUnitY( ).compare( unitY ) == 0 ) &&
                        ( Actual.GetType( ) == type ) &&
                        ( undefined_literals ||
                          ( ( Actual.GetNData( ) == nData ) &&
                            ( Actual.GetNBytes( ) == nBytes ) ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( Actual.GetNDim( ) == nDim ) &&
                          ( ( nDim == 0 ) ||
                            ( ( Actual.GetDim( 0 ).GetNx( ) == nx ) &&
                              ( Actual.GetDim( 0 ).GetDx( ) == dx ) &&
                              ( Actual.GetDim( 0 ).GetUnitX( ).compare(
                                    unitX ) == 0 ) ) ) )
                        // Dimension end
                    );
                }
                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    name = "";
                    unitY = "";
                    nDim = 0;
                    undefined_literals = true;
                }
            };

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

                try
                {
                    // -------------------
                    // Default constructor
                    // -------------------
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > source_vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect( source_vect );

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

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_vect_type< frame_spec_version >   vect;
                dimension_type< frame_spec_version > dims;

                return ( // FrVect
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetName( ) ) ) &&
                    ( check_data_type< compress_type >(
                        vect.GetCompress( ) ) ) &&
                    ( check_data_type< type_type >( vect.GetType( ) ) ) &&
                    ( check_data_type< nData_type >( vect.GetNData( ) ) ) &&
                    ( check_data_type< nBytes_type >( vect.GetNBytes( ) ) ) &&
                    ( check_data_type< nDim_type >( vect.GetNDim( ) ) ) &&
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetUnitY( ) ) )
                    // FrVect - end
                    &&
                    // Dimensions
                    ( check_data_type< nx_type >( dims.GetNx( ) ) ) &&
                    ( check_data_type< dx_type >( dims.GetDx( ) ) ) &&
                    ( check_data_type_string< T_FRAME_SPEC_VERSION >(
                        dims.GetUnitX( ) ) )
                    // Dimensions - 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_vect_type< frame_spec_version >;
            using previous_type = fr_vect_previous_type< frame_spec_version >;

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

            typedef std::string name_type;
            typedef INT_2U      compress_type;
            typedef INT_2U      type_type;
            typedef INT_4U      nData_type;
            typedef INT_4U      nBytes_type;
            typedef char*       data_type;
            typedef INT_4U      nDim_type;
            typedef INT_4U      nx_type;
            typedef REAL_8      dx_type;
            typedef REAL_8      startX_type; // new
            typedef std::string unitX_type;
            typedef std::string unitY_type;

            constexpr static startX_type DEFAULT_START_X{ 0.0 };

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrVect
                name_type     name{ name_type( "name" ) };
                compress_type compress{ 0 };
                type_type     type{ 0 };
                nData_type    nData{ 0 };
                nBytes_type   nBytes{ 0 };
                unitY_type    unitY{ unitY_type( "unitY" ) };
                data_type     data{ nullptr };
                // Dimension information
                nx_type     nx{ 0 };
                dx_type     dx{ 0.0 };
                startX_type startX{ 0.0 };
                unitX_type  unitX{ unitX_type( "unitX" ) };

                // ---------
                // meta data
                // ---------
                nDim_type                 nDim{ 1 };
                FrameCPP::byte_order_type byte_order{
                    FrameCPP::BYTE_ORDER_HOST
                };
                bool undefined_literals{ false };

                bool
                compare( const fr_vect_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrVect
                        ( Actual.GetName( ).compare( name ) == 0 ) &&
                        ( Actual.GetUnitY( ).compare( unitY ) == 0 ) &&
                        ( Actual.GetType( ) == type ) &&
                        ( undefined_literals ||
                          ( ( Actual.GetNData( ) == nData ) &&
                            ( Actual.GetNBytes( ) == nBytes ) ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( Actual.GetNDim( ) == nDim ) &&
                          ( ( nDim == 0 ) ||
                            ( ( Actual.GetDim( 0 ).GetNx( ) == nx ) &&
                              ( Actual.GetDim( 0 ).GetDx( ) == dx ) &&
                              ( Actual.GetDim( 0 ).GetStartX( ) == startX ) &&
                              ( Actual.GetDim( 0 ).GetUnitX( ).compare(
                                    unitX ) == 0 ) ) ) )
                        // Dimension end
                    );
                }
                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    name = "";
                    unitY = "";
                    nDim = 0;
                    undefined_literals = true;
                }
            };

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

                try
                {
                    // -------------------
                    // Default constructor
                    // -------------------
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > source_vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect( source_vect );

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

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_vect_type< frame_spec_version >   vect;
                dimension_type< frame_spec_version > dims;

                return ( // FrVect
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetName( ) ) ) &&
                    ( check_data_type< compress_type >(
                        vect.GetCompress( ) ) ) &&
                    ( check_data_type< type_type >( vect.GetType( ) ) ) &&
                    ( check_data_type< nData_type >( vect.GetNData( ) ) ) &&
                    ( check_data_type< nBytes_type >( vect.GetNBytes( ) ) ) &&
                    ( check_data_type< nDim_type >( vect.GetNDim( ) ) ) &&
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetUnitY( ) ) )
                    // FrVect - end
                    &&
                    // Dimensions
                    ( check_data_type< nx_type >( dims.GetNx( ) ) ) &&
                    ( check_data_type< dx_type >( dims.GetDx( ) ) ) &&
                    ( check_data_type< startX_type >( dims.GetStartX( ) ) ) &&
                    ( check_data_type_string< T_FRAME_SPEC_VERSION >(
                        dims.GetUnitX( ) ) )
                    // Dimensions - end
                );
            }

            template < typename T, typename U >
            struct is_shared_ptr_of : std::false_type
            {
            };

            template < typename T, typename U >
            struct is_shared_ptr_of< boost::shared_ptr< T >, U >
                : std::is_same< T, U >
            {
            };

            template < typename SourceType, typename DerivedType >
            static typename std::enable_if<
                is_shared_ptr_of< typename SourceType::element_type,
                                  FrameCPP::Version_4::FrVect >::value ||
                    is_shared_ptr_of< typename DerivedType::element_type,
                                      FrameCPP::Version_4::FrVect >::value,
                bool >::type
            compare_data_down_convert( SourceType  SourceVect,
                                       DerivedType DerivedVect )
            {
                bool retval = true;

                return ( retval );
            }

            template < typename SourceType, typename DerivedType >
            static bool
            compare_data_down_convert( SourceType  SourceVect,
                                       DerivedType DerivedVect )
            {
                bool retval = true;

                auto source_buffer =
                    SourceVect->DataAlloc( SourceVect->GetType( ),
                                           SourceVect->GetDim( ),
                                           SourceVect->GetNDim( ) );
                auto derived_buffer =
                    DerivedVect->DataAlloc( DerivedVect->GetType( ),
                                            DerivedVect->GetDim( ),
                                            DerivedVect->GetNDim( ) );
                return ( retval );
            }

            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_vect =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_vect =
                        boost::dynamic_pointer_cast< previous_type >( Derived );
                    // -----
                    // Do comparison
                    // -----
                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_vect.get( ) ) !=
                          static_cast< const void* >( derived_vect.get( ) ) ) &&
                        // FrVect
                        ( source_vect->GetName( ).compare(
                              derived_vect->GetName( ) ) == 0 ) &&
                        ( source_vect->GetUnitY( ).compare(
                              derived_vect->GetUnitY( ) ) == 0 ) &&
                        ( source_vect->GetType( ) ==
                          derived_vect->GetType( ) ) &&
                        ( source_vect->GetNData( ) ==
                          derived_vect->GetNData( ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( source_vect->GetNDim( ) ==
                            derived_vect->GetNDim( ) ) &&
                          ( ( derived_vect->GetNDim( ) == 0 ) ||
                            ( ( source_vect->GetDim( 0 ).GetNx( ) ==
                                derived_vect->GetDim( 0 ).GetNx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetDx( ) ==
                                derived_vect->GetDim( 0 ).GetDx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetUnitX( ).compare(
                                    derived_vect->GetDim( 0 ).GetUnitX( ) ) ==
                                0 ) ) ) )
                        // Dimension end
                        &&
                        // Data contents
                        compare_data_down_convert( source_vect, derived_vect )
                        // Data contents - 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 source_vect =
                        boost::dynamic_pointer_cast< previous_type >( Source );
                    auto derived_vect =
                        boost::dynamic_pointer_cast< current_type >( Derived );

                    return ( compare_down_convert( Derived, Source ) &&
                             ( derived_vect->GetNDim( ) ||
                               ( derived_vect->GetDim( 0 ).GetStartX( ) ==
                                 DEFAULT_START_X ) ) );
                }
                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_vect_type< frame_spec_version >;
            using previous_type = fr_vect_previous_type< frame_spec_version >;

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

            typedef std::string name_type;
            typedef INT_2U      compress_type;
            typedef INT_2U      type_type;
            typedef INT_8U      nData_type; // changed
            typedef INT_8U      nBytes_type; // changed
            typedef char*       data_type;
            typedef INT_4U      nDim_type;
            typedef INT_8U      nx_type; // changed
            typedef REAL_8      dx_type;
            typedef REAL_8      startX_type;
            typedef std::string unitX_type;
            typedef std::string unitY_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrVect
                name_type     name{ name_type( "name" ) };
                compress_type compress{ 0 };
                type_type     type{ 0 };
                nData_type    nData{ 0 };
                nBytes_type   nBytes{ 0 };
                unitY_type    unitY{ unitY_type( "unitY" ) };
                data_type     data{ nullptr };
                // Dimension information
                nx_type     nx{ 0 };
                dx_type     dx{ 0.0 };
                startX_type startX{ 0.0 };
                unitX_type  unitX{ unitX_type( "unitX" ) };

                // ---------
                // meta data
                // ---------
                nDim_type                 nDim{ 1 };
                FrameCPP::byte_order_type byte_order{
                    FrameCPP::BYTE_ORDER_HOST
                };
                bool undefined_literals{ false };

                bool
                compare( const fr_vect_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrVect
                        ( Actual.GetName( ).compare( name ) == 0 ) &&
                        ( Actual.GetUnitY( ).compare( unitY ) == 0 ) &&
                        ( Actual.GetType( ) == type ) &&
                        ( undefined_literals ||
                          ( ( Actual.GetNData( ) == nData ) &&
                            ( Actual.GetNBytes( ) == nBytes ) ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( Actual.GetNDim( ) == nDim ) &&
                          ( ( nDim == 0 ) ||
                            ( ( Actual.GetDim( 0 ).GetNx( ) == nx ) &&
                              ( Actual.GetDim( 0 ).GetDx( ) == dx ) &&
                              ( Actual.GetDim( 0 ).GetStartX( ) == startX ) &&
                              ( Actual.GetDim( 0 ).GetUnitX( ).compare(
                                    unitX ) == 0 ) ) ) )
                        // Dimension end
                    );
                }

                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    name = "";
                    unitY = "";
                    nDim = 0;
                    undefined_literals = true;
                }
            };

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

                try
                {
                    // -------------------
                    // Default constructor
                    // -------------------
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > source_vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect( source_vect );

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

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_vect_type< frame_spec_version >   vect;
                dimension_type< frame_spec_version > dims;

                return ( // FrVect
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetName( ) ) ) &&
                    ( check_data_type< compress_type >(
                        vect.GetCompress( ) ) ) &&
                    ( check_data_type< type_type >( vect.GetType( ) ) ) &&
                    ( check_data_type< nData_type >( vect.GetNData( ) ) ) &&
                    ( check_data_type< nBytes_type >( vect.GetNBytes( ) ) ) &&
                    ( check_data_type< nDim_type >( vect.GetNDim( ) ) ) &&
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetUnitY( ) ) )
                    // FrVect - end
                    &&
                    // Dimensions
                    ( check_data_type< nx_type >( dims.GetNx( ) ) ) &&
                    ( check_data_type< dx_type >( dims.GetDx( ) ) ) &&
                    ( check_data_type< startX_type >( dims.GetStartX( ) ) ) &&
                    ( check_data_type_string< T_FRAME_SPEC_VERSION >(
                        dims.GetUnitX( ) ) )
                    // Dimensions - 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_vect =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_vect =
                        boost::dynamic_pointer_cast< previous_type >( Derived );
                    // -----
                    // Do comparison
                    // -----
                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_vect.get( ) ) !=
                          static_cast< const void* >( derived_vect.get( ) ) ) &&
                        // FrVect
                        ( source_vect->GetName( ).compare(
                              derived_vect->GetName( ) ) == 0 ) &&
                        ( source_vect->GetUnitY( ).compare(
                              derived_vect->GetUnitY( ) ) == 0 ) &&
                        ( source_vect->GetType( ) ==
                          derived_vect->GetType( ) ) &&
                        ( source_vect->GetNData( ) ==
                          derived_vect->GetNData( ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( source_vect->GetNDim( ) ==
                            derived_vect->GetNDim( ) ) &&
                          ( ( derived_vect->GetNDim( ) == 0 ) ||
                            ( ( source_vect->GetDim( 0 ).GetNx( ) ==
                                derived_vect->GetDim( 0 ).GetNx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetDx( ) ==
                                derived_vect->GetDim( 0 ).GetDx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetStartX( ) ==
                                derived_vect->GetDim( 0 ).GetStartX( ) ) &&
                              ( source_vect->GetDim( 0 ).GetUnitX( ).compare(
                                    derived_vect->GetDim( 0 ).GetUnitX( ) ) ==
                                0 ) ) ) )
                        // Dimension 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
                {
                    // Nothing do do here since only type changed
                    return ( compare_down_convert( Derived, Source ) );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }
        };

        template < int T_FRAME_SPEC_VERSION >
        struct version_info< T_FRAME_SPEC_VERSION, VERSION::V8 >
        {
            // NOTE: Introduced per object checksum which is not recorded here

            constexpr static int frame_spec_version{ T_FRAME_SPEC_VERSION };

            using current_type = fr_vect_type< frame_spec_version >;
            using previous_type = fr_vect_previous_type< frame_spec_version >;

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

            typedef std::string name_type;
            typedef INT_2U      compress_type;
            typedef INT_2U      type_type;
            typedef INT_8U      nData_type;
            typedef INT_8U      nBytes_type;
            typedef INT_4U      nDim_type;
            typedef char*       data_type;
            typedef INT_8U      nx_type;
            typedef REAL_8      dx_type;
            typedef REAL_8      startX_type;
            typedef std::string unitX_type;
            typedef std::string unitY_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrVect
                name_type     name{ name_type( "name" ) };
                compress_type compress{ 0 };
                type_type     type{ 0 };
                nData_type    nData{ 0 };
                nBytes_type   nBytes{ 0 };
                unitY_type    unitY{ unitY_type( "unitY" ) };
                data_type     data{ nullptr };
                // Dimension information
                nx_type     nx{ 0 };
                dx_type     dx{ 0.0 };
                startX_type startX{ 0.0 };
                unitX_type  unitX{ unitX_type( "unitX" ) };

                // ---------
                // meta data
                // ---------
                nDim_type                 nDim{ 1 };
                FrameCPP::byte_order_type byte_order{
                    FrameCPP::BYTE_ORDER_HOST
                };
                bool undefined_literals{ false };

                bool
                compare( const fr_vect_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrVect
                        ( Actual.GetName( ).compare( name ) == 0 ) &&
                        ( Actual.GetUnitY( ).compare( unitY ) == 0 ) &&
                        ( Actual.GetType( ) == type ) &&
                        ( undefined_literals ||
                          ( ( Actual.GetNData( ) == nData ) &&
                            ( Actual.GetNBytes( ) == nBytes ) ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( Actual.GetNDim( ) == nDim ) &&
                          ( ( nDim == 0 ) ||
                            ( ( Actual.GetDim( 0 ).GetNx( ) == nx ) &&
                              ( Actual.GetDim( 0 ).GetDx( ) == dx ) &&
                              ( Actual.GetDim( 0 ).GetStartX( ) == startX ) &&
                              ( Actual.GetDim( 0 ).GetUnitX( ).compare(
                                    unitX ) == 0 ) ) ) )
                        // Dimension end
                    );
                }

                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    name = "";
                    unitY = "";
                    nDim = 0;
                    undefined_literals = true;
                }
            };

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

                try
                {
                    // -------------------
                    // Default constructor
                    // -------------------
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > source_vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect( source_vect );

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

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_vect_type< frame_spec_version >   vect;
                dimension_type< frame_spec_version > dims;

                return ( // FrVect
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetName( ) ) ) &&
                    ( check_data_type< compress_type >(
                        vect.GetCompress( ) ) ) &&
                    ( check_data_type< type_type >( vect.GetType( ) ) ) &&
                    ( check_data_type< nData_type >( vect.GetNData( ) ) ) &&
                    ( check_data_type< nBytes_type >( vect.GetNBytes( ) ) ) &&
                    ( check_data_type< nDim_type >( vect.GetNDim( ) ) ) &&
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetUnitY( ) ) )
                    // FrVect - end
                    &&
                    // Dimensions
                    ( check_data_type< nx_type >( dims.GetNx( ) ) ) &&
                    ( check_data_type< dx_type >( dims.GetDx( ) ) ) &&
                    ( check_data_type< startX_type >( dims.GetStartX( ) ) ) &&
                    ( check_data_type_string< T_FRAME_SPEC_VERSION >(
                        dims.GetUnitX( ) ) )
                    // Dimensions - 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_vect =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_vect =
                        boost::dynamic_pointer_cast< previous_type >( Derived );
                    // -----
                    // Do comparison
                    // -----
                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_vect.get( ) ) !=
                          static_cast< const void* >( derived_vect.get( ) ) ) &&
                        // FrVect
                        ( source_vect->GetName( ).compare(
                              derived_vect->GetName( ) ) == 0 ) &&
                        ( source_vect->GetUnitY( ).compare(
                              derived_vect->GetUnitY( ) ) == 0 ) &&
                        ( source_vect->GetType( ) ==
                          derived_vect->GetType( ) ) &&
                        ( source_vect->GetNData( ) ==
                          derived_vect->GetNData( ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( source_vect->GetNDim( ) ==
                            derived_vect->GetNDim( ) ) &&
                          ( ( derived_vect->GetNDim( ) == 0 ) ||
                            ( ( source_vect->GetDim( 0 ).GetNx( ) ==
                                derived_vect->GetDim( 0 ).GetNx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetDx( ) ==
                                derived_vect->GetDim( 0 ).GetDx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetStartX( ) ==
                                derived_vect->GetDim( 0 ).GetStartX( ) ) &&
                              ( source_vect->GetDim( 0 ).GetUnitX( ).compare(
                                    derived_vect->GetDim( 0 ).GetUnitX( ) ) ==
                                0 ) ) ) )
                        // Dimension 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
                {
                    // Nothing do do here since only type changed
                    return ( compare_down_convert( Derived, Source ) );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }
        };

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

            using current_type = fr_vect_type< frame_spec_version >;
            using previous_type = fr_vect_previous_type< frame_spec_version >;

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

            typedef std::string name_type;
            typedef INT_2U      compress_type;
            typedef INT_2U      type_type;
            typedef INT_8U      nData_type;
            typedef INT_8U      nBytes_type;
            typedef INT_4U      nDim_type;
            typedef char*       data_type;
            typedef INT_8U      nx_type;
            typedef REAL_8      dx_type;
            typedef REAL_8      startX_type;
            typedef std::string unitX_type;
            typedef std::string unitY_type;

            struct expected_type
            {
                // -----------
                // Seed values
                // -----------
                // FrVect
                name_type     name{ name_type( "name" ) };
                compress_type compress{ 0 };
                type_type     type{ 0 };
                nData_type    nData{ 0 };
                nBytes_type   nBytes{ 0 };
                unitY_type    unitY{ unitY_type( "unitY" ) };
                data_type     data{ nullptr };
                // Dimension information
                nx_type     nx{ 0 };
                dx_type     dx{ 0.0 };
                startX_type startX{ 0.0 };
                unitX_type  unitX{ unitX_type( "unitX" ) };

                // ---------
                // meta data
                // ---------
                nDim_type                 nDim{ 1 };
                FrameCPP::byte_order_type byte_order{
                    FrameCPP::BYTE_ORDER_HOST
                };
                bool undefined_literals{ false };

                bool
                compare( const fr_vect_type< T_FRAME_SPEC_VERSION >& Actual )
                {
                    return (
                        // FrVect
                        ( Actual.GetName( ).compare( name ) == 0 ) &&
                        ( Actual.GetUnitY( ).compare( unitY ) == 0 ) &&
                        ( Actual.GetType( ) == type ) &&
                        ( undefined_literals ||
                          ( ( Actual.GetNData( ) == nData ) &&
                            ( Actual.GetNBytes( ) == nBytes ) ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( Actual.GetNDim( ) == nDim ) &&
                          ( ( nDim == 0 ) ||
                            ( ( Actual.GetDim( 0 ).GetNx( ) == nx ) &&
                              ( Actual.GetDim( 0 ).GetDx( ) == dx ) &&
                              ( Actual.GetDim( 0 ).GetStartX( ) == startX ) &&
                              ( Actual.GetDim( 0 ).GetUnitX( ).compare(
                                    unitX ) == 0 ) ) ) )
                        // Dimension end
                    );
                }

                void
                set_default_constructor_values( )
                {
                    // local overrides for corner case of default constructor
                    name = "";
                    unitY = "";
                    nDim = 0;
                    undefined_literals = true;
                }
            };

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

                try
                {
                    // -------------------
                    // Default constructor
                    // -------------------
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect;

                    expected_type expected;
                    expected.set_default_constructor_values( );

                    std::cerr << "DEBUG: Default constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Explicit constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );

                    std::cerr << "DEBUG: Explicit constructor "
                              << expected.compare( vect ) << std::endl;
                    retval = retval && expected.compare( vect );
                }
                catch ( ... )
                {
                    retval = false;
                }
                // -----
                // Copy constructor
                // -----
                try
                {
                    expected_type                          expected;
                    dimension_type< T_FRAME_SPEC_VERSION > dims(
                        expected.nx, expected.dx, expected.unitX );
                    fr_vect_type< T_FRAME_SPEC_VERSION > source_vect(
                        expected.name,
                        expected.type,
                        1,
                        &dims,
                        expected.byte_order,
                        expected.data,
                        expected.unitY );
                    fr_vect_type< T_FRAME_SPEC_VERSION > vect( source_vect );

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

                return ( retval );
            }

            static bool
            validate_data_types( )
            {
                fr_vect_type< frame_spec_version >   vect;
                dimension_type< frame_spec_version > dims;

                return ( // FrVect
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetName( ) ) ) &&
                    ( check_data_type< compress_type >(
                        vect.GetCompress( ) ) ) &&
                    ( check_data_type< type_type >( vect.GetType( ) ) ) &&
                    ( check_data_type< nData_type >( vect.GetNData( ) ) ) &&
                    ( check_data_type< nBytes_type >( vect.GetNBytes( ) ) ) &&
                    ( check_data_type< nDim_type >( vect.GetNDim( ) ) ) &&
                    ( check_data_type_string< frame_spec_version >(
                        vect.GetUnitY( ) ) )
                    // FrVect - end
                    &&
                    // Dimensions
                    ( check_data_type< nx_type >( dims.GetNx( ) ) ) &&
                    ( check_data_type< dx_type >( dims.GetDx( ) ) ) &&
                    ( check_data_type< startX_type >( dims.GetStartX( ) ) ) &&
                    ( check_data_type_string< T_FRAME_SPEC_VERSION >(
                        dims.GetUnitX( ) ) )
                    // Dimensions - 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_vect =
                        boost::dynamic_pointer_cast< current_type >( Source );
                    auto derived_vect =
                        boost::dynamic_pointer_cast< previous_type >( Derived );
                    // -----
                    // Do comparison
                    // -----
                    return (
                        // Must be different addresses
                        ( static_cast< const void* >( source_vect.get( ) ) !=
                          static_cast< const void* >( derived_vect.get( ) ) ) &&
                        // FrVect
                        ( source_vect->GetName( ).compare(
                              derived_vect->GetName( ) ) == 0 ) &&
                        ( source_vect->GetUnitY( ).compare(
                              derived_vect->GetUnitY( ) ) == 0 ) &&
                        ( source_vect->GetType( ) ==
                          derived_vect->GetType( ) ) &&
                        ( source_vect->GetNData( ) ==
                          derived_vect->GetNData( ) )
                        // FrVect end
                        &&
                        // Dimension
                        ( ( source_vect->GetNDim( ) ==
                            derived_vect->GetNDim( ) ) &&
                          ( ( derived_vect->GetNDim( ) == 0 ) ||
                            ( ( source_vect->GetDim( 0 ).GetNx( ) ==
                                derived_vect->GetDim( 0 ).GetNx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetDx( ) ==
                                derived_vect->GetDim( 0 ).GetDx( ) ) &&
                              ( source_vect->GetDim( 0 ).GetStartX( ) ==
                                derived_vect->GetDim( 0 ).GetStartX( ) ) &&
                              ( source_vect->GetDim( 0 ).GetUnitX( ).compare(
                                    derived_vect->GetDim( 0 ).GetUnitX( ) ) ==
                                0 ) ) ) )
                        // Dimension 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
                {
                    // Nothing do do here since only type changed
                    return ( compare_down_convert( Derived, Source ) );
                }
                catch ( ... )
                {
                    retval = false;
                }
                return ( retval );
            }
        };

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

        template < int T_FRAME_SPEC_VERSION, VERSION T_VERSION >
        struct mk_fr_vect_helper;

        template < int T_FRAME_SPEC_VERSION, VERSION T_VERSION >
        struct mk_fr_vect_helper
        {
            using retval_type = fr_vect_type< T_FRAME_SPEC_VERSION >;

            static retval_type*
            create( )
            {
                static bool                            initialized{ false };
                dimension_type< T_FRAME_SPEC_VERSION > DIM( SAMPLES );

                if ( !initialized )
                {
                    Ramp::GenSawToothRising< vect_data_type > saw_tooth_rising(
                        START, STOP, INC );
                    std::generate( &( DATA[ 0 ] ),
                                   &( DATA[ SAMPLES ] ),
                                   saw_tooth_rising );
                    initialized = true;
                }

                return ( new retval_type( NAME, 1, &DIM, DATA, UNIT_Y ) );
            };
        };

        template < int T_FRAME_SPEC_VERSION >
        fr_vect_type< T_FRAME_SPEC_VERSION >*
        mk_fr_vect( )
        {
            return ( mk_fr_vect_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_vect< 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_vect< T_FRAME_SPEC_VERSION >,
                    mk_fr_vect< 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 };

                // -----
                // Down convert
                // -----
                try
                {
                    // With no conversion, the object returned should be at the
                    // same address
                    object_type< T_FRAME_SPEC_VERSION > source_obj{
                        mk_fr_vect< 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_vect< 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 "
                                "FrVect at version "
                                << FrameSpecT );
            BOOST_CHECK( verify_data_types< FrameSpecT >( ) );
            BOOST_CHECK( verify_constructors< FrameSpecT >( ) );
            BOOST_CHECK( verify_convert< FrameSpecT >( ) );
        }
    }; // namespace fr_vect

} // namespace testing
#endif /* fr_vect_hh */
