<commit_before>#include <bts/blockchain/asset_operations.hpp>
#include <bts/blockchain/exceptions.hpp>
#include <bts/blockchain/pending_chain_state.hpp>

namespace bts { namespace blockchain {

bool is_power_of_ten( uint64_t n )
{
    switch( n )
    {
        case 1ll:
        case 10ll:
        case 100ll:
        case 1000ll:
        case 10000ll:
        case 100000ll:
        case 1000000ll:
        case 10000000ll:
        case 100000000ll:
        case 1000000000ll:
        case 10000000000ll:
        case 100000000000ll:
        case 1000000000000ll:
        case 10000000000000ll:
        case 100000000000000ll:
        case 1000000000000000ll:
            return true;
        default:
            return false;
    }
}

void create_asset_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    if( !eval_state._pending_state->is_valid_symbol_name( this->symbol ) )
        FC_CAPTURE_AND_THROW( invalid_asset_symbol, (symbol) );

    const auto dot_pos = this->symbol.find('.');
    if( dot_pos != string::npos )
    {
        string parent_symbol = this->symbol.substr( 0, dot_pos );
        oasset_record parent_asset_record = eval_state._pending_state->get_asset_record( parent_symbol );
        FC_ASSERT( parent_asset_record.valid() );

        if( !eval_state.verify_authority( parent_asset_record->authority ) )
            FC_CAPTURE_AND_THROW( missing_signature, (parent_asset_record->authority) );
    }

    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( this->symbol );
    if( current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( asset_symbol_in_use, (symbol) );

    if( this->name.empty() )
        FC_CAPTURE_AND_THROW( invalid_asset_name, (this->name) );

    const asset_id_type asset_id = eval_state._pending_state->last_asset_id() + 1;
    current_asset_record = eval_state._pending_state->get_asset_record( asset_id );
    if( current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( asset_id_in_use, (asset_id) );

    oaccount_record issuer_account_record;
    if( issuer_account_id != asset_record::market_issuer_id )
    {
        issuer_account_record = eval_state._pending_state->get_account_record( this->issuer_account_id );
        if( !issuer_account_record.valid() )
            FC_CAPTURE_AND_THROW( unknown_account_id, (issuer_account_id) );
    }

    if( this->maximum_share_supply <= 0 || this->maximum_share_supply > BTS_BLOCKCHAIN_MAX_SHARES )
        FC_CAPTURE_AND_THROW( invalid_asset_amount, (this->maximum_share_supply) );

    if( !is_power_of_ten( this->precision ) )
        FC_CAPTURE_AND_THROW( invalid_precision, (this->precision) );

    const asset reg_fee( eval_state._pending_state->get_asset_registration_fee( this->symbol.size() ), 0 );
    eval_state.min_fees[ reg_fee.asset_id ] += reg_fee.amount;

    asset_record new_record;

    new_record.id                 = eval_state._pending_state->new_asset_id();
    new_record.symbol             = this->symbol;

    new_record.issuer_id          = this->issuer_account_id;

    if( issuer_account_record.valid() )
    {
        new_record.authority.owners.insert( issuer_account_record->active_key() );
        new_record.authority.required = 1;
    }

    new_record.name               = this->name;
    new_record.description        = this->description;
    new_record.public_data        = this->public_data;

    new_record.precision          = this->precision;
    new_record.max_supply         = this->maximum_share_supply;

    new_record.registration_date  = eval_state._pending_state->now();
    new_record.last_update        = new_record.registration_date;

    eval_state._pending_state->store_asset_record( new_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void issue_asset_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( abs( this->amount.asset_id ) );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id, (amount.asset_id) );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( !eval_state.verify_authority( current_asset_record->authority ) )
        FC_CAPTURE_AND_THROW( missing_signature, (current_asset_record->authority) );

    if( this->amount.amount <= 0 )
        FC_CAPTURE_AND_THROW( negative_issue, (amount) );

    if( this->amount.asset_id > 0 )
    {
        if( this->amount.amount > current_asset_record->max_supply - current_asset_record->current_supply )
            FC_CAPTURE_AND_THROW( over_issue, (amount)(*current_asset_record) );

        current_asset_record->current_supply += this->amount.amount;
    }
    else
    {
        if( this->amount.amount > current_asset_record->collected_fees )
            FC_CAPTURE_AND_THROW( amount_too_large, (amount)(*current_asset_record) );

        current_asset_record->collected_fees -= this->amount.amount;
    }

    eval_state.add_balance( asset( this->amount.amount, abs( this->amount.asset_id ) ) );

    current_asset_record->last_update = eval_state._pending_state->now();
    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void asset_update_properties_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( this->asset_id );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id, (this->asset_id) );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( !eval_state.verify_authority( current_asset_record->authority ) )
        FC_CAPTURE_AND_THROW( missing_signature, (current_asset_record->authority) );

    // Reject no-ops
    FC_ASSERT( this->issuer_id.valid()
               || this->name.valid()
               || this->description.valid()
               || this->public_data.valid()
               || this->precision.valid()
               || this->max_supply.valid()
               || this->withdrawal_fee.valid()
               || this->market_fee_rate.valid() );

    if( this->issuer_id.valid() )
    {
        const oaccount_record account_record = eval_state._pending_state->get_account_record( *this->issuer_id );
        if( !account_record.valid() )
            FC_CAPTURE_AND_THROW( unknown_account_id, (*this->issuer_id) );

        current_asset_record->issuer_id = *this->issuer_id;
    }

    if( this->name.valid() )
    {
        if( this->name->empty() )
            FC_CAPTURE_AND_THROW( invalid_asset_name, (*this->name) );

        current_asset_record->name = *this->name;
    }

    if( this->description.valid() )
        current_asset_record->description = *this->description;

    if( this->public_data.valid() )
        current_asset_record->public_data = *this->public_data;

    if( this->precision.valid() )
    {
        if( current_asset_record->current_supply != 0 )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( !is_power_of_ten( *this->precision ) )
            FC_CAPTURE_AND_THROW( invalid_precision, (*this->precision) );

        current_asset_record->precision = *this->precision;
    }

    if( this->max_supply.valid() )
    {
        if( current_asset_record->current_supply != 0 && !current_asset_record->flag_is_active( asset_record::dynamic_max_supply ) )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( *this->max_supply < current_asset_record->current_supply || *this->max_supply > BTS_BLOCKCHAIN_MAX_SHARES )
            FC_CAPTURE_AND_THROW( invalid_asset_amount, (*this->max_supply) );

        current_asset_record->max_supply = *this->max_supply;
    }

    if( this->withdrawal_fee.valid() )
    {
        if( current_asset_record->current_supply != 0 && !current_asset_record->flag_is_active( asset_record::dynamic_fees ) )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( *this->withdrawal_fee < 0 || *this->withdrawal_fee > current_asset_record->max_supply )
            FC_CAPTURE_AND_THROW( invalid_asset_amount, (*this->withdrawal_fee) );

        current_asset_record->withdrawal_fee = *this->withdrawal_fee;
    }

    if( this->market_fee_rate.valid() )
    {
        if( current_asset_record->current_supply != 0 && !current_asset_record->flag_is_active( asset_record::dynamic_fees ) )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( *this->market_fee_rate > BTS_BLOCKCHAIN_MAX_UIA_MARKET_FEE_RATE )
            FC_CAPTURE_AND_THROW( invalid_fee_rate, (*this->market_fee_rate) );

        current_asset_record->market_fee_rate = *this->market_fee_rate;
    }

    current_asset_record->last_update = eval_state._pending_state->now();
    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void asset_update_permissions_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( this->asset_id );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id, (this->asset_id) );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( !eval_state.verify_authority( current_asset_record->authority ) )
        FC_CAPTURE_AND_THROW( missing_signature, (current_asset_record->authority) );

    // Reject no-ops
    FC_ASSERT( this->authority.valid()
               || this->authority_flag_permissions.valid()
               || this->active_flags.valid() );

    if( this->authority.valid() )
    {
        if( this->authority->required < 1 || this->authority->owners.empty() )
            FC_CAPTURE_AND_THROW( invalid_authority, (*this->authority) );

        current_asset_record->authority = *this->authority;
    }

    if( this->authority_flag_permissions.valid() )
    {
        if( current_asset_record->current_supply != 0 )
        {
            for( size_t i = 0; i < sizeof( current_asset_record->authority_flag_permissions ) * 8; ++i )
            {
                const auto permission = static_cast<asset_record::flag_enum>( 1 << i );
                const bool requesting_permission = *this->authority_flag_permissions & permission;
                if( requesting_permission && !current_asset_record->authority_has_flag_permission( permission ) )
                    FC_CAPTURE_AND_THROW( outstanding_shares_exist, (permission) );
            }
        }

        current_asset_record->authority_flag_permissions = *this->authority_flag_permissions;
    }

    if( this->active_flags.valid() )
    {
        for( size_t i = 0; i < sizeof( current_asset_record->active_flags ) * 8; ++i )
        {
            const auto permission = static_cast<asset_record::flag_enum>( 1 << i );
            const bool activating_permission = *this->active_flags & permission;
            if( activating_permission && !current_asset_record->authority_has_flag_permission( permission ) )
                FC_CAPTURE_AND_THROW( permission_not_available, (permission) );
        }

        current_asset_record->active_flags = *this->active_flags;
    }

    current_asset_record->last_update = eval_state._pending_state->now();
    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void asset_update_whitelist_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( abs( this->asset_id ) );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( this->asset_id > 0 )
    {
        FC_ASSERT( current_asset_record->flag_is_active( asset_record::restricted_deposits ) );
        current_asset_record->whitelist.insert( this->owner );
    }
    else
    {
        current_asset_record->whitelist.erase( this->owner );
    }

    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<commit_msg>Add missing check when validating asset creation<commit_after>#include <bts/blockchain/asset_operations.hpp>
#include <bts/blockchain/exceptions.hpp>
#include <bts/blockchain/pending_chain_state.hpp>

namespace bts { namespace blockchain {

bool is_power_of_ten( uint64_t n )
{
    switch( n )
    {
        case 1ll:
        case 10ll:
        case 100ll:
        case 1000ll:
        case 10000ll:
        case 100000ll:
        case 1000000ll:
        case 10000000ll:
        case 100000000ll:
        case 1000000000ll:
        case 10000000000ll:
        case 100000000000ll:
        case 1000000000000ll:
        case 10000000000000ll:
        case 100000000000000ll:
        case 1000000000000000ll:
            return true;
        default:
            return false;
    }
}

void create_asset_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    if( !eval_state._pending_state->is_valid_symbol_name( this->symbol ) )
        FC_CAPTURE_AND_THROW( invalid_asset_symbol, (symbol) );

    const auto dot_pos = this->symbol.find('.');
    if( dot_pos != string::npos )
    {
        string parent_symbol = this->symbol.substr( 0, dot_pos );
        oasset_record parent_asset_record = eval_state._pending_state->get_asset_record( parent_symbol );
        FC_ASSERT( parent_asset_record.valid() && parent_asset_record->is_user_issued() );

        if( !eval_state.verify_authority( parent_asset_record->authority ) )
            FC_CAPTURE_AND_THROW( missing_signature, (parent_asset_record->authority) );
    }

    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( this->symbol );
    if( current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( asset_symbol_in_use, (symbol) );

    if( this->name.empty() )
        FC_CAPTURE_AND_THROW( invalid_asset_name, (this->name) );

    const asset_id_type asset_id = eval_state._pending_state->last_asset_id() + 1;
    current_asset_record = eval_state._pending_state->get_asset_record( asset_id );
    if( current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( asset_id_in_use, (asset_id) );

    oaccount_record issuer_account_record;
    if( issuer_account_id != asset_record::market_issuer_id )
    {
        issuer_account_record = eval_state._pending_state->get_account_record( this->issuer_account_id );
        if( !issuer_account_record.valid() )
            FC_CAPTURE_AND_THROW( unknown_account_id, (issuer_account_id) );
    }

    if( this->maximum_share_supply <= 0 || this->maximum_share_supply > BTS_BLOCKCHAIN_MAX_SHARES )
        FC_CAPTURE_AND_THROW( invalid_asset_amount, (this->maximum_share_supply) );

    if( !is_power_of_ten( this->precision ) )
        FC_CAPTURE_AND_THROW( invalid_precision, (this->precision) );

    const asset reg_fee( eval_state._pending_state->get_asset_registration_fee( this->symbol.size() ), 0 );
    eval_state.min_fees[ reg_fee.asset_id ] += reg_fee.amount;

    asset_record new_record;

    new_record.id                 = eval_state._pending_state->new_asset_id();
    new_record.symbol             = this->symbol;

    new_record.issuer_id          = this->issuer_account_id;

    if( issuer_account_record.valid() )
    {
        new_record.authority.owners.insert( issuer_account_record->active_key() );
        new_record.authority.required = 1;
    }

    new_record.name               = this->name;
    new_record.description        = this->description;
    new_record.public_data        = this->public_data;

    new_record.precision          = this->precision;
    new_record.max_supply         = this->maximum_share_supply;

    new_record.registration_date  = eval_state._pending_state->now();
    new_record.last_update        = new_record.registration_date;

    eval_state._pending_state->store_asset_record( new_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void issue_asset_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( abs( this->amount.asset_id ) );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id, (amount.asset_id) );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( !eval_state.verify_authority( current_asset_record->authority ) )
        FC_CAPTURE_AND_THROW( missing_signature, (current_asset_record->authority) );

    if( this->amount.amount <= 0 )
        FC_CAPTURE_AND_THROW( negative_issue, (amount) );

    if( this->amount.asset_id > 0 )
    {
        if( this->amount.amount > current_asset_record->max_supply - current_asset_record->current_supply )
            FC_CAPTURE_AND_THROW( over_issue, (amount)(*current_asset_record) );

        current_asset_record->current_supply += this->amount.amount;
    }
    else
    {
        if( this->amount.amount > current_asset_record->collected_fees )
            FC_CAPTURE_AND_THROW( amount_too_large, (amount)(*current_asset_record) );

        current_asset_record->collected_fees -= this->amount.amount;
    }

    eval_state.add_balance( asset( this->amount.amount, abs( this->amount.asset_id ) ) );

    current_asset_record->last_update = eval_state._pending_state->now();
    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void asset_update_properties_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( this->asset_id );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id, (this->asset_id) );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( !eval_state.verify_authority( current_asset_record->authority ) )
        FC_CAPTURE_AND_THROW( missing_signature, (current_asset_record->authority) );

    // Reject no-ops
    FC_ASSERT( this->issuer_id.valid()
               || this->name.valid()
               || this->description.valid()
               || this->public_data.valid()
               || this->precision.valid()
               || this->max_supply.valid()
               || this->withdrawal_fee.valid()
               || this->market_fee_rate.valid() );

    if( this->issuer_id.valid() )
    {
        const oaccount_record account_record = eval_state._pending_state->get_account_record( *this->issuer_id );
        if( !account_record.valid() )
            FC_CAPTURE_AND_THROW( unknown_account_id, (*this->issuer_id) );

        current_asset_record->issuer_id = *this->issuer_id;
    }

    if( this->name.valid() )
    {
        if( this->name->empty() )
            FC_CAPTURE_AND_THROW( invalid_asset_name, (*this->name) );

        current_asset_record->name = *this->name;
    }

    if( this->description.valid() )
        current_asset_record->description = *this->description;

    if( this->public_data.valid() )
        current_asset_record->public_data = *this->public_data;

    if( this->precision.valid() )
    {
        if( current_asset_record->current_supply != 0 )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( !is_power_of_ten( *this->precision ) )
            FC_CAPTURE_AND_THROW( invalid_precision, (*this->precision) );

        current_asset_record->precision = *this->precision;
    }

    if( this->max_supply.valid() )
    {
        if( current_asset_record->current_supply != 0 && !current_asset_record->flag_is_active( asset_record::dynamic_max_supply ) )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( *this->max_supply < current_asset_record->current_supply || *this->max_supply > BTS_BLOCKCHAIN_MAX_SHARES )
            FC_CAPTURE_AND_THROW( invalid_asset_amount, (*this->max_supply) );

        current_asset_record->max_supply = *this->max_supply;
    }

    if( this->withdrawal_fee.valid() )
    {
        if( current_asset_record->current_supply != 0 && !current_asset_record->flag_is_active( asset_record::dynamic_fees ) )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( *this->withdrawal_fee < 0 || *this->withdrawal_fee > current_asset_record->max_supply )
            FC_CAPTURE_AND_THROW( invalid_asset_amount, (*this->withdrawal_fee) );

        current_asset_record->withdrawal_fee = *this->withdrawal_fee;
    }

    if( this->market_fee_rate.valid() )
    {
        if( current_asset_record->current_supply != 0 && !current_asset_record->flag_is_active( asset_record::dynamic_fees ) )
            FC_CAPTURE_AND_THROW( outstanding_shares_exist, (current_asset_record->current_supply) );

        if( *this->market_fee_rate > BTS_BLOCKCHAIN_MAX_UIA_MARKET_FEE_RATE )
            FC_CAPTURE_AND_THROW( invalid_fee_rate, (*this->market_fee_rate) );

        current_asset_record->market_fee_rate = *this->market_fee_rate;
    }

    current_asset_record->last_update = eval_state._pending_state->now();
    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void asset_update_permissions_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( this->asset_id );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id, (this->asset_id) );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( !eval_state.verify_authority( current_asset_record->authority ) )
        FC_CAPTURE_AND_THROW( missing_signature, (current_asset_record->authority) );

    // Reject no-ops
    FC_ASSERT( this->authority.valid()
               || this->authority_flag_permissions.valid()
               || this->active_flags.valid() );

    if( this->authority.valid() )
    {
        if( this->authority->required < 1 || this->authority->owners.empty() )
            FC_CAPTURE_AND_THROW( invalid_authority, (*this->authority) );

        current_asset_record->authority = *this->authority;
    }

    if( this->authority_flag_permissions.valid() )
    {
        if( current_asset_record->current_supply != 0 )
        {
            for( size_t i = 0; i < sizeof( current_asset_record->authority_flag_permissions ) * 8; ++i )
            {
                const auto permission = static_cast<asset_record::flag_enum>( 1 << i );
                const bool requesting_permission = *this->authority_flag_permissions & permission;
                if( requesting_permission && !current_asset_record->authority_has_flag_permission( permission ) )
                    FC_CAPTURE_AND_THROW( outstanding_shares_exist, (permission) );
            }
        }

        current_asset_record->authority_flag_permissions = *this->authority_flag_permissions;
    }

    if( this->active_flags.valid() )
    {
        for( size_t i = 0; i < sizeof( current_asset_record->active_flags ) * 8; ++i )
        {
            const auto permission = static_cast<asset_record::flag_enum>( 1 << i );
            const bool activating_permission = *this->active_flags & permission;
            if( activating_permission && !current_asset_record->authority_has_flag_permission( permission ) )
                FC_CAPTURE_AND_THROW( permission_not_available, (permission) );
        }

        current_asset_record->active_flags = *this->active_flags;
    }

    current_asset_record->last_update = eval_state._pending_state->now();
    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

void asset_update_whitelist_operation::evaluate( transaction_evaluation_state& eval_state )const
{ try {
    oasset_record current_asset_record = eval_state._pending_state->get_asset_record( abs( this->asset_id ) );
    if( !current_asset_record.valid() )
        FC_CAPTURE_AND_THROW( unknown_asset_id );

    if( !current_asset_record->is_user_issued() )
        FC_CAPTURE_AND_THROW( not_user_issued, (*current_asset_record) );

    if( this->asset_id > 0 )
    {
        FC_ASSERT( current_asset_record->flag_is_active( asset_record::restricted_deposits ) );
        current_asset_record->whitelist.insert( this->owner );
    }
    else
    {
        current_asset_record->whitelist.erase( this->owner );
    }

    eval_state._pending_state->store_asset_record( *current_asset_record );
} FC_CAPTURE_AND_RETHROW( (*this) ) }

} } // bts::blockchain
<|endoftext|>


<commit_before>// Copyright (C) 2012  JINMEI Tatuya
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <query_repository.h>
#include <query_context.h>
#include <asio_message_manager.h>
#include <dispatcher.h>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>

#include <cstring>
#include <iostream>
#include <vector>
#include <stdexcept>

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

using namespace std;
using namespace Queryperf;
using namespace boost::posix_time;
using boost::lexical_cast;
using boost::shared_ptr;

namespace {
void
usage() {
    cerr << "Usage: queryperf++ [-d datafile]" << endl;
    exit(1);
}

void*
runQueryperf(void* arg) {
    Dispatcher* disp = static_cast<Dispatcher*>(arg);
    disp->run();
    return (NULL);
}

typedef shared_ptr<QueryRepository> QueryRepositoryPtr;
typedef shared_ptr<ASIOMessageManager> ASIOMessageManagerPtr;
typedef shared_ptr<QueryContextCreator> QueryContextCreatorPtr;
typedef shared_ptr<Dispatcher> DispatcherPtr;
}

int
main(int argc, char* argv[]) {
    const char* data_file = NULL;
    size_t num_threads = 1;

    int ch;
    while ((ch = getopt(argc, argv, "d:n:")) != -1) {
        switch (ch) {
        case 'd':
            data_file = optarg;
            break;
        case 'n':
            num_threads = lexical_cast<size_t>(optarg);
            break;
        case '?':
        default :
            usage();
        }
    }
    if (data_file == NULL) {
        cerr << "data file must be explicitly specified by -d for now" << endl;
        exit(1);
    }

    try {
        vector<QueryRepositoryPtr> repositories;
        vector<ASIOMessageManagerPtr> msg_mgrs;
        vector<QueryContextCreatorPtr> ctx_creators;
        vector<DispatcherPtr> dispatchers;
        vector<pthread_t> threads;

        // Prepare
        for (size_t i = 0; i < num_threads; ++i) {
            repositories.push_back(QueryRepositoryPtr(new QueryRepository(
                                                          data_file)));
            msg_mgrs.push_back(ASIOMessageManagerPtr(new ASIOMessageManager));
            ctx_creators.push_back(QueryContextCreatorPtr(
                                       new QueryContextCreator(
                                           *repositories.back())));
            dispatchers.push_back(DispatcherPtr(new Dispatcher(
                                                    *msg_mgrs.back(),
                                                    *ctx_creators.back())));
        }

        // Run
        for (size_t i = 0; i < num_threads; ++i) {
            pthread_t th = NULL;
            const int error = pthread_create(&th, NULL, runQueryperf,
                                             dispatchers[i].get());
            if (error != 0) {
                throw runtime_error(
                    string("Failed to create a worker thread: ") +
                    strerror(error));
            }
            threads.push_back(th);
        }

        for (size_t i = 0; i < num_threads; ++i) {
            const int error = pthread_join(threads[i], NULL);
            if (error != 0) {
                // if join failed, we warn about it and just continue anyway
                cerr << "pthread_join failed: " << strerror(error) << endl;
            }
        }

        for (size_t i = 0; i < num_threads; ++i) {
            const Dispatcher& disp = *dispatchers[i];
            cout << "  Queries sent:         " << disp.getQueriesSent()
                 << " queries\n";
            cout << "  Queries completed:    " << disp.getQueriesCompleted()
                 << " queries\n";
            cout << "\n";

            cout << "  Started at:           " << disp.getStartTime() << endl;
            cout << "  Finished at:          " << disp.getEndTime() << endl;
            cout << "\n";

            const time_duration duration = disp.getEndTime() -
                disp.getStartTime();
            const double qps = disp.getQueriesCompleted() / (
                static_cast<double>(duration.total_microseconds()) / 1000000);
            cout.precision(6);
            cout << "  Queries per second:   " << fixed << qps << " qps\n";
            cout << endl;
        }
    } catch (const exception& ex) {
        cerr << "Unexpected failure: " << ex.what() << endl;
        return (1);
    }

    return (0);
}
<commit_msg>don't assume thread_t is a pointer and stop initializing it to NULL.<commit_after>// Copyright (C) 2012  JINMEI Tatuya
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <query_repository.h>
#include <query_context.h>
#include <asio_message_manager.h>
#include <dispatcher.h>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>

#include <cstring>
#include <iostream>
#include <vector>
#include <stdexcept>

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

using namespace std;
using namespace Queryperf;
using namespace boost::posix_time;
using boost::lexical_cast;
using boost::shared_ptr;

namespace {
void
usage() {
    cerr << "Usage: queryperf++ [-d datafile]" << endl;
    exit(1);
}

void*
runQueryperf(void* arg) {
    Dispatcher* disp = static_cast<Dispatcher*>(arg);
    disp->run();
    return (NULL);
}

typedef shared_ptr<QueryRepository> QueryRepositoryPtr;
typedef shared_ptr<ASIOMessageManager> ASIOMessageManagerPtr;
typedef shared_ptr<QueryContextCreator> QueryContextCreatorPtr;
typedef shared_ptr<Dispatcher> DispatcherPtr;
}

int
main(int argc, char* argv[]) {
    const char* data_file = NULL;
    size_t num_threads = 1;

    int ch;
    while ((ch = getopt(argc, argv, "d:n:")) != -1) {
        switch (ch) {
        case 'd':
            data_file = optarg;
            break;
        case 'n':
            num_threads = lexical_cast<size_t>(optarg);
            break;
        case '?':
        default :
            usage();
        }
    }
    if (data_file == NULL) {
        cerr << "data file must be explicitly specified by -d for now" << endl;
        exit(1);
    }

    try {
        vector<QueryRepositoryPtr> repositories;
        vector<ASIOMessageManagerPtr> msg_mgrs;
        vector<QueryContextCreatorPtr> ctx_creators;
        vector<DispatcherPtr> dispatchers;
        vector<pthread_t> threads;

        // Prepare
        for (size_t i = 0; i < num_threads; ++i) {
            repositories.push_back(QueryRepositoryPtr(new QueryRepository(
                                                          data_file)));
            msg_mgrs.push_back(ASIOMessageManagerPtr(new ASIOMessageManager));
            ctx_creators.push_back(QueryContextCreatorPtr(
                                       new QueryContextCreator(
                                           *repositories.back())));
            dispatchers.push_back(DispatcherPtr(new Dispatcher(
                                                    *msg_mgrs.back(),
                                                    *ctx_creators.back())));
        }

        // Run
        for (size_t i = 0; i < num_threads; ++i) {
            pthread_t th;
            const int error = pthread_create(&th, NULL, runQueryperf,
                                             dispatchers[i].get());
            if (error != 0) {
                throw runtime_error(
                    string("Failed to create a worker thread: ") +
                    strerror(error));
            }
            threads.push_back(th);
        }

        for (size_t i = 0; i < num_threads; ++i) {
            const int error = pthread_join(threads[i], NULL);
            if (error != 0) {
                // if join failed, we warn about it and just continue anyway
                cerr << "pthread_join failed: " << strerror(error) << endl;
            }
        }

        for (size_t i = 0; i < num_threads; ++i) {
            const Dispatcher& disp = *dispatchers[i];
            cout << "  Queries sent:         " << disp.getQueriesSent()
                 << " queries\n";
            cout << "  Queries completed:    " << disp.getQueriesCompleted()
                 << " queries\n";
            cout << "\n";

            cout << "  Started at:           " << disp.getStartTime() << endl;
            cout << "  Finished at:          " << disp.getEndTime() << endl;
            cout << "\n";

            const time_duration duration = disp.getEndTime() -
                disp.getStartTime();
            const double qps = disp.getQueriesCompleted() / (
                static_cast<double>(duration.total_microseconds()) / 1000000);
            cout.precision(6);
            cout << "  Queries per second:   " << fixed << qps << " qps\n";
            cout << endl;
        }
    } catch (const exception& ex) {
        cerr << "Unexpected failure: " << ex.what() << endl;
        return (1);
    }

    return (0);
}
<|endoftext|>


<commit_before>// Copyright 2014 BVLC and contributors.

#include <algorithm>
#include <cfloat>
#include <vector>

#include "caffe/layer.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/filler.hpp"
//#include "caffe/PoolType.h"

#include <fstream>

using std::max;
using std::min;

namespace caffe {

 template<typename Dtype>
 void PoolingLayer<Dtype>::LoadPoolingStructure() {

   int n_pooled_elements, c, i, k;

   int top_size = pooled_width_*pooled_height_;//36;

    std::ifstream inFile(pooling_structure_file_.c_str());

    // shoud it be with the num? pooling_structure_.Reshape(bottom[0]->num(), channels_, pooled_height_, pooled_width_);
    pooling_structure_.Reshape(channels_, pooled_height_*pooled_width_/*map_size*/, height_, width_); // I will use masks instead of indexing for efficiency

    //fill the structure with zeros
    FillerParameter filler_param;
	filler_param.set_value(0.);
    ConstantFiller<Dtype> filler(filler_param);
    filler.Fill(&(pooling_structure_));

	pooling_structure_.Update();

    Dtype* pooling_structure = pooling_structure_.mutable_cpu_data();

    int x_coordinate, y_coordinate;

    if (inFile.is_open()) {

      //load the mutable structure with ones where necessary
      for (c = 0; c < channels_; ++c) {
		for (i = 0; i < top_size; ++i) {

			//fill it with zeros
			/*for (int ph = 0; ph < height_; ++ph) {
				for (int pw = 0; pw < width_; ++pw) {
					pooling_structure[ph * width_ + pw] = 0;
				}
			}*/

			inFile >> n_pooled_elements;

			for (k = 0; k < n_pooled_elements; ++k) {
			  inFile >> x_coordinate;
			  inFile >> y_coordinate;

			  //take care not to overstep the boundaries
			  x_coordinate = min(x_coordinate, width_- 1);
			  y_coordinate = min(y_coordinate, height_- 1);

			  pooling_structure[y_coordinate*width_ + x_coordinate] = 1;

			}

			pooling_structure += pooling_structure_.offset(0,1); //move through map neurons
		}
		//pooling_structure += pooling_structure_.offset(1); //move through channels
      }
    }

    inFile.close();
 }

template <typename Dtype>
void PoolingLayer<Dtype>::SetUp(const vector<Blob<Dtype>*>& bottom,
      vector<Blob<Dtype>*>* top) {
  CHECK_EQ(bottom.size(), 1) << "PoolingLayer takes a single blob as input.";
  CHECK_EQ(top->size(), 1) << "PoolingLayer takes a single blob as output.";
  kernel_size_ = this->layer_param_.pooling_param().kernel_size();
  stride_ = this->layer_param_.pooling_param().stride();
  pad_ = this->layer_param_.pooling_param().pad();
  pooling_structure_file_= this->layer_param_.pooling_param().pooling_structure_file();

  if (pad_ != 0) {
    CHECK_EQ(this->layer_param_.pooling_param().pool(),
             PoolingParameter_PoolMethod_AVE)
        << "Padding implemented only for average pooling.";
  }
  channels_ = bottom[0]->channels();
  height_ = bottom[0]->height();
  width_ = bottom[0]->width();
  pooled_height_ = static_cast<int>(ceil(static_cast<float>(
      height_ + 2 * pad_ - kernel_size_) / stride_)) + 1;
  pooled_width_ = static_cast<int>(ceil(static_cast<float>(
      width_ + 2 * pad_ - kernel_size_) / stride_)) + 1;
  (*top)[0]->Reshape(bottom[0]->num(), channels_, pooled_height_,
      pooled_width_);
  // If stochastic pooling, we will initialize the random index part.
  if (this->layer_param_.pooling_param().pool() ==
      PoolingParameter_PoolMethod_STOCHASTIC) {
    rand_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_,
      pooled_width_);
  }
  // If selective max pooling, we will initialize the random index part.
  if (this->layer_param_.pooling_param().pool() ==
    PoolingParameter_PoolMethod_MAX_SEL) {

    LoadPoolingStructure();

  }
}

// TODO(Yangqing): Is there a faster way to do pooling in the channel-first
// case?
template <typename Dtype>
Dtype PoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
      vector<Blob<Dtype>*>* top) {
  const Dtype* bottom_data = bottom[0]->cpu_data();
  Dtype* top_data = (*top)[0]->mutable_cpu_data();
  const Dtype* pooling_structure;

  // Different pooling methods. We explicitly do the switch outside the for
  // loop to save time, although this results in more codes.
  int top_count = (*top)[0]->count();
  switch (this->layer_param_.pooling_param().pool()) {
  case PoolingParameter_PoolMethod_MAX:
    // Initialize
    for (int i = 0; i < top_count; ++i) {
      top_data[i] = -FLT_MAX;
    }
    // The main loop
    for (int n = 0; n < bottom[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_;
            int wstart = pw * stride_;
            int hend = min(hstart + kernel_size_, height_);
            int wend = min(wstart + kernel_size_, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                top_data[ph * pooled_width_ + pw] =
                  max(top_data[ph * pooled_width_ + pw],
                      bottom_data[h * width_ + w]);
              }
            }
          }
        }
        // compute offset
        bottom_data += bottom[0]->offset(0, 1);
        top_data += (*top)[0]->offset(0, 1);
      }
    }
    break;
  case PoolingParameter_PoolMethod_AVE:
    for (int i = 0; i < top_count; ++i) {
      top_data[i] = 0;
    }
    // The main loop
    for (int n = 0; n < bottom[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_ - pad_;
            int wstart = pw * stride_ - pad_;
            int hend = min(hstart + kernel_size_, height_ + pad_);
            int wend = min(wstart + kernel_size_, width_ + pad_);
            int pool_size = (hend - hstart) * (wend - wstart);
            hstart = max(hstart, 0);
            wstart = max(wstart, 0);
            hend = min(hend, height_);
            wend = min(wend, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                top_data[ph * pooled_width_ + pw] +=
                    bottom_data[h * width_ + w];
              }
            }
            top_data[ph * pooled_width_ + pw] /= pool_size;
          }
        }
        // compute offset
        bottom_data += bottom[0]->offset(0, 1);
        top_data += (*top)[0]->offset(0, 1);
      }
    }
    break;
    case PoolingParameter_PoolMethod_MAX_SEL:

      pooling_structure  = pooling_structure_.cpu_data();

    // Initialize
    for (int i = 0; i < top_count; ++i) {
      top_data[i] = -FLT_MAX;
    }

    // The main loop
    for (int n = 0; n < bottom[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
	for (int nk = 0; nk < pooled_height_*pooled_width_; ++nk) //go through the neuron maps
	{
	  for (int h = 0; h < height_; ++h) {
	    for (int w = 0; w < width_; ++w) {
	      if(pooling_structure[h * width_ + w] == 1){
		//take this input into account
		  top_data[nk] =
			  max(top_data[nk],
			  bottom_data[h * width_ + w]);
	      }

	    }
	  }
	  pooling_structure += pooling_structure_.offset(0,1); //move through map neurons
      }
      //pooling_structure += pooling_structure_.offset(1); //move through channels
      bottom_data += bottom[0]->offset(0, 1);
      top_data += (*top)[0]->offset(0, 1);
      }
    }

	//set those already not set to 0
	for (int i = 0; i < top_count; ++i) {
      if(top_data[i] == -FLT_MAX)
		top_data[i] = 0;
    }
   break;
  case PoolingParameter_PoolMethod_STOCHASTIC:
    NOT_IMPLEMENTED;
    break;
  default:
    LOG(FATAL) << "Unknown pooling method.";
  }
  return Dtype(0.);
}

template <typename Dtype>
void PoolingLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
      const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
  if (!propagate_down) {
    return;
  }
  const Dtype* top_diff = top[0]->cpu_diff();
  const Dtype* top_data = top[0]->cpu_data();
  const Dtype* bottom_data = (*bottom)[0]->cpu_data();
  Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
  Dtype* pooling_structure; // = this->pooling_structure_.mutable_cpu_data();
  // Different pooling methods. We explicitly do the switch outside the for
  // loop to save time, although this results in more codes.
  memset(bottom_diff, 0, (*bottom)[0]->count() * sizeof(Dtype));
  switch (this->layer_param_.pooling_param().pool()) {
  case PoolingParameter_PoolMethod_MAX:
    // The main loop
    for (int n = 0; n < top[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_;
            int wstart = pw * stride_;
            int hend = min(hstart + kernel_size_, height_);
            int wend = min(wstart + kernel_size_, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                bottom_diff[h * width_ + w] +=
                    top_diff[ph * pooled_width_ + pw] *
                    (bottom_data[h * width_ + w] ==
                        top_data[ph * pooled_width_ + pw]);
              }
            }
          }
        }
        // offset
        bottom_data += (*bottom)[0]->offset(0, 1);
        top_data += top[0]->offset(0, 1);
        bottom_diff += (*bottom)[0]->offset(0, 1);
        top_diff += top[0]->offset(0, 1);
      }
    }
    break;
  case PoolingParameter_PoolMethod_AVE:
    // The main loop
    for (int n = 0; n < top[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_ - pad_;
            int wstart = pw * stride_ - pad_;
            int hend = min(hstart + kernel_size_, height_ + pad_);
            int wend = min(wstart + kernel_size_, width_ + pad_);
            int pool_size = (hend - hstart) * (wend - wstart);
            hstart = max(hstart, 0);
            wstart = max(wstart, 0);
            hend = min(hend, height_);
            wend = min(wend, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                bottom_diff[h * width_ + w] +=
                  top_diff[ph * pooled_width_ + pw] / pool_size;
              }
            }
          }
        }
        // offset
        bottom_data += (*bottom)[0]->offset(0, 1);
        top_data += top[0]->offset(0, 1);
        bottom_diff += (*bottom)[0]->offset(0, 1);
        top_diff += top[0]->offset(0, 1);
      }
    }
    break;
    case PoolingParameter_PoolMethod_MAX_SEL:

      pooling_structure = this->pooling_structure_.mutable_cpu_data();

    // The main loop
    for (int n = 0; n < (*bottom)[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
	for (int nk = 0; nk < pooled_height_*pooled_width_; ++nk) //go through the neuron maps
	{
	  for (int h = 0; h < height_; ++h) {
	    for (int w = 0; w < width_; ++w) {
	      if(pooling_structure[h * width_ + w] == 1){
		//take this input into account
		  bottom_diff[h * width_ + w] +=
                    top_diff[nk] *
                    (bottom_data[h * width_ + w] ==
                        top_data[nk]);
	      }

	    }
	  }
	  pooling_structure += pooling_structure_.offset(0,1); //move through map neurons
	}

	//pooling_structure += pooling_structure_.offset(1); //move through channels
	//bottom_data += bottom[0]->offset(0, 1);
	//top_data += (*top)[0]->offset(0, 1);
	bottom_data += (*bottom)[0]->offset(0, 1);
	top_data += top[0]->offset(0, 1);
	bottom_diff += (*bottom)[0]->offset(0, 1);
	top_diff += top[0]->offset(0, 1);
      }
    }
    break;
  case PoolingParameter_PoolMethod_STOCHASTIC:
    NOT_IMPLEMENTED;
    break;
  default:
    LOG(FATAL) << "Unknown pooling method.";
  }
}

INSTANTIATE_CLASS(PoolingLayer);

}  // namespace caffe
<commit_msg>Changed the type of the 0 assigned to unused pooling neurons.<commit_after>// Copyright 2014 BVLC and contributors.

#include <algorithm>
#include <cfloat>
#include <vector>

#include "caffe/layer.hpp"
#include "caffe/vision_layers.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/filler.hpp"
//#include "caffe/PoolType.h"

#include <fstream>

using std::max;
using std::min;

namespace caffe {

 template<typename Dtype>
 void PoolingLayer<Dtype>::LoadPoolingStructure() {

   int n_pooled_elements, c, i, k;

   int top_size = pooled_width_*pooled_height_;//36;

    std::ifstream inFile(pooling_structure_file_.c_str());

    // shoud it be with the num? pooling_structure_.Reshape(bottom[0]->num(), channels_, pooled_height_, pooled_width_);
    pooling_structure_.Reshape(channels_, pooled_height_*pooled_width_/*map_size*/, height_, width_); // I will use masks instead of indexing for efficiency

    //fill the structure with zeros
    FillerParameter filler_param;
	filler_param.set_value(0.);
    ConstantFiller<Dtype> filler(filler_param);
    filler.Fill(&(pooling_structure_));

	pooling_structure_.Update();

    Dtype* pooling_structure = pooling_structure_.mutable_cpu_data();

    int x_coordinate, y_coordinate;

    if (inFile.is_open()) {

      //load the mutable structure with ones where necessary
      for (c = 0; c < channels_; ++c) {
		for (i = 0; i < top_size; ++i) {

			//fill it with zeros
			/*for (int ph = 0; ph < height_; ++ph) {
				for (int pw = 0; pw < width_; ++pw) {
					pooling_structure[ph * width_ + pw] = 0;
				}
			}*/

			inFile >> n_pooled_elements;

			for (k = 0; k < n_pooled_elements; ++k) {
			  inFile >> x_coordinate;
			  inFile >> y_coordinate;

			  //take care not to overstep the boundaries
			  x_coordinate = min(x_coordinate, width_- 1);
			  y_coordinate = min(y_coordinate, height_- 1);

			  pooling_structure[y_coordinate*width_ + x_coordinate] = 1;

			}

			pooling_structure += pooling_structure_.offset(0,1); //move through map neurons
		}
		//pooling_structure += pooling_structure_.offset(1); //move through channels
      }
    }

    inFile.close();
 }

template <typename Dtype>
void PoolingLayer<Dtype>::SetUp(const vector<Blob<Dtype>*>& bottom,
      vector<Blob<Dtype>*>* top) {
  CHECK_EQ(bottom.size(), 1) << "PoolingLayer takes a single blob as input.";
  CHECK_EQ(top->size(), 1) << "PoolingLayer takes a single blob as output.";
  kernel_size_ = this->layer_param_.pooling_param().kernel_size();
  stride_ = this->layer_param_.pooling_param().stride();
  pad_ = this->layer_param_.pooling_param().pad();
  pooling_structure_file_= this->layer_param_.pooling_param().pooling_structure_file();

  if (pad_ != 0) {
    CHECK_EQ(this->layer_param_.pooling_param().pool(),
             PoolingParameter_PoolMethod_AVE)
        << "Padding implemented only for average pooling.";
  }
  channels_ = bottom[0]->channels();
  height_ = bottom[0]->height();
  width_ = bottom[0]->width();
  pooled_height_ = static_cast<int>(ceil(static_cast<float>(
      height_ + 2 * pad_ - kernel_size_) / stride_)) + 1;
  pooled_width_ = static_cast<int>(ceil(static_cast<float>(
      width_ + 2 * pad_ - kernel_size_) / stride_)) + 1;
  (*top)[0]->Reshape(bottom[0]->num(), channels_, pooled_height_,
      pooled_width_);
  // If stochastic pooling, we will initialize the random index part.
  if (this->layer_param_.pooling_param().pool() ==
      PoolingParameter_PoolMethod_STOCHASTIC) {
    rand_idx_.Reshape(bottom[0]->num(), channels_, pooled_height_,
      pooled_width_);
  }
  // If selective max pooling, we will initialize the random index part.
  if (this->layer_param_.pooling_param().pool() ==
    PoolingParameter_PoolMethod_MAX_SEL) {

    LoadPoolingStructure();

  }
}

// TODO(Yangqing): Is there a faster way to do pooling in the channel-first
// case?
template <typename Dtype>
Dtype PoolingLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
      vector<Blob<Dtype>*>* top) {
  const Dtype* bottom_data = bottom[0]->cpu_data();
  Dtype* top_data = (*top)[0]->mutable_cpu_data();
  const Dtype* pooling_structure;

  // Different pooling methods. We explicitly do the switch outside the for
  // loop to save time, although this results in more codes.
  int top_count = (*top)[0]->count();
  switch (this->layer_param_.pooling_param().pool()) {
  case PoolingParameter_PoolMethod_MAX:
    // Initialize
    for (int i = 0; i < top_count; ++i) {
      top_data[i] = -FLT_MAX;
    }
    // The main loop
    for (int n = 0; n < bottom[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_;
            int wstart = pw * stride_;
            int hend = min(hstart + kernel_size_, height_);
            int wend = min(wstart + kernel_size_, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                top_data[ph * pooled_width_ + pw] =
                  max(top_data[ph * pooled_width_ + pw],
                      bottom_data[h * width_ + w]);
              }
            }
          }
        }
        // compute offset
        bottom_data += bottom[0]->offset(0, 1);
        top_data += (*top)[0]->offset(0, 1);
      }
    }
    break;
  case PoolingParameter_PoolMethod_AVE:
    for (int i = 0; i < top_count; ++i) {
      top_data[i] = 0;
    }
    // The main loop
    for (int n = 0; n < bottom[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_ - pad_;
            int wstart = pw * stride_ - pad_;
            int hend = min(hstart + kernel_size_, height_ + pad_);
            int wend = min(wstart + kernel_size_, width_ + pad_);
            int pool_size = (hend - hstart) * (wend - wstart);
            hstart = max(hstart, 0);
            wstart = max(wstart, 0);
            hend = min(hend, height_);
            wend = min(wend, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                top_data[ph * pooled_width_ + pw] +=
                    bottom_data[h * width_ + w];
              }
            }
            top_data[ph * pooled_width_ + pw] /= pool_size;
          }
        }
        // compute offset
        bottom_data += bottom[0]->offset(0, 1);
        top_data += (*top)[0]->offset(0, 1);
      }
    }
    break;
    case PoolingParameter_PoolMethod_MAX_SEL:

      pooling_structure  = pooling_structure_.cpu_data();

    // Initialize
    for (int i = 0; i < top_count; ++i) {
      top_data[i] = -FLT_MAX;
    }

    // The main loop
    for (int n = 0; n < bottom[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
	for (int nk = 0; nk < pooled_height_*pooled_width_; ++nk) //go through the neuron maps
	{
	  for (int h = 0; h < height_; ++h) {
	    for (int w = 0; w < width_; ++w) {
	      if(pooling_structure[h * width_ + w] == 1){
		//take this input into account
		  top_data[nk] =
			  max(top_data[nk],
			  bottom_data[h * width_ + w]);
	      }

	    }
	  }
	  pooling_structure += pooling_structure_.offset(0,1); //move through map neurons
      }
      //pooling_structure += pooling_structure_.offset(1); //move through channels
      bottom_data += bottom[0]->offset(0, 1);
      top_data += (*top)[0]->offset(0, 1);
      }
    }

	//set those already not set to 0
	for (int i = 0; i < top_count; ++i) {
      if(top_data[i] == -FLT_MAX)
		top_data[i] = Dtype(0.);
    }
   break;
  case PoolingParameter_PoolMethod_STOCHASTIC:
    NOT_IMPLEMENTED;
    break;
  default:
    LOG(FATAL) << "Unknown pooling method.";
  }
  return Dtype(0.);
}

template <typename Dtype>
void PoolingLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
      const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
  if (!propagate_down) {
    return;
  }
  const Dtype* top_diff = top[0]->cpu_diff();
  const Dtype* top_data = top[0]->cpu_data();
  const Dtype* bottom_data = (*bottom)[0]->cpu_data();
  Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
  Dtype* pooling_structure; // = this->pooling_structure_.mutable_cpu_data();
  // Different pooling methods. We explicitly do the switch outside the for
  // loop to save time, although this results in more codes.
  memset(bottom_diff, 0, (*bottom)[0]->count() * sizeof(Dtype));
  switch (this->layer_param_.pooling_param().pool()) {
  case PoolingParameter_PoolMethod_MAX:
    // The main loop
    for (int n = 0; n < top[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_;
            int wstart = pw * stride_;
            int hend = min(hstart + kernel_size_, height_);
            int wend = min(wstart + kernel_size_, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                bottom_diff[h * width_ + w] +=
                    top_diff[ph * pooled_width_ + pw] *
                    (bottom_data[h * width_ + w] ==
                        top_data[ph * pooled_width_ + pw]);
              }
            }
          }
        }
        // offset
        bottom_data += (*bottom)[0]->offset(0, 1);
        top_data += top[0]->offset(0, 1);
        bottom_diff += (*bottom)[0]->offset(0, 1);
        top_diff += top[0]->offset(0, 1);
      }
    }
    break;
  case PoolingParameter_PoolMethod_AVE:
    // The main loop
    for (int n = 0; n < top[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
        for (int ph = 0; ph < pooled_height_; ++ph) {
          for (int pw = 0; pw < pooled_width_; ++pw) {
            int hstart = ph * stride_ - pad_;
            int wstart = pw * stride_ - pad_;
            int hend = min(hstart + kernel_size_, height_ + pad_);
            int wend = min(wstart + kernel_size_, width_ + pad_);
            int pool_size = (hend - hstart) * (wend - wstart);
            hstart = max(hstart, 0);
            wstart = max(wstart, 0);
            hend = min(hend, height_);
            wend = min(wend, width_);
            for (int h = hstart; h < hend; ++h) {
              for (int w = wstart; w < wend; ++w) {
                bottom_diff[h * width_ + w] +=
                  top_diff[ph * pooled_width_ + pw] / pool_size;
              }
            }
          }
        }
        // offset
        bottom_data += (*bottom)[0]->offset(0, 1);
        top_data += top[0]->offset(0, 1);
        bottom_diff += (*bottom)[0]->offset(0, 1);
        top_diff += top[0]->offset(0, 1);
      }
    }
    break;
    case PoolingParameter_PoolMethod_MAX_SEL:

      pooling_structure = this->pooling_structure_.mutable_cpu_data();

    // The main loop
    for (int n = 0; n < (*bottom)[0]->num(); ++n) {
      for (int c = 0; c < channels_; ++c) {
	for (int nk = 0; nk < pooled_height_*pooled_width_; ++nk) //go through the neuron maps
	{
	  for (int h = 0; h < height_; ++h) {
	    for (int w = 0; w < width_; ++w) {
	      if(pooling_structure[h * width_ + w] == 1){
		//take this input into account
		  bottom_diff[h * width_ + w] +=
                    top_diff[nk] *
                    (bottom_data[h * width_ + w] ==
                        top_data[nk]);
	      }

	    }
	  }
	  pooling_structure += pooling_structure_.offset(0,1); //move through map neurons
	}

	//pooling_structure += pooling_structure_.offset(1); //move through channels
	//bottom_data += bottom[0]->offset(0, 1);
	//top_data += (*top)[0]->offset(0, 1);
	bottom_data += (*bottom)[0]->offset(0, 1);
	top_data += top[0]->offset(0, 1);
	bottom_diff += (*bottom)[0]->offset(0, 1);
	top_diff += top[0]->offset(0, 1);
      }
    }
    break;
  case PoolingParameter_PoolMethod_STOCHASTIC:
    NOT_IMPLEMENTED;
    break;
  default:
    LOG(FATAL) << "Unknown pooling method.";
  }
}

INSTANTIATE_CLASS(PoolingLayer);

}  // namespace caffe
<|endoftext|>


<commit_before>/* Copyright 2009 SPARTA, Inc., dba Cobham Analytic Solutions
 *
 * This file is part of WATCHER.
 *
 *     WATCHER is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     WATCHER is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Watcher.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file main.cpp
 * @author Geoff Lawler <geoff.lawler@cobham.com>
 * @date 2009-07-15
 */
#include <iostream>
#include <QTimer>
#include <string>
#include <GL/glut.h>
#include <getopt.h>

#include "ui_watcher.h"
#include "watcherMainWindow.h"
#include "watcherScrollingGraphControl.h"

#include "logger.h"
#include "libconfig.h++"
#include "initConfig.h"
#include "singletonConfig.h"

using namespace std;
using namespace watcher;
using namespace libconfig;

int main(int argc, char *argv[])
{
    TRACE_ENTER();

    option options[] = {
        { "help", 0, NULL, 'h' },
        { "configFile", 1, NULL, 'f' },
        { 0, 0, NULL, 0 }
    };
    char i;
    while ((i = getopt_long(argc, argv, "hf:", options, NULL)) != -1)
        if (i=='h') {
            cout << "Usage : " << basename(argv[0]) << " -f,--configFile=cfgFile -h,--help" << endl;
            exit(EXIT_FAILURE);
        }

    string configFilename;
    SingletonConfig::lock();
    Config &config=SingletonConfig::instance();
    if (false==initConfig(config, argc, argv, configFilename))
    {
        cerr << "Error reading configuration file, unable to continue." << endl;
        cerr << "Usage: " << basename(argv[0]) << " [-f|--configFile] configfile [standard watcher arguments]" << endl;
        return 1;
    }
    SingletonConfig::setConfigFile(configFilename);
    SingletonConfig::unlock();

    string logConf("watcher.log.properties");
    if (!config.lookupValue("logProperties", logConf))
    {
        cerr << "Unable to find logproperties setting in the configuration file, using default: " << logConf << endl;
        config.getRoot().add("logProperties", Setting::TypeString)=logConf;
    }

    LOAD_LOG_PROPS(logConf);

    LOG_INFO("Logger initialized from file \"" << logConf << "\"");
    LOG_INFO("Although the legacy watcher code does not use it, so it is not overly valuable");

    QApplication::setColorSpec(QApplication::CustomColor);
    QApplication app(argc, argv);
    WatcherMainWindow *window = new WatcherMainWindow;
    Ui::MainWindow ui;
    ui.setupUi(window);

    ui.menuLayers->setTearOffEnabled(true);
    ui.menuView->setTearOffEnabled(true);

    QObject::connect(ui.quitButton, SIGNAL(clicked()), &app, SLOT(quit()));
    QObject::connect(&app, SIGNAL(aboutToQuit()), ui.manetGLViewWindow, SLOT(saveConfiguration()));

    // Is there a way to get this from within manetGLView via theApp or something?
    ui.manetGLViewWindow->setLayerMenu(ui.menuLayers);
    ui.manetGLViewWindow->setPlaybackSlider(ui.playbackSlider);

    //
    // Connect the scrolling graph dialog controller to other bits.
    //
    {
        WatcherScrollingGraphControl *sgc=WatcherScrollingGraphControl::getWatcherScrollingGraphControl();

        // Add the dyanmic graphs to this menu.
        sgc->setMenu(ui.menuGraph);

        QObject::connect(ui.manetGLViewWindow, SIGNAL(nodeDataInGraphsToggled(unsigned int)), sgc, SLOT(toggleNodeDataInGraphs(unsigned int)));
        QObject::connect(sgc, SIGNAL(nodeDataInGraphsToggled(unsigned int)), ui.manetGLViewWindow, SLOT(toggleNodeSelectedForGraph(unsigned int)));

        QObject::connect(ui.manetGLViewWindow, SIGNAL(nodeDataInGraphsShowed(unsigned int, bool)), sgc, SLOT(showNodeDataInGraphs(unsigned int, bool)));
        QObject::connect(sgc, SIGNAL(nodeDataInGraphsShowed(unsigned int, bool)), ui.manetGLViewWindow, SLOT(showNodeSelectedForGraph(unsigned int, bool)));
    }

    srand(time(NULL));

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    if (!ui.manetGLViewWindow->loadConfiguration())
    {
        LOG_FATAL("Error in cfg file, unable to continue");
        // write out what we have.
        SingletonConfig::saveConfig();
        TRACE_EXIT();
        return EXIT_FAILURE;
    }

    window->show();

    TRACE_EXIT();
    return app.exec();
}
<commit_msg>watcher: command line parameter parsing error was causing us to ignore '-c file' parameter. Which is not good.<commit_after>/* Copyright 2009 SPARTA, Inc., dba Cobham Analytic Solutions
 *
 * This file is part of WATCHER.
 *
 *     WATCHER is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     WATCHER is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Watcher.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file main.cpp
 * @author Geoff Lawler <geoff.lawler@cobham.com>
 * @date 2009-07-15
 */
#include <iostream>
#include <QTimer>
#include <string>
#include <GL/glut.h>
#include <getopt.h>

#include "ui_watcher.h"
#include "watcherMainWindow.h"
#include "watcherScrollingGraphControl.h"

#include "logger.h"
#include "libconfig.h++"
#include "initConfig.h"
#include "singletonConfig.h"

using namespace std;
using namespace watcher;
using namespace libconfig;

int main(int argc, char *argv[])
{
    TRACE_ENTER();

    for (int i=0; i!=argc; i++)
        if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help") || !strcmp(argv[i], "-?")) {
            cout << "Usage : " << basename(argv[0]) << " -c,--configFile=cfgFile -h,--help" << endl;
            exit(EXIT_FAILURE);
        }

    string configFilename;
    SingletonConfig::lock();
    Config &config=SingletonConfig::instance();
    if (false==initConfig(config, argc, argv, configFilename))
    {
        cerr << "Error reading configuration file, unable to continue." << endl;
        cerr << "Usage: " << basename(argv[0]) << " [-f|--configFile] configfile [standard watcher arguments]" << endl;
        return 1;
    }
    SingletonConfig::setConfigFile(configFilename);
    SingletonConfig::unlock();

    string logConf("watcher.log.properties");
    if (!config.lookupValue("logProperties", logConf))
    {
        cerr << "Unable to find logproperties setting in the configuration file, using default: " << logConf << endl;
        config.getRoot().add("logProperties", Setting::TypeString)=logConf;
    }

    LOAD_LOG_PROPS(logConf);

    LOG_INFO("Logger initialized from file \"" << logConf << "\"");
    LOG_INFO("Although the legacy watcher code does not use it, so it is not overly valuable");

    QApplication::setColorSpec(QApplication::CustomColor);
    QApplication app(argc, argv);
    WatcherMainWindow *window = new WatcherMainWindow;
    Ui::MainWindow ui;
    ui.setupUi(window);

    ui.menuLayers->setTearOffEnabled(true);
    ui.menuView->setTearOffEnabled(true);

    QObject::connect(ui.quitButton, SIGNAL(clicked()), &app, SLOT(quit()));
    QObject::connect(&app, SIGNAL(aboutToQuit()), ui.manetGLViewWindow, SLOT(saveConfiguration()));

    // Is there a way to get this from within manetGLView via theApp or something?
    ui.manetGLViewWindow->setLayerMenu(ui.menuLayers);
    ui.manetGLViewWindow->setPlaybackSlider(ui.playbackSlider);

    //
    // Connect the scrolling graph dialog controller to other bits.
    //
    {
        WatcherScrollingGraphControl *sgc=WatcherScrollingGraphControl::getWatcherScrollingGraphControl();

        // Add the dyanmic graphs to this menu.
        sgc->setMenu(ui.menuGraph);

        QObject::connect(ui.manetGLViewWindow, SIGNAL(nodeDataInGraphsToggled(unsigned int)), sgc, SLOT(toggleNodeDataInGraphs(unsigned int)));
        QObject::connect(sgc, SIGNAL(nodeDataInGraphsToggled(unsigned int)), ui.manetGLViewWindow, SLOT(toggleNodeSelectedForGraph(unsigned int)));

        QObject::connect(ui.manetGLViewWindow, SIGNAL(nodeDataInGraphsShowed(unsigned int, bool)), sgc, SLOT(showNodeDataInGraphs(unsigned int, bool)));
        QObject::connect(sgc, SIGNAL(nodeDataInGraphsShowed(unsigned int, bool)), ui.manetGLViewWindow, SLOT(showNodeSelectedForGraph(unsigned int, bool)));
    }

    srand(time(NULL));

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

    if (!ui.manetGLViewWindow->loadConfiguration())
    {
        LOG_FATAL("Error in cfg file, unable to continue");
        // write out what we have.
        SingletonConfig::saveConfig();
        TRACE_EXIT();
        return EXIT_FAILURE;
    }

    window->show();

    TRACE_EXIT();
    return app.exec();
}
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskLooperTest
#include "JPetTaskLooper/JPetTaskLooper.h"
#include "JPetCommonTools/JPetCommonTools.h"
#include "JPetOptionsGenerator/JPetOptionsGeneratorTools.h"
#include "JPetTaskIO/JPetTaskIO.h"
#include "JPetUserTask/JPetUserTask.h"

#include <boost/test/unit_test.hpp>

class TestTask : public JPetTask
{
public:
  explicit TestTask(const char* name = "") : JPetTask(name) {}
  bool init(const JPetParams&) override { return true; }
  bool run(const JPetDataInterface&) override
  {
    fRunCounter++;
    return true;
  }
  bool terminate(JPetParams&) override { return true; }
  int fRunCounter = 0;
};

class TestTaskRun20Times : public JPetTask
{
public:
  explicit TestTaskRun20Times(const char* name = "") : JPetTask(name) {}
  bool init(const JPetParams& paramsI) override
  {
    fParams = static_cast<const JPetParams&>(paramsI);
    return true;
  }
  bool run(const JPetDataInterface&) override
  {
    fRunCounter++;
    return true;
  }
  bool terminate(JPetParams& paramsO) override
  {
    auto& params = static_cast<JPetParams&>(paramsO);
    /// Here I set the condition that it should stop after 20th iteration, but it can be some other condition.
    if (fRunCounter == 20)
    {
      auto newOpts = params.getOptions();
      newOpts["StopIteration_bool"] = true;
      params = JPetParams(newOpts, nullptr);
    }
    else
    {
      params = fParams;
    }
    return true;
  }
  int fRunCounter = 0;
  JPetParams fParams;
};

class TestLooperUserTask : public JPetUserTask
{
public:
  TestLooperUserTask(const char* name = "") : JPetUserTask(name) {}
  virtual ~TestLooperUserTask() { ; }
  int fRunCounter = 0;

protected:
  bool init() { return true; }
  bool exec()
  {
    fRunCounter++;
    return true;
  }
  bool terminate()
  {
    /// Here I set the condition that it should stop after 100th iteration, but it can be some other condition.
    if (fRunCounter == 100)
    {
      auto newOpts = getOptions();
      newOpts["StopIteration_bool"] = true;
      fParams = JPetParams(newOpts, fParams.getParamManagerAsShared());
    }
    return true;
  }
};

BOOST_AUTO_TEST_SUITE(JPetTaskTestSuite)

BOOST_AUTO_TEST_CASE(my_test_false_predicate)
{
  using namespace jpet_options_generator_tools;
  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTask));
  JPetDataInterface nullDataObject;
  JPetParams inputParams;
  JPetParams outputParams;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTask*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, 0);
}

BOOST_AUTO_TEST_CASE(my_test_10_iterations)
{
  using namespace jpet_options_generator_tools;
  const int maxIter = 10;
  int counter = 0;
  auto condFunc = [maxIter, &counter](const JPetParams&) -> bool {
    if (counter < maxIter)
    {
      counter++;
      return true;
    }
    else
    {
      return false;
    }
  };
  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTask), condFunc);
  JPetDataInterface nullDataObject;
  JPetParams inputParams;
  JPetParams outputParams;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTask*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, maxIter);
}

BOOST_AUTO_TEST_CASE(my_test_10_iterations_with_predefined_function)
{
  const int maxIter = 10;
  auto condFunc = JPetTaskLooper::getMaxIterationPredicate(maxIter);

  using namespace jpet_options_generator_tools;
  std::vector<jpet_options_tools::OptsStrAny> opts;
  auto opt = getDefaultOptions();
  opts.push_back(opt);
  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTask), condFunc);
  JPetDataInterface nullDataObject;
  JPetParams inputParams;
  JPetParams outputParams;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTask*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, maxIter);
}

BOOST_AUTO_TEST_CASE(my_test_withSettingOptions)
{
  std::string optName = "StopIteration_bool";
  auto condFunc = JPetTaskLooper::getStopOnOptionPredicate(optName);

  using namespace jpet_options_generator_tools;
  auto opt = getDefaultOptions();
  opt[optName] = false;
  JPetParams inputParams = JPetParams(opt, nullptr);

  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTaskRun20Times), condFunc);
  JPetDataInterface nullDataObject;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTaskRun20Times*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, 20);
}

BOOST_AUTO_TEST_CASE(my_test_JPetTaskIO)
{
  std::string optName = "StopIteration_bool";
  auto condFunc = JPetTaskLooper::getStopOnOptionPredicate(optName);

  using namespace jpet_options_generator_tools;

  auto task = jpet_common_tools::make_unique<JPetTaskIO>("bla", "", "");
  task->addSubTask(std::unique_ptr<JPetTask>(new TestTaskRun20Times));
  JPetTaskLooper looper("bla", std::move(task), condFunc);

  auto opt = getDefaultOptions();
  opt[optName] = false;
  JPetParams inputParams;
  inputParams = JPetParams(opt, nullptr);

  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  JPetDataInterface nullDataObject;
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);

  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);

  auto subTaskIO = dynamic_cast<JPetTaskIO*>(looper.getSubTasks()[0]);
  auto subSubTask = dynamic_cast<TestTaskRun20Times*>(subTaskIO->getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subSubTask->fRunCounter, 20);
}

BOOST_AUTO_TEST_CASE(my_test_JPetTaskIO_2)
{
  const int maxIter = 10;
  auto condFunc = JPetTaskLooper::getMaxIterationPredicate(maxIter);
  using namespace jpet_options_generator_tools;

  auto task = jpet_common_tools::make_unique<JPetTaskIO>("IOBla", "", "");
  task->addSubTask(jpet_common_tools::make_unique<TestLooperUserTask>("userBla"));
  JPetTaskLooper looper("looperBla", std::move(task), condFunc);

  auto opt = getDefaultOptions();
  JPetParams inputParams;
  inputParams = JPetParams(opt, nullptr);

  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  JPetDataInterface nullDataObject;
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);

  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);

  auto subTaskIO = dynamic_cast<JPetTaskIO*>(looper.getSubTasks()[0]);
  auto subSubTask = dynamic_cast<TestLooperUserTask*>(subTaskIO->getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subSubTask->fRunCounter, 10);
}

BOOST_AUTO_TEST_CASE(my_test_JPetTaskIO_3)
{
  std::string optName = "StopIteration_bool";
  auto condFunc = JPetTaskLooper::getStopOnOptionPredicate(optName);

  using namespace jpet_options_generator_tools;

  auto task = jpet_common_tools::make_unique<JPetTaskIO>("IOBla", "", "");
  task->addSubTask(jpet_common_tools::make_unique<TestLooperUserTask>("userBla"));
  JPetTaskLooper looper("looperBla", std::move(task), condFunc);

  auto opt = getDefaultOptions();
  opt[optName] = false;
  JPetParams inputParams;
  inputParams = JPetParams(opt, nullptr);

  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  JPetDataInterface nullDataObject;
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);

  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);

  auto subTaskIO = dynamic_cast<JPetTaskIO*>(looper.getSubTasks()[0]);
  auto subSubTask = dynamic_cast<TestLooperUserTask*>(subTaskIO->getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subSubTask->fRunCounter, 100);
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fix cppcheck issues<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskLooperTest
#include "JPetTaskLooper/JPetTaskLooper.h"
#include "JPetCommonTools/JPetCommonTools.h"
#include "JPetOptionsGenerator/JPetOptionsGeneratorTools.h"
#include "JPetTaskIO/JPetTaskIO.h"
#include "JPetUserTask/JPetUserTask.h"

#include <boost/test/unit_test.hpp>

class TestTask : public JPetTask
{
public:
  explicit TestTask(const char* name = "") : JPetTask(name) {}
  bool init(const JPetParams&) override { return true; }
  bool run(const JPetDataInterface&) override
  {
    fRunCounter++;
    return true;
  }
  bool terminate(JPetParams&) override { return true; }
  int fRunCounter = 0;
};

class TestTaskRun20Times : public JPetTask
{
public:
  explicit TestTaskRun20Times(const char* name = "") : JPetTask(name) {}
  bool init(const JPetParams& paramsI) override
  {
    fParams = static_cast<const JPetParams&>(paramsI);
    return true;
  }
  bool run(const JPetDataInterface&) override
  {
    fRunCounter++;
    return true;
  }
  bool terminate(JPetParams& paramsO) override
  {
    auto& params = static_cast<JPetParams&>(paramsO);
    /// Here I set the condition that it should stop after 20th iteration, but it can be some other condition.
    if (fRunCounter == 20)
    {
      auto newOpts = params.getOptions();
      newOpts["StopIteration_bool"] = true;
      params = JPetParams(newOpts, nullptr);
    }
    else
    {
      params = fParams;
    }
    return true;
  }
  int fRunCounter = 0;
  JPetParams fParams;
};

class TestLooperUserTask : public JPetUserTask
{
public:
  explicit TestLooperUserTask(const char* name = "") : JPetUserTask(name) {}
  virtual ~TestLooperUserTask() { ; }
  int fRunCounter = 0;

protected:
  bool init() { return true; }
  bool exec()
  {
    fRunCounter++;
    return true;
  }
  bool terminate()
  {
    /// Here I set the condition that it should stop after 100th iteration, but it can be some other condition.
    if (fRunCounter == 100)
    {
      auto newOpts = getOptions();
      newOpts["StopIteration_bool"] = true;
      fParams = JPetParams(newOpts, fParams.getParamManagerAsShared());
    }
    return true;
  }
};

BOOST_AUTO_TEST_SUITE(JPetTaskTestSuite)

BOOST_AUTO_TEST_CASE(my_test_false_predicate)
{
  using namespace jpet_options_generator_tools;
  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTask));
  JPetDataInterface nullDataObject;
  JPetParams inputParams;
  JPetParams outputParams;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTask*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, 0);
}

BOOST_AUTO_TEST_CASE(my_test_10_iterations)
{
  using namespace jpet_options_generator_tools;
  const int maxIter = 10;
  int counter = 0;
  auto condFunc = [&counter](const JPetParams&) -> bool {
    // cppcheck-suppress knownConditionTrueFalse
    if (counter < maxIter)
    {
      counter++;
      return true;
    }
    else
    {
      return false;
    }
  };
  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTask), condFunc);
  JPetDataInterface nullDataObject;
  JPetParams inputParams;
  JPetParams outputParams;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTask*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, maxIter);
}

BOOST_AUTO_TEST_CASE(my_test_10_iterations_with_predefined_function)
{
  const int maxIter = 10;
  auto condFunc = JPetTaskLooper::getMaxIterationPredicate(maxIter);

  using namespace jpet_options_generator_tools;
  std::vector<jpet_options_tools::OptsStrAny> opts;
  auto opt = getDefaultOptions();
  opts.push_back(opt);
  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTask), condFunc);
  JPetDataInterface nullDataObject;
  JPetParams inputParams;
  JPetParams outputParams;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTask*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, maxIter);
}

BOOST_AUTO_TEST_CASE(my_test_withSettingOptions)
{
  std::string optName = "StopIteration_bool";
  auto condFunc = JPetTaskLooper::getStopOnOptionPredicate(optName);

  using namespace jpet_options_generator_tools;
  auto opt = getDefaultOptions();
  opt[optName] = false;
  JPetParams inputParams = JPetParams(opt, nullptr);

  JPetTaskLooper looper("testTaskLooper", std::unique_ptr<JPetTask>(new TestTaskRun20Times), condFunc);
  JPetDataInterface nullDataObject;
  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);
  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);
  auto subTask = dynamic_cast<TestTaskRun20Times*>(looper.getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subTask->fRunCounter, 20);
}

BOOST_AUTO_TEST_CASE(my_test_JPetTaskIO)
{
  std::string optName = "StopIteration_bool";
  auto condFunc = JPetTaskLooper::getStopOnOptionPredicate(optName);

  using namespace jpet_options_generator_tools;

  auto task = jpet_common_tools::make_unique<JPetTaskIO>("bla", "", "");
  task->addSubTask(std::unique_ptr<JPetTask>(new TestTaskRun20Times));
  JPetTaskLooper looper("bla", std::move(task), condFunc);

  auto opt = getDefaultOptions();
  opt[optName] = false;
  JPetParams inputParams;
  inputParams = JPetParams(opt, nullptr);

  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  JPetDataInterface nullDataObject;
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);

  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);

  auto subTaskIO = dynamic_cast<JPetTaskIO*>(looper.getSubTasks()[0]);
  auto subSubTask = dynamic_cast<TestTaskRun20Times*>(subTaskIO->getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subSubTask->fRunCounter, 20);
}

BOOST_AUTO_TEST_CASE(my_test_JPetTaskIO_2)
{
  const int maxIter = 10;
  auto condFunc = JPetTaskLooper::getMaxIterationPredicate(maxIter);
  using namespace jpet_options_generator_tools;

  auto task = jpet_common_tools::make_unique<JPetTaskIO>("IOBla", "", "");
  task->addSubTask(jpet_common_tools::make_unique<TestLooperUserTask>("userBla"));
  JPetTaskLooper looper("looperBla", std::move(task), condFunc);

  auto opt = getDefaultOptions();
  JPetParams inputParams;
  inputParams = JPetParams(opt, nullptr);

  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  JPetDataInterface nullDataObject;
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);

  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);

  auto subTaskIO = dynamic_cast<JPetTaskIO*>(looper.getSubTasks()[0]);
  auto subSubTask = dynamic_cast<TestLooperUserTask*>(subTaskIO->getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subSubTask->fRunCounter, 10);
}

BOOST_AUTO_TEST_CASE(my_test_JPetTaskIO_3)
{
  std::string optName = "StopIteration_bool";
  auto condFunc = JPetTaskLooper::getStopOnOptionPredicate(optName);

  using namespace jpet_options_generator_tools;

  auto task = jpet_common_tools::make_unique<JPetTaskIO>("IOBla", "", "");
  task->addSubTask(jpet_common_tools::make_unique<TestLooperUserTask>("userBla"));
  JPetTaskLooper looper("looperBla", std::move(task), condFunc);

  auto opt = getDefaultOptions();
  opt[optName] = false;
  JPetParams inputParams;
  inputParams = JPetParams(opt, nullptr);

  auto result = looper.init(inputParams);
  BOOST_REQUIRE(result);
  JPetDataInterface nullDataObject;
  result = looper.run(nullDataObject);
  BOOST_REQUIRE(result);

  JPetParams outputParams;
  result = looper.terminate(outputParams);
  BOOST_REQUIRE(result);

  auto subTaskIO = dynamic_cast<JPetTaskIO*>(looper.getSubTasks()[0]);
  auto subSubTask = dynamic_cast<TestLooperUserTask*>(subTaskIO->getSubTasks()[0]);
  BOOST_REQUIRE_EQUAL(subSubTask->fRunCounter, 100);
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>

class tst_examples : public QObject
{
    Q_OBJECT
public:
    tst_examples();

private slots:
    void examples_data();
    void examples();

    void namingConvention();
private:
    QString qmlruntime;
    QStringList excludedDirs;

    void namingConvention(const QDir &);
    QStringList findQmlFiles(const QDir &);
};

tst_examples::tst_examples()
{
    QString binaries = QLibraryInfo::location(QLibraryInfo::BinariesPath);

#if defined(Q_WS_MAC)
    qmlruntime = QDir(binaries).absoluteFilePath("qml.app/Contents/MacOS/qml");
#elif defined(Q_WS_WIN)
    qmlruntime = QDir(binaries).absoluteFilePath("qml.exe");
#else
    qmlruntime = QDir(binaries).absoluteFilePath("qml");
#endif

    // Add directories you want excluded here
    excludedDirs << "examples/declarative/extending";
    excludedDirs << "examples/declarative/plugins";
    excludedDirs << "examples/declarative/proxywidgets";
    excludedDirs << "examples/declarative/gestures";
}

/*
This tests that the demos and examples follow the naming convention required
to have them tested by the examples() test.
*/
void tst_examples::namingConvention(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return;
    }

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);

    bool seenQml = !files.isEmpty();
    bool seenLowercase = false;

    foreach (const QString &file, files) {
        if (file.at(0).isLower())
            seenLowercase = true;
    }

    if (!seenQml) {
        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                QDir::NoSymLinks);
        foreach (const QString &dir, dirs) {
            QDir sub = d;
            sub.cd(dir);
            namingConvention(sub);
        }
    } else if(!seenLowercase) {
        QTest::qFail(QString("Directory " + d.absolutePath() + " violates naming convention").toLatin1().constData(), __FILE__, __LINE__);
    }
}

void tst_examples::namingConvention()
{
    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
    QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);

    namingConvention(QDir(examples));
    namingConvention(QDir(demos));
}

QStringList tst_examples::findQmlFiles(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return QStringList();
    }

    QStringList rv;

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);
    foreach (const QString &file, files) {
        if (file.at(0).isLower()) {
            rv << d.absoluteFilePath(file);
        }
    }

    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                                   QDir::NoSymLinks);
    foreach (const QString &dir, dirs) {
        QDir sub = d;
        sub.cd(dir);
        rv << findQmlFiles(sub);
    }

    return rv;
}

/*
This test runs all the examples in the declarative UI source tree and ensures
that they start and exit cleanly.

Examples are any .qml files under the examples/ or demos/ directory that start
with a lower case letter.
*/
void tst_examples::examples_data()
{
    QTest::addColumn<QString>("file");

    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
    QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);
    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/";

    QStringList files;
    files << findQmlFiles(QDir(examples));
    files << findQmlFiles(QDir(demos));
    files << findQmlFiles(QDir(snippets));

    foreach (const QString &file, files)
        QTest::newRow(file.toLatin1().constData()) << file;
}

void tst_examples::examples()
{
    QFETCH(QString, file);

    QFileInfo fi(file);
    QFileInfo dir(fi.path());
    QString script = SRCDIR "/data/"+dir.baseName()+"/"+fi.baseName();
    QFileInfo testdata(script+".qml");
    QStringList arguments;
    arguments << "-script" << (testdata.exists() ? script : QLatin1String(SRCDIR "/data/dummytest"))
              << "-scriptopts" << "play,testerror,exitoncomplete,exitonfailure"
              << file;
#ifdef Q_WS_QWS
    arguments << "-qws";
#endif

    QProcess p;
    p.start(qmlruntime, arguments);
    QVERIFY(p.waitForFinished());
    if (p.exitStatus() != QProcess::NormalExit || p.exitCode() != 0)
        qWarning() << p.readAllStandardOutput() << p.readAllStandardError();
    QCOMPARE(p.exitStatus(), QProcess::NormalExit);
    QCOMPARE(p.exitCode(), 0);
}

QTEST_MAIN(tst_examples)

#include "tst_examples.moc"
<commit_msg>Don't test XmlListModel examples on platforms without QtXmlPatterns<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QLibraryInfo>
#include <QDir>
#include <QProcess>
#include <QDebug>

class tst_examples : public QObject
{
    Q_OBJECT
public:
    tst_examples();

private slots:
    void examples_data();
    void examples();

    void namingConvention();
private:
    QString qmlruntime;
    QStringList excludedDirs;

    void namingConvention(const QDir &);
    QStringList findQmlFiles(const QDir &);
};

tst_examples::tst_examples()
{
    QString binaries = QLibraryInfo::location(QLibraryInfo::BinariesPath);

#if defined(Q_WS_MAC)
    qmlruntime = QDir(binaries).absoluteFilePath("qml.app/Contents/MacOS/qml");
#elif defined(Q_WS_WIN)
    qmlruntime = QDir(binaries).absoluteFilePath("qml.exe");
#else
    qmlruntime = QDir(binaries).absoluteFilePath("qml");
#endif

    // Add directories you want excluded here
    excludedDirs << "examples/declarative/extending";
    excludedDirs << "examples/declarative/plugins";
    excludedDirs << "examples/declarative/proxywidgets";
    excludedDirs << "examples/declarative/gestures";
#ifdef QT_NO_XMLPATTERNS
    excludedDirs << "examples/declarative/xmldata";
    excludedDirs << "demos/declarative/twitter";
    excludedDirs << "demos/declarative/flickr";
    excludedDirs << "demos/declarative/photoviewer";
#endif
}

/*
This tests that the demos and examples follow the naming convention required
to have them tested by the examples() test.
*/
void tst_examples::namingConvention(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return;
    }

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);

    bool seenQml = !files.isEmpty();
    bool seenLowercase = false;

    foreach (const QString &file, files) {
        if (file.at(0).isLower())
            seenLowercase = true;
    }

    if (!seenQml) {
        QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                QDir::NoSymLinks);
        foreach (const QString &dir, dirs) {
            QDir sub = d;
            sub.cd(dir);
            namingConvention(sub);
        }
    } else if(!seenLowercase) {
        QTest::qFail(QString("Directory " + d.absolutePath() + " violates naming convention").toLatin1().constData(), __FILE__, __LINE__);
    }
}

void tst_examples::namingConvention()
{
    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
    QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);

    namingConvention(QDir(examples));
    namingConvention(QDir(demos));
}

QStringList tst_examples::findQmlFiles(const QDir &d)
{
    for (int ii = 0; ii < excludedDirs.count(); ++ii) {
        QString s = excludedDirs.at(ii);
        if (d.absolutePath().endsWith(s))
            return QStringList();
    }

    QStringList rv;

    QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
                                    QDir::Files);
    foreach (const QString &file, files) {
        if (file.at(0).isLower()) {
            rv << d.absoluteFilePath(file);
        }
    }

    QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
                                   QDir::NoSymLinks);
    foreach (const QString &dir, dirs) {
        QDir sub = d;
        sub.cd(dir);
        rv << findQmlFiles(sub);
    }

    return rv;
}

/*
This test runs all the examples in the declarative UI source tree and ensures
that they start and exit cleanly.

Examples are any .qml files under the examples/ or demos/ directory that start
with a lower case letter.
*/
void tst_examples::examples_data()
{
    QTest::addColumn<QString>("file");

    QString examples = QLibraryInfo::location(QLibraryInfo::ExamplesPath);
    QString demos = QLibraryInfo::location(QLibraryInfo::DemosPath);
    QString snippets = QLatin1String(SRCDIR) + "/../../../../doc/src/snippets/";

    QStringList files;
    files << findQmlFiles(QDir(examples));
    files << findQmlFiles(QDir(demos));
    files << findQmlFiles(QDir(snippets));

    foreach (const QString &file, files)
        QTest::newRow(file.toLatin1().constData()) << file;
}

void tst_examples::examples()
{
    QFETCH(QString, file);

    QFileInfo fi(file);
    QFileInfo dir(fi.path());
    QString script = SRCDIR "/data/"+dir.baseName()+"/"+fi.baseName();
    QFileInfo testdata(script+".qml");
    QStringList arguments;
    arguments << "-script" << (testdata.exists() ? script : QLatin1String(SRCDIR "/data/dummytest"))
              << "-scriptopts" << "play,testerror,exitoncomplete,exitonfailure"
              << file;
#ifdef Q_WS_QWS
    arguments << "-qws";
#endif

    QProcess p;
    p.start(qmlruntime, arguments);
    QVERIFY(p.waitForFinished());
    if (p.exitStatus() != QProcess::NormalExit || p.exitCode() != 0)
        qWarning() << p.readAllStandardOutput() << p.readAllStandardError();
    QCOMPARE(p.exitStatus(), QProcess::NormalExit);
    QCOMPARE(p.exitCode(), 0);
}

QTEST_MAIN(tst_examples)

#include "tst_examples.moc"
<|endoftext|>