<commit_before>#include <boost/test/unit_test.hpp>
#include <climits>

#include "bignum.h"
#include "util.h"

BOOST_AUTO_TEST_SUITE(bignum_tests)

// For the following test case, it is useful to use additional tools.
//
// The simplest one to use is the compiler flag -ftrapv, which detects integer
// overflows and similar errors. However, due to optimizations and compilers
// taking advantage of undefined behavior sometimes it may not actually detect
// anything.
//
// You can also use compiler-based stack protection to possibly detect possible
// stack buffer overruns.
//
// For more accurate diagnostics, you can use an undefined arithmetic operation
// detector such as the clang-based tool:
//
// "IOC: An Integer Overflow Checker for C/C++"
//
// Available at: http://embed.cs.utah.edu/ioc/
//
// It might also be useful to use Google's AddressSanitizer to detect
// stack buffer overruns, which valgrind can't currently detect.

// Let's force this code not to be inlined, in order to actually
// test a generic version of the function. This increases the chance
// that -ftrapv will detect overflows.
NOINLINE void mysetint64(CBigNum& num, int64 n)
{
	num.setint64(n);
}

// For each number, we do 2 tests: one with inline code, then we reset the
// value to 0, then the second one with a non-inlined function.
BOOST_AUTO_TEST_CASE(bignum_setint64)
{
    int64 n;

    {
        n = 0;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "0");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "0");
    }
    {
        n = 1;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "1");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "1");
    }
    {
        n = -1;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "-1");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "-1");
    }
    {
        n = 5;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "5");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "5");
    }
    {
        n = -5;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "-5");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "-5");
    }
    {
        n = LLONG_MIN;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "-9223372036854775808");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "-9223372036854775808");
    }
    {
        n = LLONG_MAX;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "9223372036854775807");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "9223372036854775807");
    }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Use C++-style numeric limits instead of C-style.<commit_after>#include <boost/test/unit_test.hpp>
#include <limits>

#include "bignum.h"
#include "util.h"

BOOST_AUTO_TEST_SUITE(bignum_tests)

// For the following test case, it is useful to use additional tools.
//
// The simplest one to use is the compiler flag -ftrapv, which detects integer
// overflows and similar errors. However, due to optimizations and compilers
// taking advantage of undefined behavior sometimes it may not actually detect
// anything.
//
// You can also use compiler-based stack protection to possibly detect possible
// stack buffer overruns.
//
// For more accurate diagnostics, you can use an undefined arithmetic operation
// detector such as the clang-based tool:
//
// "IOC: An Integer Overflow Checker for C/C++"
//
// Available at: http://embed.cs.utah.edu/ioc/
//
// It might also be useful to use Google's AddressSanitizer to detect
// stack buffer overruns, which valgrind can't currently detect.

// Let's force this code not to be inlined, in order to actually
// test a generic version of the function. This increases the chance
// that -ftrapv will detect overflows.
NOINLINE void mysetint64(CBigNum& num, int64 n)
{
	num.setint64(n);
}

// For each number, we do 2 tests: one with inline code, then we reset the
// value to 0, then the second one with a non-inlined function.
BOOST_AUTO_TEST_CASE(bignum_setint64)
{
    int64 n;

    {
        n = 0;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "0");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "0");
    }
    {
        n = 1;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "1");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "1");
    }
    {
        n = -1;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "-1");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "-1");
    }
    {
        n = 5;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "5");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "5");
    }
    {
        n = -5;
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "-5");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "-5");
    }
    {
        n = std::numeric_limits<int64>::min();
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "-9223372036854775808");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "-9223372036854775808");
    }
    {
        n = std::numeric_limits<int64>::max();
        CBigNum num(n);
        BOOST_CHECK(num.ToString() == "9223372036854775807");
        num.setulong(0);
        BOOST_CHECK(num.ToString() == "0");
        mysetint64(num, n);
        BOOST_CHECK(num.ToString() == "9223372036854775807");
    }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <arith_uint256.h>
#include <compressor.h>
#include <consensus/merkle.h>
#include <core_io.h>
#include <crypto/common.h>
#include <crypto/siphash.h>
#include <key_io.h>
#include <memusage.h>
#include <netbase.h>
#include <policy/settings.h>
#include <pow.h>
#include <pubkey.h>
#include <rpc/util.h>
#include <script/signingprovider.h>
#include <script/standard.h>
#include <serialize.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <uint256.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/time.h>

#include <cassert>
#include <limits>
#include <vector>

void initialize()
{
    SelectParams(CBaseChainParams::REGTEST);
}

void test_one_input(const std::vector<uint8_t>& buffer)
{
    if (buffer.size() < sizeof(uint256) + sizeof(uint160)) {
        return;
    }
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    const uint256 u256(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint256)));
    const uint160 u160(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint160)));
    const uint64_t u64 = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
    const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
    const uint32_t u32 = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
    const int32_t i32 = fuzzed_data_provider.ConsumeIntegral<int32_t>();
    const uint16_t u16 = fuzzed_data_provider.ConsumeIntegral<uint16_t>();
    const int16_t i16 = fuzzed_data_provider.ConsumeIntegral<int16_t>();
    const uint8_t u8 = fuzzed_data_provider.ConsumeIntegral<uint8_t>();
    const int8_t i8 = fuzzed_data_provider.ConsumeIntegral<int8_t>();
    // We cannot assume a specific value of std::is_signed<char>::value:
    // ConsumeIntegral<char>() instead of casting from {u,}int8_t.
    const char ch = fuzzed_data_provider.ConsumeIntegral<char>();

    const Consensus::Params& consensus_params = Params().GetConsensus();
    (void)CheckProofOfWork(u256, u32, consensus_params);
    (void)CompressAmount(u64);
    static const uint256 u256_min(uint256S("0000000000000000000000000000000000000000000000000000000000000000"));
    static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
    const std::vector<uint256> v256{u256, u256_min, u256_max};
    (void)ComputeMerkleRoot(v256);
    (void)CountBits(u64);
    (void)DecompressAmount(u64);
    (void)FormatISO8601Date(i64);
    (void)FormatISO8601DateTime(i64);
    (void)GetSizeOfCompactSize(u64);
    (void)GetSpecialScriptSize(u32);
    // (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs
    // (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs
    (void)HexDigit(ch);
    (void)i64tostr(i64);
    (void)IsDigit(ch);
    (void)IsSpace(ch);
    (void)IsSwitchChar(ch);
    (void)itostr(i32);
    (void)memusage::DynamicUsage(ch);
    (void)memusage::DynamicUsage(i16);
    (void)memusage::DynamicUsage(i32);
    (void)memusage::DynamicUsage(i64);
    (void)memusage::DynamicUsage(i8);
    (void)memusage::DynamicUsage(u16);
    (void)memusage::DynamicUsage(u32);
    (void)memusage::DynamicUsage(u64);
    (void)memusage::DynamicUsage(u8);
    const unsigned char uch = static_cast<unsigned char>(u8);
    (void)memusage::DynamicUsage(uch);
    (void)MillisToTimeval(i64);
    const double d = ser_uint64_to_double(u64);
    assert(ser_double_to_uint64(d) == u64);
    const float f = ser_uint32_to_float(u32);
    assert(ser_float_to_uint32(f) == u32);
    (void)SighashToStr(uch);
    (void)SipHashUint256(u64, u64, u256);
    (void)SipHashUint256Extra(u64, u64, u256, u32);
    (void)ToLower(ch);

    const arith_uint256 au256 = UintToArith256(u256);
    assert(ArithToUint256(au256) == u256);
    assert(uint256S(au256.GetHex()) == u256);
    (void)au256.bits();
    (void)au256.GetCompact(/* fNegative= */ false);
    (void)au256.GetCompact(/* fNegative= */ true);
    (void)au256.getdouble();
    (void)au256.GetHex();
    (void)au256.GetLow64();
    (void)au256.size();
    (void)au256.ToString();

    const CKeyID key_id{u160};
    const CScriptID script_id{u160};
    // CTxDestination = CNoDestination ∪ PKHash ∪ ScriptHash ∪ WitnessV0ScriptHash ∪ WitnessV0KeyHash ∪ WitnessUnknown
    const PKHash pk_hash{u160};
    const ScriptHash script_hash{u160};
    const WitnessV0KeyHash witness_v0_key_hash{u160};
    const WitnessV0ScriptHash witness_v0_script_hash{u256};
    const std::vector<CTxDestination> destinations{pk_hash, script_hash, witness_v0_key_hash, witness_v0_script_hash};
    const SigningProvider store;
    for (const CTxDestination& destination : destinations) {
        (void)DescribeAddress(destination);
        (void)EncodeDestination(destination);
        (void)GetKeyForDestination(store, destination);
        (void)GetScriptForDestination(destination);
        (void)IsValidDestination(destination);
    }
}
<commit_msg>tests: Add amount compression/decompression fuzzing to existing fuzzing harness: test compression round-trip<commit_after>// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <amount.h>
#include <arith_uint256.h>
#include <compressor.h>
#include <consensus/merkle.h>
#include <core_io.h>
#include <crypto/common.h>
#include <crypto/siphash.h>
#include <key_io.h>
#include <memusage.h>
#include <netbase.h>
#include <policy/settings.h>
#include <pow.h>
#include <pubkey.h>
#include <rpc/util.h>
#include <script/signingprovider.h>
#include <script/standard.h>
#include <serialize.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <uint256.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/time.h>

#include <cassert>
#include <limits>
#include <vector>

void initialize()
{
    SelectParams(CBaseChainParams::REGTEST);
}

void test_one_input(const std::vector<uint8_t>& buffer)
{
    if (buffer.size() < sizeof(uint256) + sizeof(uint160)) {
        return;
    }
    FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
    const uint256 u256(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint256)));
    const uint160 u160(fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint160)));
    const uint64_t u64 = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
    const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
    const uint32_t u32 = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
    const int32_t i32 = fuzzed_data_provider.ConsumeIntegral<int32_t>();
    const uint16_t u16 = fuzzed_data_provider.ConsumeIntegral<uint16_t>();
    const int16_t i16 = fuzzed_data_provider.ConsumeIntegral<int16_t>();
    const uint8_t u8 = fuzzed_data_provider.ConsumeIntegral<uint8_t>();
    const int8_t i8 = fuzzed_data_provider.ConsumeIntegral<int8_t>();
    // We cannot assume a specific value of std::is_signed<char>::value:
    // ConsumeIntegral<char>() instead of casting from {u,}int8_t.
    const char ch = fuzzed_data_provider.ConsumeIntegral<char>();

    const Consensus::Params& consensus_params = Params().GetConsensus();
    (void)CheckProofOfWork(u256, u32, consensus_params);
    if (u64 <= MAX_MONEY) {
        const uint64_t compressed_money_amount = CompressAmount(u64);
        assert(u64 == DecompressAmount(compressed_money_amount));
        static const uint64_t compressed_money_amount_max = CompressAmount(MAX_MONEY - 1);
        assert(compressed_money_amount <= compressed_money_amount_max);
    } else {
        (void)CompressAmount(u64);
    }
    static const uint256 u256_min(uint256S("0000000000000000000000000000000000000000000000000000000000000000"));
    static const uint256 u256_max(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
    const std::vector<uint256> v256{u256, u256_min, u256_max};
    (void)ComputeMerkleRoot(v256);
    (void)CountBits(u64);
    (void)DecompressAmount(u64);
    (void)FormatISO8601Date(i64);
    (void)FormatISO8601DateTime(i64);
    (void)GetSizeOfCompactSize(u64);
    (void)GetSpecialScriptSize(u32);
    // (void)GetVirtualTransactionSize(i64, i64); // function defined only for a subset of int64_t inputs
    // (void)GetVirtualTransactionSize(i64, i64, u32); // function defined only for a subset of int64_t/uint32_t inputs
    (void)HexDigit(ch);
    (void)i64tostr(i64);
    (void)IsDigit(ch);
    (void)IsSpace(ch);
    (void)IsSwitchChar(ch);
    (void)itostr(i32);
    (void)memusage::DynamicUsage(ch);
    (void)memusage::DynamicUsage(i16);
    (void)memusage::DynamicUsage(i32);
    (void)memusage::DynamicUsage(i64);
    (void)memusage::DynamicUsage(i8);
    (void)memusage::DynamicUsage(u16);
    (void)memusage::DynamicUsage(u32);
    (void)memusage::DynamicUsage(u64);
    (void)memusage::DynamicUsage(u8);
    const unsigned char uch = static_cast<unsigned char>(u8);
    (void)memusage::DynamicUsage(uch);
    (void)MillisToTimeval(i64);
    const double d = ser_uint64_to_double(u64);
    assert(ser_double_to_uint64(d) == u64);
    const float f = ser_uint32_to_float(u32);
    assert(ser_float_to_uint32(f) == u32);
    (void)SighashToStr(uch);
    (void)SipHashUint256(u64, u64, u256);
    (void)SipHashUint256Extra(u64, u64, u256, u32);
    (void)ToLower(ch);

    const arith_uint256 au256 = UintToArith256(u256);
    assert(ArithToUint256(au256) == u256);
    assert(uint256S(au256.GetHex()) == u256);
    (void)au256.bits();
    (void)au256.GetCompact(/* fNegative= */ false);
    (void)au256.GetCompact(/* fNegative= */ true);
    (void)au256.getdouble();
    (void)au256.GetHex();
    (void)au256.GetLow64();
    (void)au256.size();
    (void)au256.ToString();

    const CKeyID key_id{u160};
    const CScriptID script_id{u160};
    // CTxDestination = CNoDestination ∪ PKHash ∪ ScriptHash ∪ WitnessV0ScriptHash ∪ WitnessV0KeyHash ∪ WitnessUnknown
    const PKHash pk_hash{u160};
    const ScriptHash script_hash{u160};
    const WitnessV0KeyHash witness_v0_key_hash{u160};
    const WitnessV0ScriptHash witness_v0_script_hash{u256};
    const std::vector<CTxDestination> destinations{pk_hash, script_hash, witness_v0_key_hash, witness_v0_script_hash};
    const SigningProvider store;
    for (const CTxDestination& destination : destinations) {
        (void)DescribeAddress(destination);
        (void)EncodeDestination(destination);
        (void)GetKeyForDestination(store, destination);
        (void)GetScriptForDestination(destination);
        (void)IsValidDestination(destination);
    }
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

COPYRIGHT NOTICE:

  TokuDB, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

  This program 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
  General Public License for more details.

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

// Create a lot of dirty nodes, kick off a checkpoint, and close the environment.
// Measure the time it takes to close the environment since we are speeding up that
// function.

#include "test.h"
#include <endian.h>
#include <toku_time.h>

#ifndef htobe64
#define htobe64(x) __bswap_64(x)
#endif

// Insert max_rows key/val pairs into the db
static void do_inserts(DB_ENV *env, DB *db, uint64_t max_rows, size_t val_size) {
    char val_data[val_size]; memset(val_data, 0, val_size);
    int r;
    DB_TXN *txn = nullptr;
    r = env->txn_begin(env, nullptr, &txn, 0);
    CKERR(r);

    for (uint64_t i = 1; i <= max_rows; i++) {
        // pick a sequential key but it does not matter for this test.
        uint64_t k[2] = {
            htobe64(i), random64(),
        };
        DBT key = { .data = k, .size = sizeof k };
        DBT val = { .data = val_data, .size = (uint32_t) val_size };
        r = db->put(db, txn, &key, &val, 0);
        CKERR(r);

        if ((i % 1000) == 0) {
            if (verbose)
                fprintf(stderr, "put %" PRIu64 "\n", i);
            r = txn->commit(txn, 0);
            CKERR(r);
            r = env->txn_begin(env, nullptr, &txn, 0);
            CKERR(r);
        }
    }

    r = txn->commit(txn, 0);
    CKERR(r);
}

// Create a cache with a lot of dirty nodes, kick off a checkpoint, and measure the time to
// close the environment.
static void big_shutdown(void) {
    int r;

    DB_ENV *env = nullptr;
    r = db_env_create(&env, 0);
    CKERR(r);
    r = env->set_cachesize(env, 8, 0, 1);
    CKERR(r);
    r = env->open(env, TOKU_TEST_FILENAME,
                  DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
                  S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    DB *db = nullptr;
    r = db_create(&db, env, 0);
    CKERR(r);
    r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    do_inserts(env, db, 1000000, 1024);

    // kick the checkpoint thread
    if (verbose)
        fprintf(stderr, "env->checkpointing_set_period\n");
    r = env->checkpointing_set_period(env, 2);
    CKERR(r);
    sleep(3);

    if (verbose)
        fprintf(stderr, "db->close\n");
    r = db->close(db, 0);
    CKERR(r);

    // measure the shutdown time
    uint64_t tstart = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close\n");
    r = env->close(env, 0);
    CKERR(r);
    uint64_t tend = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close complete %" PRIu64 " sec\n", (tend - tstart)/1000000);
}

int test_main (int argc, char *const argv[]) {
    default_parse_args(argc, argv);

    // init the env directory
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    // run the test
    big_shutdown();

    return 0;
}
<commit_msg>FT-312 compile big-shutdown on osx<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:

  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation, and provided that the
  following conditions are met:

      * Redistributions of source code must retain this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below).

      * Redistributions in binary form must reproduce this COPYING
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
        GRANT (below) in the documentation and/or other materials
        provided with the distribution.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  02110-1301, USA.

COPYRIGHT NOTICE:

  TokuDB, Tokutek Fractal Tree Indexing Library.
  Copyright (C) 2007-2013 Tokutek, Inc.

DISCLAIMER:

  This program 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
  General Public License for more details.

UNIVERSITY PATENT NOTICE:

  The technology is licensed by the Massachusetts Institute of
  Technology, Rutgers State University of New Jersey, and the Research
  Foundation of State University of New York at Stony Brook under
  United States of America Serial No. 11/760379 and to the patents
  and/or patent applications resulting from it.

PATENT MARKING NOTICE:

  This software is covered by US Patent No. 8,185,551.
  This software is covered by US Patent No. 8,489,638.

PATENT RIGHTS GRANT:

  "THIS IMPLEMENTATION" means the copyrightable works distributed by
  Tokutek as part of the Fractal Tree project.

  "PATENT CLAIMS" means the claims of patents that are owned or
  licensable by Tokutek, both currently or in the future; and that in
  the absence of this license would be infringed by THIS
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.

  "PATENT CHALLENGE" shall mean a challenge to the validity,
  patentability, enforceability and/or non-infringement of any of the
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.

  Tokutek hereby grants to you, for the term and geographical scope of
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
  irrevocable (except as stated in this section) patent license to
  make, have made, use, offer to sell, sell, import, transfer, and
  otherwise run, modify, and propagate the contents of THIS
  IMPLEMENTATION, where such license applies only to the PATENT
  CLAIMS.  This grant does not include claims that would be infringed
  only as a consequence of further modifications of THIS
  IMPLEMENTATION.  If you or your agent or licensee institute or order
  or agree to the institution of patent litigation against any entity
  (including a cross-claim or counterclaim in a lawsuit) alleging that
  THIS IMPLEMENTATION constitutes direct or contributory patent
  infringement, or inducement of patent infringement, then any rights
  granted to you under this License shall terminate as of the date
  such litigation is filed.  If you or your agent or exclusive
  licensee institute or order or agree to the institution of a PATENT
  CHALLENGE, then Tokutek may terminate any rights granted to you
  under this License.
*/

#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

// Create a lot of dirty nodes, kick off a checkpoint, and close the environment.
// Measure the time it takes to close the environment since we are speeding up that
// function.

#include "test.h"
#include <toku_time.h>

// Insert max_rows key/val pairs into the db
static void do_inserts(DB_ENV *env, DB *db, uint64_t max_rows, size_t val_size) {
    char val_data[val_size]; memset(val_data, 0, val_size);
    int r;
    DB_TXN *txn = nullptr;
    r = env->txn_begin(env, nullptr, &txn, 0);
    CKERR(r);

    for (uint64_t i = 1; i <= max_rows; i++) {
        // pick a sequential key but it does not matter for this test.
        uint64_t k[2] = {
            htonl(i), random64(),
        };
        DBT key = { .data = k, .size = sizeof k };
        DBT val = { .data = val_data, .size = (uint32_t) val_size };
        r = db->put(db, txn, &key, &val, 0);
        CKERR(r);

        if ((i % 1000) == 0) {
            if (verbose)
                fprintf(stderr, "put %" PRIu64 "\n", i);
            r = txn->commit(txn, 0);
            CKERR(r);
            r = env->txn_begin(env, nullptr, &txn, 0);
            CKERR(r);
        }
    }

    r = txn->commit(txn, 0);
    CKERR(r);
}

// Create a cache with a lot of dirty nodes, kick off a checkpoint, and measure the time to
// close the environment.
static void big_shutdown(void) {
    int r;

    DB_ENV *env = nullptr;
    r = db_env_create(&env, 0);
    CKERR(r);
    r = env->set_cachesize(env, 8, 0, 1);
    CKERR(r);
    r = env->open(env, TOKU_TEST_FILENAME,
                  DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN|DB_PRIVATE,
                  S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    DB *db = nullptr;
    r = db_create(&db, env, 0);
    CKERR(r);
    r = db->open(db, nullptr, "foo.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    do_inserts(env, db, 1000000, 1024);

    // kick the checkpoint thread
    if (verbose)
        fprintf(stderr, "env->checkpointing_set_period\n");
    r = env->checkpointing_set_period(env, 2);
    CKERR(r);
    sleep(3);

    if (verbose)
        fprintf(stderr, "db->close\n");
    r = db->close(db, 0);
    CKERR(r);

    // measure the shutdown time
    uint64_t tstart = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close\n");
    r = env->close(env, 0);
    CKERR(r);
    uint64_t tend = toku_current_time_microsec();
    if (verbose)
        fprintf(stderr, "env->close complete %" PRIu64 " sec\n", (tend - tstart)/1000000);
}

int test_main (int argc, char *const argv[]) {
    default_parse_args(argc, argv);

    // init the env directory
    toku_os_recursive_delete(TOKU_TEST_FILENAME);
    int r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO);
    CKERR(r);

    // run the test
    big_shutdown();

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <list>
#include <string>
#include <utility>

#include "../fpdfsdk/include/fpdf_dataavail.h"
#include "../fpdfsdk/include/fpdf_ext.h"
#include "../fpdfsdk/include/fpdfformfill.h"
#include "../fpdfsdk/include/fpdftext.h"
#include "../fpdfsdk/include/fpdfview.h"
#include "v8/include/v8.h"

#ifdef _WIN32
  #define snprintf _snprintf
#endif

enum OutputFormat {
  OUTPUT_NONE,
  OUTPUT_PPM,
#ifdef _WIN32
  OUTPUT_BMP,
  OUTPUT_EMF,
#endif
};

static void WritePpm(const char* pdf_name, int num, const void* buffer_void,
                     int stride, int width, int height) {
  const char* buffer = reinterpret_cast<const char*>(buffer_void);

  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = width * height;
  if (out_len > INT_MAX / 3)
    return;
  out_len *= 3;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;
  fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);
  // Source data is B, G, R, unused.
  // Dest data is R, G, B.
  char* result = new char[out_len];
  if (result) {
    for (int h = 0; h < height; ++h) {
      const char* src_line = buffer + (stride * h);
      char* dest_line = result + (width * h * 3);
      for (int w = 0; w < width; ++w) {
        // R
        dest_line[w * 3] = src_line[(w * 4) + 2];
        // G
        dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];
        // B
        dest_line[(w * 3) + 2] = src_line[w * 4];
      }
    }
    fwrite(result, out_len, 1, fp);
    delete [] result;
  }
  fclose(fp);
}

#ifdef _WIN32
static void WriteBmp(const char* pdf_name, int num, const void* buffer,
                     int stride, int width, int height) {
  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = stride * height;
  if (out_len > INT_MAX / 3)
    return;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.bmp", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;

  BITMAPINFO bmi = {0};
  bmi.bmiHeader.biSize = sizeof(bmi) - sizeof(RGBQUAD);
  bmi.bmiHeader.biWidth = width;
  bmi.bmiHeader.biHeight = -height;  // top-down image
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biSizeImage = 0;

  BITMAPFILEHEADER file_header = {0};
  file_header.bfType = 0x4d42;
  file_header.bfSize = sizeof(file_header) + bmi.bmiHeader.biSize + out_len;
  file_header.bfOffBits = file_header.bfSize - out_len;

  fwrite(&file_header, sizeof(file_header), 1, fp);
  fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp);
  fwrite(buffer, out_len, 1, fp);
  fclose(fp);
}

void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
  int width = static_cast<int>(FPDF_GetPageWidth(page));
  int height = static_cast<int>(FPDF_GetPageHeight(page));

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num);

  HDC dc = CreateEnhMetaFileA(NULL, filename, NULL, NULL);

  HRGN rgn = CreateRectRgn(0, 0, width, height);
  SelectClipRgn(dc, rgn);
  DeleteObject(rgn);

  SelectObject(dc, GetStockObject(NULL_PEN));
  SelectObject(dc, GetStockObject(WHITE_BRUSH));
  // If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
  Rectangle(dc, 0, 0, width + 1, height + 1);

  FPDF_RenderPage(dc, page, 0, 0, width, height, 0,
                  FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);

  DeleteEnhMetaFile(CloseEnhMetaFile(dc));
}
#endif

int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {
  printf("Form_Alert called.\n");
  return 0;
}

void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
  std::string feature = "Unknown";
  switch (type) {
    case FPDF_UNSP_DOC_XFAFORM:
      feature = "XFA";
      break;
    case FPDF_UNSP_DOC_PORTABLECOLLECTION:
      feature = "Portfolios_Packages";
      break;
    case FPDF_UNSP_DOC_ATTACHMENT:
    case FPDF_UNSP_ANNOT_ATTACHMENT:
      feature = "Attachment";
      break;
    case FPDF_UNSP_DOC_SECURITY:
      feature = "Rights_Management";
      break;
    case FPDF_UNSP_DOC_SHAREDREVIEW:
      feature = "Shared_Review";
      break;
    case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
    case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
    case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
      feature = "Shared_Form";
      break;
    case FPDF_UNSP_ANNOT_3DANNOT:
      feature = "3D";
      break;
    case FPDF_UNSP_ANNOT_MOVIE:
      feature = "Movie";
      break;
    case FPDF_UNSP_ANNOT_SOUND:
      feature = "Sound";
      break;
    case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
    case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
      feature = "Screen";
      break;
    case FPDF_UNSP_ANNOT_SIG:
      feature = "Digital_Signature";
      break;
  }
  printf("Unsupported feature: %s.\n", feature.c_str());
}

bool ParseCommandLine(int argc, const char* argv[], OutputFormat* output_format,
                      std::list<const char*>* files) {
  *output_format = OUTPUT_NONE;
  files->clear();

  int cur_arg = 1;
  if (cur_arg < argc) {
    if (strcmp(argv[cur_arg], "--ppm") == 0)
      *output_format = OUTPUT_PPM;
#ifdef _WIN32
    if (strcmp(argv[cur_arg], "--emf") == 0)
      *output_format = OUTPUT_EMF;
    if (strcmp(argv[cur_arg], "--bmp") == 0)
      *output_format = OUTPUT_BMP;
#endif
    if (*output_format != OUTPUT_NONE)
      cur_arg++;
  }

  if (cur_arg >= argc)
    return false;

  for (int i = cur_arg; i < argc; i++)
    files->push_back(argv[i]);

  return true;
}

class TestLoader {
 public:
  TestLoader(const char* pBuf, size_t len);

  const char* m_pBuf;
  size_t m_Len;
};

TestLoader::TestLoader(const char* pBuf, size_t len)
    : m_pBuf(pBuf), m_Len(len) {
}

int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
              unsigned long size) {
  TestLoader* pLoader = (TestLoader*) param;
  if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
  memcpy(pBuf, pLoader->m_pBuf + pos, size);
  return 1;
}

bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
  return true;
}

void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
}

void RenderPdf(const char* name, const char* pBuf, size_t len,
               OutputFormat format) {
  printf("Rendering PDF file %s.\n", name);

  IPDF_JSPLATFORM platform_callbacks;
  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
  platform_callbacks.version = 1;
  platform_callbacks.app_alert = Form_Alert;

  FPDF_FORMFILLINFO form_callbacks;
  memset(&form_callbacks, '\0', sizeof(form_callbacks));
  form_callbacks.version = 1;
  form_callbacks.m_pJsPlatform = &platform_callbacks;

  TestLoader loader(pBuf, len);

  FPDF_FILEACCESS file_access;
  memset(&file_access, '\0', sizeof(file_access));
  file_access.m_FileLen = static_cast<unsigned long>(len);
  file_access.m_GetBlock = Get_Block;
  file_access.m_Param = &loader;

  FX_FILEAVAIL file_avail;
  memset(&file_avail, '\0', sizeof(file_avail));
  file_avail.version = 1;
  file_avail.IsDataAvail = Is_Data_Avail;

  FX_DOWNLOADHINTS hints;
  memset(&hints, '\0', sizeof(hints));
  hints.version = 1;
  hints.AddSegment = Add_Segment;

  FPDF_DOCUMENT doc;
  FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access);

  (void) FPDFAvail_IsDocAvail(pdf_avail, &hints);

  if (!FPDFAvail_IsLinearized(pdf_avail)) {
    printf("Non-linearized path...\n");
    doc = FPDF_LoadCustomDocument(&file_access, NULL);
  } else {
    printf("Linearized path...\n");
    doc = FPDFAvail_GetDocument(pdf_avail, NULL);
  }

  (void) FPDF_GetDocPermissions(doc);
  (void) FPDFAvail_IsFormAvail(pdf_avail, &hints);

  FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnviroument(doc, &form_callbacks);
  FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD);
  FPDF_SetFormFieldHighlightAlpha(form, 100);

  int first_page = FPDFAvail_GetFirstPageNum(doc);
  (void) FPDFAvail_IsPageAvail(pdf_avail, first_page, &hints);

  int page_count = FPDF_GetPageCount(doc);
  for (int i = 0; i < page_count; ++i) {
    (void) FPDFAvail_IsPageAvail(pdf_avail, i, &hints);
  }

  FORM_DoDocumentJSAction(form);
  FORM_DoDocumentOpenAction(form);

  for (int i = 0; i < page_count; ++i) {
    FPDF_PAGE page = FPDF_LoadPage(doc, i);
    FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
    FORM_OnAfterLoadPage(page, form);
    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN);

    int width = static_cast<int>(FPDF_GetPageWidth(page));
    int height = static_cast<int>(FPDF_GetPageHeight(page));
    FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
    FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);

    FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
    FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0);
    int stride = FPDFBitmap_GetStride(bitmap);
    const char* buffer =
        reinterpret_cast<const char*>(FPDFBitmap_GetBuffer(bitmap));

    switch (format) {
#ifdef _WIN32
      case OUTPUT_BMP:
        WriteBmp(name, i, buffer, stride, width, height);
        break;

      case OUTPUT_EMF:
        WriteEmf(page, name, i);
        break;
#endif
      case OUTPUT_PPM:
        WritePpm(name, i, buffer, stride, width, height);
        break;
      default:
        break;
    }

    FPDFBitmap_Destroy(bitmap);

    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
    FORM_OnBeforeClosePage(page, form);
    FPDFText_ClosePage(text_page);
    FPDF_ClosePage(page);
  }

  FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC);
  FPDFDOC_ExitFormFillEnviroument(form);
  FPDF_CloseDocument(doc);
  FPDFAvail_Destroy(pdf_avail);

  printf("Loaded, parsed and rendered %d pages.\n", page_count);
}

int main(int argc, const char* argv[]) {
  v8::V8::InitializeICU();
  OutputFormat format = OUTPUT_NONE;
  std::list<const char*> files;
  if (!ParseCommandLine(argc, argv, &format, &files)) {
    printf("Usage: pdfium_test [OPTIONS] [FILE]\n");
    printf("--ppm    write page images <pdf-name>.<page-number>.ppm\n");
#ifdef _WIN32
    printf("--bmp    write page images <pdf-name>.<page-number>.bmp\n");
    printf("--emf    write page meta files <pdf-name>.<page-number>.emf\n");
#endif
    return 1;
  }

  FPDF_InitLibrary(NULL);

  UNSUPPORT_INFO unsuppored_info;
  memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
  unsuppored_info.version = 1;
  unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;

  FSDK_SetUnSpObjProcessHandler(&unsuppored_info);

  while (!files.empty()) {
    const char* filename = files.front();
    files.pop_front();
    FILE* file = fopen(filename, "rb");
    if (!file) {
      fprintf(stderr, "Failed to open: %s\n", filename);
      continue;
    }
    (void) fseek(file, 0, SEEK_END);
    size_t len = ftell(file);
    (void) fseek(file, 0, SEEK_SET);
    char* pBuf = (char*) malloc(len);
    size_t ret = fread(pBuf, 1, len, file);
    (void) fclose(file);
    if (ret != len) {
      fprintf(stderr, "Failed to read: %s\n", filename);
    } else {
      RenderPdf(filename, pBuf, len, format);
    }
    free(pBuf);
  }

  FPDF_DestroyLibrary();

  return 0;
}
<commit_msg>Check if user provided more than one option for pdfium_test.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <list>
#include <string>
#include <utility>

#include "../fpdfsdk/include/fpdf_dataavail.h"
#include "../fpdfsdk/include/fpdf_ext.h"
#include "../fpdfsdk/include/fpdfformfill.h"
#include "../fpdfsdk/include/fpdftext.h"
#include "../fpdfsdk/include/fpdfview.h"
#include "v8/include/v8.h"

#ifdef _WIN32
  #define snprintf _snprintf
#endif

enum OutputFormat {
  OUTPUT_NONE,
  OUTPUT_PPM,
#ifdef _WIN32
  OUTPUT_BMP,
  OUTPUT_EMF,
#endif
};

static void WritePpm(const char* pdf_name, int num, const void* buffer_void,
                     int stride, int width, int height) {
  const char* buffer = reinterpret_cast<const char*>(buffer_void);

  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = width * height;
  if (out_len > INT_MAX / 3)
    return;
  out_len *= 3;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;
  fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);
  // Source data is B, G, R, unused.
  // Dest data is R, G, B.
  char* result = new char[out_len];
  if (result) {
    for (int h = 0; h < height; ++h) {
      const char* src_line = buffer + (stride * h);
      char* dest_line = result + (width * h * 3);
      for (int w = 0; w < width; ++w) {
        // R
        dest_line[w * 3] = src_line[(w * 4) + 2];
        // G
        dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];
        // B
        dest_line[(w * 3) + 2] = src_line[w * 4];
      }
    }
    fwrite(result, out_len, 1, fp);
    delete [] result;
  }
  fclose(fp);
}

#ifdef _WIN32
static void WriteBmp(const char* pdf_name, int num, const void* buffer,
                     int stride, int width, int height) {
  if (stride < 0 || width < 0 || height < 0)
    return;
  if (height > 0 && width > INT_MAX / height)
    return;
  int out_len = stride * height;
  if (out_len > INT_MAX / 3)
    return;

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.bmp", pdf_name, num);
  FILE* fp = fopen(filename, "wb");
  if (!fp)
    return;

  BITMAPINFO bmi = {0};
  bmi.bmiHeader.biSize = sizeof(bmi) - sizeof(RGBQUAD);
  bmi.bmiHeader.biWidth = width;
  bmi.bmiHeader.biHeight = -height;  // top-down image
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = BI_RGB;
  bmi.bmiHeader.biSizeImage = 0;

  BITMAPFILEHEADER file_header = {0};
  file_header.bfType = 0x4d42;
  file_header.bfSize = sizeof(file_header) + bmi.bmiHeader.biSize + out_len;
  file_header.bfOffBits = file_header.bfSize - out_len;

  fwrite(&file_header, sizeof(file_header), 1, fp);
  fwrite(&bmi, bmi.bmiHeader.biSize, 1, fp);
  fwrite(buffer, out_len, 1, fp);
  fclose(fp);
}

void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
  int width = static_cast<int>(FPDF_GetPageWidth(page));
  int height = static_cast<int>(FPDF_GetPageHeight(page));

  char filename[256];
  snprintf(filename, sizeof(filename), "%s.%d.emf", pdf_name, num);

  HDC dc = CreateEnhMetaFileA(NULL, filename, NULL, NULL);

  HRGN rgn = CreateRectRgn(0, 0, width, height);
  SelectClipRgn(dc, rgn);
  DeleteObject(rgn);

  SelectObject(dc, GetStockObject(NULL_PEN));
  SelectObject(dc, GetStockObject(WHITE_BRUSH));
  // If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
  Rectangle(dc, 0, 0, width + 1, height + 1);

  FPDF_RenderPage(dc, page, 0, 0, width, height, 0,
                  FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);

  DeleteEnhMetaFile(CloseEnhMetaFile(dc));
}
#endif

int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {
  printf("Form_Alert called.\n");
  return 0;
}

void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
  std::string feature = "Unknown";
  switch (type) {
    case FPDF_UNSP_DOC_XFAFORM:
      feature = "XFA";
      break;
    case FPDF_UNSP_DOC_PORTABLECOLLECTION:
      feature = "Portfolios_Packages";
      break;
    case FPDF_UNSP_DOC_ATTACHMENT:
    case FPDF_UNSP_ANNOT_ATTACHMENT:
      feature = "Attachment";
      break;
    case FPDF_UNSP_DOC_SECURITY:
      feature = "Rights_Management";
      break;
    case FPDF_UNSP_DOC_SHAREDREVIEW:
      feature = "Shared_Review";
      break;
    case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
    case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
    case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
      feature = "Shared_Form";
      break;
    case FPDF_UNSP_ANNOT_3DANNOT:
      feature = "3D";
      break;
    case FPDF_UNSP_ANNOT_MOVIE:
      feature = "Movie";
      break;
    case FPDF_UNSP_ANNOT_SOUND:
      feature = "Sound";
      break;
    case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
    case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
      feature = "Screen";
      break;
    case FPDF_UNSP_ANNOT_SIG:
      feature = "Digital_Signature";
      break;
  }
  printf("Unsupported feature: %s.\n", feature.c_str());
}

bool ParseCommandLine(int argc, const char* argv[], OutputFormat* output_format,
                      std::list<const char*>* files) {
  *output_format = OUTPUT_NONE;
  files->clear();

  int cur_arg = 1;
  for (; cur_arg < argc; ++cur_arg) {
    if (strcmp(argv[cur_arg], "--ppm") == 0)
      *output_format = OUTPUT_PPM;
#ifdef _WIN32
    else if (strcmp(argv[cur_arg], "--emf") == 0)
      *output_format = OUTPUT_EMF;
    else if (strcmp(argv[cur_arg], "--bmp") == 0)
      *output_format = OUTPUT_BMP;
#endif
    else
      break;
  }

  if (cur_arg > 2)  // Multiple options.
    return false;

  if (cur_arg >= argc)  // No input files.
    return false;

  for (int i = cur_arg; i < argc; i++)
    files->push_back(argv[i]);

  return true;
}

class TestLoader {
 public:
  TestLoader(const char* pBuf, size_t len);

  const char* m_pBuf;
  size_t m_Len;
};

TestLoader::TestLoader(const char* pBuf, size_t len)
    : m_pBuf(pBuf), m_Len(len) {
}

int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
              unsigned long size) {
  TestLoader* pLoader = (TestLoader*) param;
  if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
  memcpy(pBuf, pLoader->m_pBuf + pos, size);
  return 1;
}

bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
  return true;
}

void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
}

void RenderPdf(const char* name, const char* pBuf, size_t len,
               OutputFormat format) {
  printf("Rendering PDF file %s.\n", name);

  IPDF_JSPLATFORM platform_callbacks;
  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
  platform_callbacks.version = 1;
  platform_callbacks.app_alert = Form_Alert;

  FPDF_FORMFILLINFO form_callbacks;
  memset(&form_callbacks, '\0', sizeof(form_callbacks));
  form_callbacks.version = 1;
  form_callbacks.m_pJsPlatform = &platform_callbacks;

  TestLoader loader(pBuf, len);

  FPDF_FILEACCESS file_access;
  memset(&file_access, '\0', sizeof(file_access));
  file_access.m_FileLen = static_cast<unsigned long>(len);
  file_access.m_GetBlock = Get_Block;
  file_access.m_Param = &loader;

  FX_FILEAVAIL file_avail;
  memset(&file_avail, '\0', sizeof(file_avail));
  file_avail.version = 1;
  file_avail.IsDataAvail = Is_Data_Avail;

  FX_DOWNLOADHINTS hints;
  memset(&hints, '\0', sizeof(hints));
  hints.version = 1;
  hints.AddSegment = Add_Segment;

  FPDF_DOCUMENT doc;
  FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access);

  (void) FPDFAvail_IsDocAvail(pdf_avail, &hints);

  if (!FPDFAvail_IsLinearized(pdf_avail)) {
    printf("Non-linearized path...\n");
    doc = FPDF_LoadCustomDocument(&file_access, NULL);
  } else {
    printf("Linearized path...\n");
    doc = FPDFAvail_GetDocument(pdf_avail, NULL);
  }

  (void) FPDF_GetDocPermissions(doc);
  (void) FPDFAvail_IsFormAvail(pdf_avail, &hints);

  FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnviroument(doc, &form_callbacks);
  FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD);
  FPDF_SetFormFieldHighlightAlpha(form, 100);

  int first_page = FPDFAvail_GetFirstPageNum(doc);
  (void) FPDFAvail_IsPageAvail(pdf_avail, first_page, &hints);

  int page_count = FPDF_GetPageCount(doc);
  for (int i = 0; i < page_count; ++i) {
    (void) FPDFAvail_IsPageAvail(pdf_avail, i, &hints);
  }

  FORM_DoDocumentJSAction(form);
  FORM_DoDocumentOpenAction(form);

  for (int i = 0; i < page_count; ++i) {
    FPDF_PAGE page = FPDF_LoadPage(doc, i);
    FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
    FORM_OnAfterLoadPage(page, form);
    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN);

    int width = static_cast<int>(FPDF_GetPageWidth(page));
    int height = static_cast<int>(FPDF_GetPageHeight(page));
    FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
    FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);

    FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
    FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0);
    int stride = FPDFBitmap_GetStride(bitmap);
    const char* buffer =
        reinterpret_cast<const char*>(FPDFBitmap_GetBuffer(bitmap));

    switch (format) {
#ifdef _WIN32
      case OUTPUT_BMP:
        WriteBmp(name, i, buffer, stride, width, height);
        break;

      case OUTPUT_EMF:
        WriteEmf(page, name, i);
        break;
#endif
      case OUTPUT_PPM:
        WritePpm(name, i, buffer, stride, width, height);
        break;
      default:
        break;
    }

    FPDFBitmap_Destroy(bitmap);

    FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
    FORM_OnBeforeClosePage(page, form);
    FPDFText_ClosePage(text_page);
    FPDF_ClosePage(page);
  }

  FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC);
  FPDFDOC_ExitFormFillEnviroument(form);
  FPDF_CloseDocument(doc);
  FPDFAvail_Destroy(pdf_avail);

  printf("Loaded, parsed and rendered %d pages.\n", page_count);
}

int main(int argc, const char* argv[]) {
  v8::V8::InitializeICU();
  OutputFormat format = OUTPUT_NONE;
  std::list<const char*> files;
  if (!ParseCommandLine(argc, argv, &format, &files)) {
    printf("Usage: pdfium_test [OPTION] [FILE]...\n");
    printf("--ppm    write page images <pdf-name>.<page-number>.ppm\n");
#ifdef _WIN32
    printf("--bmp    write page images <pdf-name>.<page-number>.bmp\n");
    printf("--emf    write page meta files <pdf-name>.<page-number>.emf\n");
#endif
    return 1;
  }

  FPDF_InitLibrary(NULL);

  UNSUPPORT_INFO unsuppored_info;
  memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
  unsuppored_info.version = 1;
  unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;

  FSDK_SetUnSpObjProcessHandler(&unsuppored_info);

  while (!files.empty()) {
    const char* filename = files.front();
    files.pop_front();
    FILE* file = fopen(filename, "rb");
    if (!file) {
      fprintf(stderr, "Failed to open: %s\n", filename);
      continue;
    }
    (void) fseek(file, 0, SEEK_END);
    size_t len = ftell(file);
    (void) fseek(file, 0, SEEK_SET);
    char* pBuf = (char*) malloc(len);
    size_t ret = fread(pBuf, 1, len, file);
    (void) fclose(file);
    if (ret != len) {
      fprintf(stderr, "Failed to read: %s\n", filename);
    } else {
      RenderPdf(filename, pBuf, len, format);
    }
    free(pBuf);
  }

  FPDF_DestroyLibrary();

  return 0;
}
<|endoftext|>


<commit_before>#include <Python.h>
#include "valkyrie.h"

// exception object
static PyObject *ValkyrieError;

#define RETURN_ERROR_IF_CALLED_WITH_ARGS \
	if (!PyArg_ParseTuple(args, "")) \
		return NULL;

#define RETURN_ERROR_IF(condition) \
    if (condition) \
        return NULL;

#define THROW_EXCEPTION_IF(condition, message) \
    if ((condition)) {\
        PyErr_SetString(ValkyrieError, message);\
        return NULL;\
    }

static PyObject* vk_major_version(PyObject *self, PyObject *args)
{
	RETURN_ERROR_IF_CALLED_WITH_ARGS
	return PyLong_FromLong(VKApiMajorVersion());
}

static PyObject* vk_minor_version(PyObject *self, PyObject *args)
{
	RETURN_ERROR_IF_CALLED_WITH_ARGS
	return PyLong_FromLong(VKApiMinorVersion());
}

static PyObject* vk_patch_version(PyObject *self, PyObject *args)
{
	RETURN_ERROR_IF_CALLED_WITH_ARGS
	return PyLong_FromLong(VKApiPatchVersion());
}

static PyObject* vk_version(PyObject *self, PyObject *args)
{
    RETURN_ERROR_IF_CALLED_WITH_ARGS
    return Py_BuildValue("s", VKApiVersion());
}

static PyObject* vk_is_at_least_version(PyObject *self, PyObject *args)
{
    int major = 0;
    int minor = 0;
    int patch = 0;

    int ok = PyArg_ParseTuple(args, "i|ii", &major, &minor, &patch);
    if (!ok) return NULL;
    THROW_EXCEPTION_IF(major < 0, "Given major version is less than Zero!");
    THROW_EXCEPTION_IF(minor < 0, "Given minor version is less than Zero!");
    THROW_EXCEPTION_IF(patch < 0, "Given patch version is less than Zero!");

    return PyLong_FromLong(VKApiVersionIsAtLeast(major, minor, patch));
}

static int is_error_code(int code, const char **err_msg)
{
    *err_msg = VKErrorMessage(code);
    return (*err_msg) ? 1 : 0;
}

static PyObject* vk_model_create(PyObject *self, PyObject *args)
{
    const char *model_name = NULL;
    int model_id = 0;
    int ok = PyArg_ParseTuple(args, "i|s", &model_id, &model_name);
    if (!ok) return NULL;

    int code = VKModelCreate(model_id, model_name);

    const char *error_msg = NULL;
    THROW_EXCEPTION_IF(is_error_code(code, &error_msg), error_msg);
    return PyLong_FromLong(code);
}

static PyMethodDef ValkyrieMethods[] = {
	{"major_version", vk_major_version, METH_VARARGS, "Valkyrie API major version"},
	{"minor_version", vk_minor_version, METH_VARARGS, "Valkyrie API minor version"},
	{"patch_version", vk_patch_version, METH_VARARGS, "Valkyrie API patch version"},
    {"version", vk_version, METH_VARARGS, "Valkyrie API version"},
    {"is_at_least_version", vk_is_at_least_version, METH_VARARGS, "Checks if API version is at least the given version."},
    {"create_model", vk_model_create, METH_VARARGS, "Create a new FE model, with id and name"},
	{NULL, NULL, 0, NULL}
};

static struct PyModuleDef valkyriemodule = {
	PyModuleDef_HEAD_INIT,
	"valkyrie",
	NULL,
	-1,
	ValkyrieMethods
};

PyMODINIT_FUNC
PyInit_valkyrie(void)
{
    PyObject *ref = NULL;

    ref = PyModule_Create(&valkyriemodule);
    if (!ref)
    {
        return NULL;
    }

    ValkyrieError = PyErr_NewException("valkyrie.error", NULL, NULL);
    Py_INCREF(ValkyrieError);
    PyModule_AddObject(ref, "error", ValkyrieError);
	return ref;
}
<commit_msg>bindings for material<commit_after>#include <Python.h>
#include "valkyrie.h"

// exception object
static PyObject *ValkyrieError;

#define RETURN_ERROR_IF_CALLED_WITH_ARGS \
	if (!PyArg_ParseTuple(args, "")) \
		return NULL;

#define RETURN_ERROR_IF(condition) \
    if (condition) \
        return NULL;

#define THROW_EXCEPTION_IF(condition, message) \
    if ((condition)) {\
        PyErr_SetString(ValkyrieError, message);\
        return NULL;\
    }

static PyObject* vk_major_version(PyObject *self, PyObject *args)
{
	RETURN_ERROR_IF_CALLED_WITH_ARGS
	return PyLong_FromLong(VKApiMajorVersion());
}

static PyObject* vk_minor_version(PyObject *self, PyObject *args)
{
	RETURN_ERROR_IF_CALLED_WITH_ARGS
	return PyLong_FromLong(VKApiMinorVersion());
}

static PyObject* vk_patch_version(PyObject *self, PyObject *args)
{
	RETURN_ERROR_IF_CALLED_WITH_ARGS
	return PyLong_FromLong(VKApiPatchVersion());
}

static PyObject* vk_version(PyObject *self, PyObject *args)
{
    RETURN_ERROR_IF_CALLED_WITH_ARGS
    return Py_BuildValue("s", VKApiVersion());
}

static PyObject* vk_is_at_least_version(PyObject *self, PyObject *args)
{
    int major = 0;
    int minor = 0;
    int patch = 0;

    int ok = PyArg_ParseTuple(args, "i|ii", &major, &minor, &patch);
    if (!ok) return NULL;
    THROW_EXCEPTION_IF(major < 0, "Given major version is less than Zero!");
    THROW_EXCEPTION_IF(minor < 0, "Given minor version is less than Zero!");
    THROW_EXCEPTION_IF(patch < 0, "Given patch version is less than Zero!");

    return PyLong_FromLong(VKApiVersionIsAtLeast(major, minor, patch));
}

static int is_error_code(int code, const char **err_msg)
{
    *err_msg = VKErrorMessage(code);
    return (*err_msg) ? 1 : 0;
}

static PyObject* vk_model_create(PyObject *self, PyObject *args)
{
    const char *model_name = NULL;
    int model_id = 0;
    int ok = PyArg_ParseTuple(args, "i|s", &model_id, &model_name);
    if (!ok) return NULL;

    int code = VKModelCreate(model_id, model_name);

    const char *error_msg = NULL;
    THROW_EXCEPTION_IF(is_error_code(code, &error_msg), error_msg);
    return PyLong_FromLong(code);
}

static PyObject* vk_node_create(PyObject *self, PyObject *args)
{
    int model_id = 0;
    int node_id = 0;
    double x = 0;
    double y = 0;
    double z = 0;
    int ok = PyArg_ParseTuple(args, "iiddd", &model_id, &node_id, &x, &y, &z);
    if (!ok) return NULL;

    int code = VKModelCreateNode(model_id, node_id, x, y, z);
    const char *error_msg = NULL;
    THROW_EXCEPTION_IF(is_error_code(code, &error_msg), error_msg);
    return PyLong_FromLong(code);
}

static PyObject* vk_material_create(PyObject *self, PyObject *args)
{
    int model_id = 0;
    int material_id = 0;
    double E = 0;
    double rho = 0;
    const char *name = NULL;
    int ok = PyArg_ParseTuple(args, "iiddi|s", &model_id, &material_id, &E, &rho, &name);
    if (!ok) return NULL;

    int code = VKModelCreateMaterial(model_id, material_id, E, rho, name);
    const char *error_msg = NULL;
    THROW_EXCEPTION_IF(is_error_code(code, &error_msg), error_msg);
    return PyLong_FromLong(code);
}

static PyMethodDef ValkyrieMethods[] = {
	{"major_version", vk_major_version, METH_VARARGS, "Valkyrie API major version"},
	{"minor_version", vk_minor_version, METH_VARARGS, "Valkyrie API minor version"},
	{"patch_version", vk_patch_version, METH_VARARGS, "Valkyrie API patch version"},
    {"version", vk_version, METH_VARARGS, "Valkyrie API version"},
    {"is_at_least_version", vk_is_at_least_version, METH_VARARGS, "Checks if API version is at least the given version."},
    {"create_model", vk_model_create, METH_VARARGS, "Create a new FE model, with id and name"},
    {"create_node", vk_node_create, METH_VARARGS, "Create a new FE node"},
    {"create_material", vk_material_create, METH_VARARGS, "Create a new FE material"},
	{NULL, NULL, 0, NULL}
};

static struct PyModuleDef valkyriemodule = {
	PyModuleDef_HEAD_INIT,
	"valkyrie",
	NULL,
	-1,
	ValkyrieMethods
};

PyMODINIT_FUNC
PyInit_valkyrie(void)
{
    PyObject *ref = NULL;

    ref = PyModule_Create(&valkyriemodule);
    if (!ref)
    {
        return NULL;
    }

    ValkyrieError = PyErr_NewException("valkyrie.error", NULL, NULL);
    Py_INCREF(ValkyrieError);
    PyModule_AddObject(ref, "error", ValkyrieError);
	return ref;
}
<|endoftext|>


<commit_before>#include <systemlib/mixer/mixer.h>
#include <systemlib/err.h>
#include "../../src/systemcmds/tests/tests.h"

#include "gtest/gtest.h"

TEST(MixerTest, Mixer)
{
	const char *args[] = {"empty", "../ROMFS/px4fmu_common/mixers/IO_pass.mix", "../ROMFS/px4fmu_common/mixers/quad_w.main.mix"};
	ASSERT_EQ(test_mixer(3, (char **)args), 0) << "IO_pass.mix failed";
}
<commit_msg>Fix mixer test<commit_after>#include <systemlib/mixer/mixer.h>
#include <systemlib/err.h>
#include "../../src/systemcmds/tests/tests.h"

#include "gtest/gtest.h"

TEST(MixerTest, Mixer)
{
	const char *args[] = {"empty", "../ROMFS/px4fmu_common/mixers/IO_pass.mix", "../ROMFS/px4fmu_common/mixers/sk450_deadcat.main.mix"};
	ASSERT_EQ(test_mixer(3, (char **)args), 0) << "IO_pass.mix failed";
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mtpobjectsmodel.h"
#include <QDebug>
#include <QMessageBox>
#include <QKeyEvent>

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	_ui(new Ui::MainWindow),
	_objectModel(new MtpObjectsModel)
{
	_ui->setupUi(this);
	connect(_ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(onActivated(QModelIndex)));
	connect(_ui->listView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customContextMenuRequested(QPoint)));
}

MainWindow::~MainWindow()
{
	delete _ui;
}

void MainWindow::showEvent(QShowEvent *)
{
	if (!_device)
	{
		_device = mtp::Device::Find();
		if (!_device)
		{
			QMessageBox::critical(this, tr("MTP was not found"), tr("No MTP device found"));
			qFatal("device was not found");
		}
		_objectModel->setSession(_device->OpenSession(1));
		_ui->listView->setModel(_objectModel);
	}
}

void MainWindow::onActivated ( const QModelIndex & index )
{
	if (_objectModel->enter(index.row()))
		_history.push_back(_objectModel->parentObjectId());
}

void MainWindow::customContextMenuRequested ( const QPoint & pos )
{
	QItemSelectionModel *selection =_ui->listView->selectionModel();
	QModelIndexList rows = selection->selectedRows();

	QMenu menu(this);
	//http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
	QAction * delete_objects = menu.addAction(QIcon::fromTheme("edit-delete"), "Delete");
	QAction * action = menu.exec(_ui->listView->mapToGlobal(pos));
	if (!action)
		return;

	for(int i = 0; i < rows.size(); ++i)
	{
		if (action == delete_objects)
			_objectModel->removeRow(rows[i].row());
		else
			qDebug() << "unknown action!";
	}
}

void MainWindow::back()
{
	if (!_history.empty())
	{
		_history.pop_back();
		mtp::u32 oid = _history.empty()? mtp::Session::Root: _history.back();
		_objectModel->setParent(oid);
	}
}

void MainWindow::keyPressEvent ( QKeyEvent * event )
{
	switch(event->key())
	{
	case Qt::Key_Enter:
		qDebug() << "ENTER";
		{
			if (_objectModel->enter(_ui->listView->currentIndex().row()))
				_history.push_back(_objectModel->parentObjectId());
		}
		break;
	case Qt::Key_Escape:
		back();
		break;
	}
}

<commit_msg>delete objects in reverse order<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mtpobjectsmodel.h"
#include <QDebug>
#include <QMessageBox>
#include <QKeyEvent>

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent),
	_ui(new Ui::MainWindow),
	_objectModel(new MtpObjectsModel)
{
	_ui->setupUi(this);
	connect(_ui->listView, SIGNAL(doubleClicked(QModelIndex)), SLOT(onActivated(QModelIndex)));
	connect(_ui->listView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customContextMenuRequested(QPoint)));
}

MainWindow::~MainWindow()
{
	delete _ui;
}

void MainWindow::showEvent(QShowEvent *)
{
	if (!_device)
	{
		_device = mtp::Device::Find();
		if (!_device)
		{
			QMessageBox::critical(this, tr("MTP was not found"), tr("No MTP device found"));
			qFatal("device was not found");
		}
		_objectModel->setSession(_device->OpenSession(1));
		_ui->listView->setModel(_objectModel);
	}
}

void MainWindow::onActivated ( const QModelIndex & index )
{
	if (_objectModel->enter(index.row()))
		_history.push_back(_objectModel->parentObjectId());
}

void MainWindow::customContextMenuRequested ( const QPoint & pos )
{
	QItemSelectionModel *selection =_ui->listView->selectionModel();
	QModelIndexList rows = selection->selectedRows();

	QMenu menu(this);
	//http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
	QAction * delete_objects = menu.addAction(QIcon::fromTheme("edit-delete"), "Delete");
	QAction * action = menu.exec(_ui->listView->mapToGlobal(pos));
	if (!action)
		return;

	for(int i = rows.size() - 1; i >= 0; --i)
	{
		if (action == delete_objects)
			_objectModel->removeRow(rows[i].row());
		else
			qDebug() << "unknown action!";
	}
}

void MainWindow::back()
{
	if (!_history.empty())
	{
		_history.pop_back();
		mtp::u32 oid = _history.empty()? mtp::Session::Root: _history.back();
		_objectModel->setParent(oid);
	}
}

void MainWindow::keyPressEvent ( QKeyEvent * event )
{
	switch(event->key())
	{
	case Qt::Key_Enter:
		qDebug() << "ENTER";
		{
			if (_objectModel->enter(_ui->listView->currentIndex().row()))
				_history.push_back(_objectModel->parentObjectId());
		}
		break;
	case Qt::Key_Escape:
		back();
		break;
	}
}

<|endoftext|>


<commit_before>#include <mirrage/renderer/particle_system.hpp>

#include <mirrage/ecs/components/transform_comp.hpp>

#include <mirrage/utils/ranges.hpp>

namespace mirrage::renderer {

	namespace {
		glm::vec3 spherical_rand(std::mt19937& gen)
		{
			float theta = std::uniform_real_distribution(0.f, 6.283185307179586476925286766559f)(gen);
			float phi   = std::acos(std::uniform_real_distribution(-1.0f, 1.0f)(gen));

			float x = std::sin(phi) * std::cos(theta);
			float y = std::sin(phi) * std::sin(theta);
			float z = std::cos(phi);

			return {x, y, z};
		}

		template <typename T, typename I>
		void erase_by(std::vector<T>& v, const std::vector<I> indices)
		{
			for(auto i : indices) {
				v.erase(v.begin() + i);
			}
		}
	} // namespace

	auto Particle_emitter_config::calc_offset(std::mt19937& gen) -> std::tuple<glm::vec3, glm::vec3>
	{
		switch(shape) {
			case Particle_emitter_shape::sphere: {
				auto dir    = spherical_rand(gen);
				auto radius = std::uniform_real_distribution(0.f, shape_size.x)(gen);
				return {dir *= radius, dir};
			}
		}
		MIRRAGE_FAIL("Unhandled particle shape: " << int(shape));
	}

	Particle_emitter::Particle_emitter(graphic::Texture_ptr                 texture,
	                                   std::vector<Particle_emitter_config> keyframes,
	                                   std::size_t                          capacity,
	                                   util::maybe<ecs::Entity_facet>       follow_entity)
	  : _texture(std::move(texture)), _config_keyframes(std::move(keyframes)), _follow_entity(follow_entity)
	{
		_positions.reserve(capacity);
		_seeds.reserve(capacity);
		_creation_times.reserve(capacity);
		_ttls.reserve(capacity);
		_velocities.reserve(capacity);
	}

	void Particle_emitter::update(util::Time dt, bool emit_new, std::mt19937& gen)
	{
		const auto now = _time.value();

		_follow_entity.process([&](auto& entity) {
			auto transform = entity ? entity.template get<ecs::components::Transform_comp>() : util::nothing;
			if(transform.is_some()) {
				_center_position = transform.get_or_throw().position;
			} else {
				_follow_entity = util::nothing;
			}
		});

		auto config      = _config_keyframes.at(0); // TODO: interpolate
		auto drag_factor = 1.f - config.drag * dt.value();

		// update existing particles
		for(auto i : util::range(_positions.size())) {
			auto vel = _velocities[i];
			_positions[i] += vel * dt.value();
			_velocities[i] *= drag_factor;
		}

		// find dead particles (high indices to low)
		auto dead_count = std::count_if(_ttls.begin(), _ttls.end(), [=](auto t) { return t <= now; });
		_dead_indices.reserve(gsl::narrow<std::size_t>(dead_count));
		auto i = std::int_fast32_t(0);
		for(auto ttl : util::range_reverse(_ttls)) {
			if(ttl <= now)
				_dead_indices.emplace_back(i);

			i++;
		}

		// spawn new particles
		if(_active && emit_new) {
			auto spawn_rate =
			        std::normal_distribution(config.spawn_rate_mean, config.spawn_rate_variance)(gen);
			_to_spawn += spawn_rate * dt.value();
			auto spawn_now = std::size_t(_to_spawn);
			_to_spawn -= spawn_now;

			auto spawn = [&](auto i) {
				auto [offset, direction] = config.calc_offset(gen);
				_positions[i]            = _center_position + offset;
				_seeds[i]                = std::uniform_int_distribution<std::uint32_t>(0)(gen);
				_creation_times[i]       = now;
				_ttls[i] = now + std::normal_distribution(config.ttl_mean, config.ttl_variance)(gen);
				_velocities[i] =
				        direction
				        * std::normal_distribution(config.velocity_mean, config.velocity_variance)(gen);
			};

			// reuse old slots
			while(spawn_now > 0 && !_dead_indices.empty()) {
				spawn(std::size_t(_dead_indices.back()));
				_dead_indices.pop_back();
				spawn_now--;
			}

			// create new slots
			auto new_size = _positions.size() + spawn_now;
			_positions.resize(new_size);
			_seeds.resize(new_size);
			_creation_times.resize(new_size);
			_ttls.resize(new_size);
			_velocities.resize(new_size);

			for(auto i : util::range(spawn_now)) {
				spawn(_positions.size() - 1u - i);
			}
		}

		// remove dead particles
		if(!_dead_indices.empty()) {
			erase_by(_positions, _dead_indices);
			erase_by(_seeds, _dead_indices);
			erase_by(_creation_times, _dead_indices);
			erase_by(_ttls, _dead_indices);
			erase_by(_velocities, _dead_indices);

			_dead_indices.clear();
		}

		_time += dt;
	}

	Particle_system::Particle_system(asset::Asset_manager& assets)
	  : _assets(assets), _random_gen(std::random_device()())
	{
	}

	void Particle_system::add_emitter(std::shared_ptr<Particle_emitter> e)
	{
		_emmitter.emplace_back(std::move(e));
	}

	namespace {
		struct Emitter_descriptor {
			std::string                          texture_aid;
			std::vector<Particle_emitter_config> keyframes;
		};
		sf2_structDef(Emitter_descriptor, texture_aid, keyframes);
	} // namespace
	auto Particle_system::add_emitter(asset::AID descriptor) -> std::shared_ptr<Particle_emitter>
	{
		// TODO: load destriptor
		return {};
	}

	void Particle_system::update(util::Time dt)
	{
		for(auto& e : _emmitter) {
			e->update(dt, e.use_count() > 1, _random_gen);
		}

		util::erase_if(_emmitter, [&](auto& e) { return e.use_count() <= 1 && e->dead(); });
	}

} // namespace mirrage::renderer
<commit_msg>removed currently unused code<commit_after>#include <mirrage/renderer/particle_system.hpp>

#include <mirrage/ecs/components/transform_comp.hpp>

#include <mirrage/utils/ranges.hpp>

namespace mirrage::renderer {

	namespace {
		glm::vec3 spherical_rand(std::mt19937& gen)
		{
			float theta = std::uniform_real_distribution(0.f, 6.283185307179586476925286766559f)(gen);
			float phi   = std::acos(std::uniform_real_distribution(-1.0f, 1.0f)(gen));

			float x = std::sin(phi) * std::cos(theta);
			float y = std::sin(phi) * std::sin(theta);
			float z = std::cos(phi);

			return {x, y, z};
		}

		template <typename T, typename I>
		void erase_by(std::vector<T>& v, const std::vector<I> indices)
		{
			for(auto i : indices) {
				v.erase(v.begin() + i);
			}
		}
	} // namespace

	auto Particle_emitter_config::calc_offset(std::mt19937& gen) -> std::tuple<glm::vec3, glm::vec3>
	{
		switch(shape) {
			case Particle_emitter_shape::sphere: {
				auto dir    = spherical_rand(gen);
				auto radius = std::uniform_real_distribution(0.f, shape_size.x)(gen);
				return {dir *= radius, dir};
			}
		}
		MIRRAGE_FAIL("Unhandled particle shape: " << int(shape));
	}

	Particle_emitter::Particle_emitter(graphic::Texture_ptr                 texture,
	                                   std::vector<Particle_emitter_config> keyframes,
	                                   std::size_t                          capacity,
	                                   util::maybe<ecs::Entity_facet>       follow_entity)
	  : _texture(std::move(texture)), _config_keyframes(std::move(keyframes)), _follow_entity(follow_entity)
	{
		_positions.reserve(capacity);
		_seeds.reserve(capacity);
		_creation_times.reserve(capacity);
		_ttls.reserve(capacity);
		_velocities.reserve(capacity);
	}

	void Particle_emitter::update(util::Time dt, bool emit_new, std::mt19937& gen)
	{
		const auto now = _time.value();

		_follow_entity.process([&](auto& entity) {
			auto transform = entity ? entity.template get<ecs::components::Transform_comp>() : util::nothing;
			if(transform.is_some()) {
				_center_position = transform.get_or_throw().position;
			} else {
				_follow_entity = util::nothing;
			}
		});

		auto config      = _config_keyframes.at(0); // TODO: interpolate
		auto drag_factor = 1.f - config.drag * dt.value();

		// update existing particles
		for(auto i : util::range(_positions.size())) {
			auto vel = _velocities[i];
			_positions[i] += vel * dt.value();
			_velocities[i] *= drag_factor;
		}

		// find dead particles (high indices to low)
		auto dead_count = std::count_if(_ttls.begin(), _ttls.end(), [=](auto t) { return t <= now; });
		_dead_indices.reserve(gsl::narrow<std::size_t>(dead_count));
		auto i = std::int_fast32_t(0);
		for(auto ttl : util::range_reverse(_ttls)) {
			if(ttl <= now)
				_dead_indices.emplace_back(i);

			i++;
		}

		// spawn new particles
		if(_active && emit_new) {
			auto spawn_rate =
			        std::normal_distribution(config.spawn_rate_mean, config.spawn_rate_variance)(gen);
			_to_spawn += spawn_rate * dt.value();
			auto spawn_now = std::size_t(_to_spawn);
			_to_spawn -= spawn_now;

			auto spawn = [&](auto i) {
				auto [offset, direction] = config.calc_offset(gen);
				_positions[i]            = _center_position + offset;
				_seeds[i]                = std::uniform_int_distribution<std::uint32_t>(0)(gen);
				_creation_times[i]       = now;
				_ttls[i] = now + std::normal_distribution(config.ttl_mean, config.ttl_variance)(gen);
				_velocities[i] =
				        direction
				        * std::normal_distribution(config.velocity_mean, config.velocity_variance)(gen);
			};

			// reuse old slots
			while(spawn_now > 0 && !_dead_indices.empty()) {
				spawn(std::size_t(_dead_indices.back()));
				_dead_indices.pop_back();
				spawn_now--;
			}

			// create new slots
			auto new_size = _positions.size() + spawn_now;
			_positions.resize(new_size);
			_seeds.resize(new_size);
			_creation_times.resize(new_size);
			_ttls.resize(new_size);
			_velocities.resize(new_size);

			for(auto i : util::range(spawn_now)) {
				spawn(_positions.size() - 1u - i);
			}
		}

		// remove dead particles
		if(!_dead_indices.empty()) {
			erase_by(_positions, _dead_indices);
			erase_by(_seeds, _dead_indices);
			erase_by(_creation_times, _dead_indices);
			erase_by(_ttls, _dead_indices);
			erase_by(_velocities, _dead_indices);

			_dead_indices.clear();
		}

		_time += dt;
	}

	Particle_system::Particle_system(asset::Asset_manager& assets)
	  : _assets(assets), _random_gen(std::random_device()())
	{
	}

	void Particle_system::add_emitter(std::shared_ptr<Particle_emitter> e)
	{
		_emmitter.emplace_back(std::move(e));
	}
	/*
	namespace {
		struct Emitter_descriptor {
			std::string                          texture_aid;
			std::vector<Particle_emitter_config> keyframes;
		};
		sf2_structDef(Emitter_descriptor, texture_aid, keyframes);
	} // namespace
	*/
	auto Particle_system::add_emitter(asset::AID descriptor) -> std::shared_ptr<Particle_emitter>
	{
		// TODO: load destriptor
		return {};
	}

	void Particle_system::update(util::Time dt)
	{
		for(auto& e : _emmitter) {
			e->update(dt, e.use_count() > 1, _random_gen);
		}

		util::erase_if(_emmitter, [&](auto& e) { return e.use_count() <= 1 && e->dead(); });
	}

} // namespace mirrage::renderer
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE SparseAutoencoderTest

#include <mlpack/core.hpp>
#include "sparse_autoencoder.hpp"

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace mlpack;
using namespace mlpack::nn;

BOOST_AUTO_TEST_SUITE(SparseAutoencoderTest);

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionEvaluate)
{
  const size_t vSize = 5;
  const size_t hSize = 3;
  const size_t r = 2*hSize + 1;
  const size_t c = vSize + 1;

  // Simple fake dataset.
  arma::mat data1("0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5");
  // Transpose of the above dataset.
  arma::mat data2 = data1.t();

  // Create a SparseAutoencoderFunction. Regularization and KL divergence terms
  // ignored.
  SparseAutoencoderFunction saf1(data1, vSize, hSize, 0, 0);

  // Test using first dataset. Values were calculated using Octave.
  BOOST_REQUIRE_CLOSE(saf1.Evaluate(arma::ones(r, c)), 1.190472606540, 1e-5);
  BOOST_REQUIRE_CLOSE(saf1.Evaluate(arma::zeros(r, c)), 0.150000000000, 1e-5);
  BOOST_REQUIRE_CLOSE(saf1.Evaluate(-arma::ones(r, c)), 0.048800332266, 1e-5);

  // Create a SparseAutoencoderFunction. Regularization and KL divergence terms
  // ignored.
  SparseAutoencoderFunction saf2(data2, vSize, hSize, 0, 0);

  // Test using second dataset. Values were calculated using Octave.
  BOOST_REQUIRE_CLOSE(saf2.Evaluate(arma::ones(r, c)), 1.197585812647, 1e-5);
  BOOST_REQUIRE_CLOSE(saf2.Evaluate(arma::zeros(r, c)), 0.150000000000, 1e-5);
  BOOST_REQUIRE_CLOSE(saf2.Evaluate(-arma::ones(r, c)), 0.063466617408, 1e-5);
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionRandomEvaluate)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // Create a SparseAutoencoderFunction. Regularization and KL divergence terms
  // ignored.
  SparseAutoencoderFunction saf(data, vSize, hSize, 0, 0);

  // Run a number of trials.
  for(size_t i = 0; i < trials; i++)
  {
    // Create a random set of parameters.
    arma::mat parameters;
    parameters.randu(l3+1, l2+1);

    double reconstructionError = 0;

    // Compute error for each training example.
    for(size_t j = 0; j < points; j++)
    {
      arma::mat hiddenLayer, outputLayer, diff;

      hiddenLayer = 1.0 / (1 + arma::exp(-(parameters.submat(0, 0, l1-1, l2-1) *
          data.col(j) + parameters.submat(0, l2, l1-1, l2))));
      outputLayer = 1.0 / (1 + arma::exp(-(parameters.submat(l1,0,l3-1,l2-1).t()
          * hiddenLayer + parameters.submat(l3, 0, l3, l2-1).t())));
      diff = outputLayer - data.col(j);

      reconstructionError += 0.5 * arma::sum(arma::sum(diff % diff));
    }
    reconstructionError /= points;

    // Compare with the value returned by the function.
    BOOST_REQUIRE_CLOSE(saf.Evaluate(parameters), reconstructionError, 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionRegularizationEvaluate)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // 3 objects for comparing regularization costs.
  SparseAutoencoderFunction safNoReg(data, vSize, hSize, 0, 0);
  SparseAutoencoderFunction safSmallReg(data, vSize, hSize, 0.5, 0);
  SparseAutoencoderFunction safBigReg(data, vSize, hSize, 20, 0);

  // Run a number of trials.
  for(size_t i = 0; i < trials; i++)
  {
    // Create a random set of parameters.
    arma::mat parameters;
    parameters.randu(l3+1, l2+1);

    double wL2SquaredNorm;

    wL2SquaredNorm = arma::accu(parameters.submat(0, 0, l3-1, l2-1) %
        parameters.submat(0, 0, l3-1, l2-1));

    // Calculate regularization terms.
    const double smallRegTerm = 0.25 * wL2SquaredNorm;
    const double bigRegTerm = 10 * wL2SquaredNorm;

    BOOST_REQUIRE_CLOSE(safNoReg.Evaluate(parameters) + smallRegTerm,
        safSmallReg.Evaluate(parameters), 1e-5);
    BOOST_REQUIRE_CLOSE(safNoReg.Evaluate(parameters) + bigRegTerm,
        safBigReg.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionKLDivergenceEvaluate)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  const double rho = 0.01;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // 3 objects for comparing divergence costs.
  SparseAutoencoderFunction safNoDiv(data, vSize, hSize, 0, 0, rho);
  SparseAutoencoderFunction safSmallDiv(data, vSize, hSize, 0, 5, rho);
  SparseAutoencoderFunction safBigDiv(data, vSize, hSize, 0, 20, rho);

  // Run a number of trials.
  for(size_t i = 0; i < trials; i++)
  {
    // Create a random set of parameters.
    arma::mat parameters;
    parameters.randu(l3+1, l2+1);

    arma::mat rhoCap;
    rhoCap.zeros(hSize, 1);

    // Compute hidden layer activations for each example.
    for(size_t j = 0; j < points; j++)
    {
      arma::mat hiddenLayer;

      hiddenLayer = 1.0 / (1 + arma::exp(-(parameters.submat(0, 0, l1-1, l2-1) *
          data.col(j) + parameters.submat(0, l2, l1-1, l2))));
      rhoCap += hiddenLayer;
    }
    rhoCap /= points;

    // Calculate divergence terms.
    const double smallDivTerm = 5 * arma::accu(rho * arma::log(rho / rhoCap) +
        (1 - rho) * arma::log((1 - rho) / (1 - rhoCap)));
    const double bigDivTerm = 20 * arma::accu(rho * arma::log(rho / rhoCap) +
        (1 - rho) * arma::log((1 - rho) / (1 - rhoCap)));

    BOOST_REQUIRE_CLOSE(safNoDiv.Evaluate(parameters) + smallDivTerm,
        safSmallDiv.Evaluate(parameters), 1e-5);
    BOOST_REQUIRE_CLOSE(safNoDiv.Evaluate(parameters) + bigDivTerm,
        safBigDiv.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionGradient)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // 3 objects for 3 terms in the cost function. Each term contributes towards
  // the gradient and thus need to be checked independently.
  SparseAutoencoderFunction saf1(data, vSize, hSize, 0, 0);
  SparseAutoencoderFunction saf2(data, vSize, hSize, 20, 0);
  SparseAutoencoderFunction saf3(data, vSize, hSize, 20, 20);

  // Create a random set of parameters.
  arma::mat parameters;
  parameters.randu(l3+1, l2+1);

  // Get gradients for the current parameters.
  arma::mat gradient1, gradient2, gradient3;
  saf1.Gradient(parameters, gradient1);
  saf2.Gradient(parameters, gradient2);
  saf3.Gradient(parameters, gradient3);

  // Perturbation constant.
  const double epsilon = 0.0001;
  double costPlus1, costMinus1, numGradient1;
  double costPlus2, costMinus2, numGradient2;
  double costPlus3, costMinus3, numGradient3;

  // For each parameter.
  for(size_t i = 0; i <= l3; i++)
  {
    for(size_t j = 0; j <= l2; j++)
    {
      // Perturb parameter with a positive constant and get costs.
      parameters(i, j) += epsilon;
      costPlus1 = saf1.Evaluate(parameters);
      costPlus2 = saf2.Evaluate(parameters);
      costPlus3 = saf3.Evaluate(parameters);

      // Perturb parameter with a negative constant and get costs.
      parameters(i, j) -= 2*epsilon;
      costMinus1 = saf1.Evaluate(parameters);
      costMinus2 = saf2.Evaluate(parameters);
      costMinus3 = saf3.Evaluate(parameters);

      // Compute numerical gradients using the costs calculated above.
      numGradient1 = (costPlus1 - costMinus1) / (2*epsilon);
      numGradient2 = (costPlus2 - costMinus2) / (2*epsilon);
      numGradient3 = (costPlus3 - costMinus3) / (2*epsilon);

      // Restore the parameter value.
      parameters(i, j) += epsilon;

      // Compare numerical and backpropagation gradient values.
      BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 1e-2);
      BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 1e-2);
      BOOST_REQUIRE_CLOSE(numGradient3, gradient3(i, j), 1e-2);
    }
  }
}

BOOST_AUTO_TEST_SUITE_END();
<commit_msg>Adapt test to work in the larger framework of mlpack tests.<commit_after>/**
 * @file sparse_autoencoder_test.cpp
 * @author Siddharth Agrawal
 *
 * Test the SparseAutoencoder class.
 */
#include <mlpack/core.hpp>
#include <mlpack/methods/sparse_autoencoder/sparse_autoencoder.hpp>

#include <boost/test/unit_test.hpp>
#include "old_boost_test_definitions.hpp"

using namespace mlpack;
using namespace mlpack::nn;

BOOST_AUTO_TEST_SUITE(SparseAutoencoderTest);

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionEvaluate)
{
  const size_t vSize = 5;
  const size_t hSize = 3;
  const size_t r = 2*hSize + 1;
  const size_t c = vSize + 1;

  // Simple fake dataset.
  arma::mat data1("0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5;"
                  "0.1 0.2 0.3 0.4 0.5");
  // Transpose of the above dataset.
  arma::mat data2 = data1.t();

  // Create a SparseAutoencoderFunction. Regularization and KL divergence terms
  // ignored.
  SparseAutoencoderFunction saf1(data1, vSize, hSize, 0, 0);

  // Test using first dataset. Values were calculated using Octave.
  BOOST_REQUIRE_CLOSE(saf1.Evaluate(arma::ones(r, c)), 1.190472606540, 1e-5);
  BOOST_REQUIRE_CLOSE(saf1.Evaluate(arma::zeros(r, c)), 0.150000000000, 1e-5);
  BOOST_REQUIRE_CLOSE(saf1.Evaluate(-arma::ones(r, c)), 0.048800332266, 1e-5);

  // Create a SparseAutoencoderFunction. Regularization and KL divergence terms
  // ignored.
  SparseAutoencoderFunction saf2(data2, vSize, hSize, 0, 0);

  // Test using second dataset. Values were calculated using Octave.
  BOOST_REQUIRE_CLOSE(saf2.Evaluate(arma::ones(r, c)), 1.197585812647, 1e-5);
  BOOST_REQUIRE_CLOSE(saf2.Evaluate(arma::zeros(r, c)), 0.150000000000, 1e-5);
  BOOST_REQUIRE_CLOSE(saf2.Evaluate(-arma::ones(r, c)), 0.063466617408, 1e-5);
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionRandomEvaluate)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // Create a SparseAutoencoderFunction. Regularization and KL divergence terms
  // ignored.
  SparseAutoencoderFunction saf(data, vSize, hSize, 0, 0);

  // Run a number of trials.
  for(size_t i = 0; i < trials; i++)
  {
    // Create a random set of parameters.
    arma::mat parameters;
    parameters.randu(l3+1, l2+1);

    double reconstructionError = 0;

    // Compute error for each training example.
    for(size_t j = 0; j < points; j++)
    {
      arma::mat hiddenLayer, outputLayer, diff;

      hiddenLayer = 1.0 / (1 + arma::exp(-(parameters.submat(0, 0, l1-1, l2-1) *
          data.col(j) + parameters.submat(0, l2, l1-1, l2))));
      outputLayer = 1.0 / (1 + arma::exp(-(parameters.submat(l1,0,l3-1,l2-1).t()
          * hiddenLayer + parameters.submat(l3, 0, l3, l2-1).t())));
      diff = outputLayer - data.col(j);

      reconstructionError += 0.5 * arma::sum(arma::sum(diff % diff));
    }
    reconstructionError /= points;

    // Compare with the value returned by the function.
    BOOST_REQUIRE_CLOSE(saf.Evaluate(parameters), reconstructionError, 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionRegularizationEvaluate)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // 3 objects for comparing regularization costs.
  SparseAutoencoderFunction safNoReg(data, vSize, hSize, 0, 0);
  SparseAutoencoderFunction safSmallReg(data, vSize, hSize, 0.5, 0);
  SparseAutoencoderFunction safBigReg(data, vSize, hSize, 20, 0);

  // Run a number of trials.
  for(size_t i = 0; i < trials; i++)
  {
    // Create a random set of parameters.
    arma::mat parameters;
    parameters.randu(l3+1, l2+1);

    double wL2SquaredNorm;

    wL2SquaredNorm = arma::accu(parameters.submat(0, 0, l3-1, l2-1) %
        parameters.submat(0, 0, l3-1, l2-1));

    // Calculate regularization terms.
    const double smallRegTerm = 0.25 * wL2SquaredNorm;
    const double bigRegTerm = 10 * wL2SquaredNorm;

    BOOST_REQUIRE_CLOSE(safNoReg.Evaluate(parameters) + smallRegTerm,
        safSmallReg.Evaluate(parameters), 1e-5);
    BOOST_REQUIRE_CLOSE(safNoReg.Evaluate(parameters) + bigRegTerm,
        safBigReg.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionKLDivergenceEvaluate)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  const double rho = 0.01;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // 3 objects for comparing divergence costs.
  SparseAutoencoderFunction safNoDiv(data, vSize, hSize, 0, 0, rho);
  SparseAutoencoderFunction safSmallDiv(data, vSize, hSize, 0, 5, rho);
  SparseAutoencoderFunction safBigDiv(data, vSize, hSize, 0, 20, rho);

  // Run a number of trials.
  for(size_t i = 0; i < trials; i++)
  {
    // Create a random set of parameters.
    arma::mat parameters;
    parameters.randu(l3+1, l2+1);

    arma::mat rhoCap;
    rhoCap.zeros(hSize, 1);

    // Compute hidden layer activations for each example.
    for(size_t j = 0; j < points; j++)
    {
      arma::mat hiddenLayer;

      hiddenLayer = 1.0 / (1 + arma::exp(-(parameters.submat(0, 0, l1-1, l2-1) *
          data.col(j) + parameters.submat(0, l2, l1-1, l2))));
      rhoCap += hiddenLayer;
    }
    rhoCap /= points;

    // Calculate divergence terms.
    const double smallDivTerm = 5 * arma::accu(rho * arma::log(rho / rhoCap) +
        (1 - rho) * arma::log((1 - rho) / (1 - rhoCap)));
    const double bigDivTerm = 20 * arma::accu(rho * arma::log(rho / rhoCap) +
        (1 - rho) * arma::log((1 - rho) / (1 - rhoCap)));

    BOOST_REQUIRE_CLOSE(safNoDiv.Evaluate(parameters) + smallDivTerm,
        safSmallDiv.Evaluate(parameters), 1e-5);
    BOOST_REQUIRE_CLOSE(safNoDiv.Evaluate(parameters) + bigDivTerm,
        safBigDiv.Evaluate(parameters), 1e-5);
  }
}

BOOST_AUTO_TEST_CASE(SparseAutoencoderFunctionGradient)
{
  const size_t points = 1000;
  const size_t trials = 50;
  const size_t vSize = 20;
  const size_t hSize = 10;
  const size_t l1 = hSize;
  const size_t l2 = vSize;
  const size_t l3 = 2*hSize;

  // Initialize a random dataset.
  arma::mat data;
  data.randu(vSize, points);

  // 3 objects for 3 terms in the cost function. Each term contributes towards
  // the gradient and thus need to be checked independently.
  SparseAutoencoderFunction saf1(data, vSize, hSize, 0, 0);
  SparseAutoencoderFunction saf2(data, vSize, hSize, 20, 0);
  SparseAutoencoderFunction saf3(data, vSize, hSize, 20, 20);

  // Create a random set of parameters.
  arma::mat parameters;
  parameters.randu(l3+1, l2+1);

  // Get gradients for the current parameters.
  arma::mat gradient1, gradient2, gradient3;
  saf1.Gradient(parameters, gradient1);
  saf2.Gradient(parameters, gradient2);
  saf3.Gradient(parameters, gradient3);

  // Perturbation constant.
  const double epsilon = 0.0001;
  double costPlus1, costMinus1, numGradient1;
  double costPlus2, costMinus2, numGradient2;
  double costPlus3, costMinus3, numGradient3;

  // For each parameter.
  for(size_t i = 0; i <= l3; i++)
  {
    for(size_t j = 0; j <= l2; j++)
    {
      // Perturb parameter with a positive constant and get costs.
      parameters(i, j) += epsilon;
      costPlus1 = saf1.Evaluate(parameters);
      costPlus2 = saf2.Evaluate(parameters);
      costPlus3 = saf3.Evaluate(parameters);

      // Perturb parameter with a negative constant and get costs.
      parameters(i, j) -= 2*epsilon;
      costMinus1 = saf1.Evaluate(parameters);
      costMinus2 = saf2.Evaluate(parameters);
      costMinus3 = saf3.Evaluate(parameters);

      // Compute numerical gradients using the costs calculated above.
      numGradient1 = (costPlus1 - costMinus1) / (2*epsilon);
      numGradient2 = (costPlus2 - costMinus2) / (2*epsilon);
      numGradient3 = (costPlus3 - costMinus3) / (2*epsilon);

      // Restore the parameter value.
      parameters(i, j) += epsilon;

      // Compare numerical and backpropagation gradient values.
      BOOST_REQUIRE_CLOSE(numGradient1, gradient1(i, j), 1e-2);
      BOOST_REQUIRE_CLOSE(numGradient2, gradient2(i, j), 1e-2);
      BOOST_REQUIRE_CLOSE(numGradient3, gradient3(i, j), 1e-2);
    }
  }
}

BOOST_AUTO_TEST_SUITE_END();
<|endoftext|>