<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2016-2020 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chain.h"
#include "legacy/stakemodifier.h"  // for ComputeNextStakeModifier

/**
 * CChain implementation
 */
void CChain::SetTip(CBlockIndex* pindex)
{
    if (pindex == NULL) {
        vChain.clear();
        return;
    }
    vChain.resize(pindex->nHeight + 1);
    while (pindex && vChain[pindex->nHeight] != pindex) {
        vChain[pindex->nHeight] = pindex;
        pindex = pindex->pprev;
    }
}

CBlockLocator CChain::GetLocator(const CBlockIndex* pindex) const
{
    int nStep = 1;
    std::vector<uint256> vHave;
    vHave.reserve(32);

    if (!pindex)
        pindex = Tip();
    while (pindex) {
        vHave.push_back(pindex->GetBlockHash());
        // Stop when we have added the genesis block.
        if (pindex->nHeight == 0)
            break;
        // Exponentially larger steps back, plus the genesis block.
        int nHeight = std::max(pindex->nHeight - nStep, 0);
        if (Contains(pindex)) {
            // Use O(1) CChain index if possible.
            pindex = (*this)[nHeight];
        } else {
            // Otherwise, use O(log n) skiplist.
            pindex = pindex->GetAncestor(nHeight);
        }
        if (vHave.size() > 10)
            nStep *= 2;
    }

    return CBlockLocator(vHave);
}

const CBlockIndex* CChain::FindFork(const CBlockIndex* pindex) const
{
    if (pindex == nullptr)
        return nullptr;
    if (pindex->nHeight > Height())
        pindex = pindex->GetAncestor(Height());
    while (pindex && !Contains(pindex))
        pindex = pindex->pprev;
    return pindex;
}

CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime) const
{
    std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
        [](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
    return (lower == vChain.end() ? nullptr : *lower);
}

/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
int static inline InvertLowestOne(int n) { return n & (n - 1); }

/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
int static inline GetSkipHeight(int height)
{
    if (height < 2)
        return 0;
    // Determine which height to jump back to. Any number strictly lower than height is acceptable,
    // but the following expression seems to perform well in simulations (max 110 steps to go back
    // up to 2**18 blocks).
    return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
}

CBlockIndex* CBlockIndex::GetAncestor(int height)
{
    if (height > nHeight || height < 0)
        return NULL;

    CBlockIndex* pindexWalk = this;
    int heightWalk = nHeight;
    while (heightWalk > height) {
        int heightSkip = GetSkipHeight(heightWalk);
        int heightSkipPrev = GetSkipHeight(heightWalk - 1);
        if (heightSkip == height ||
            (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && heightSkipPrev >= height))) {
            // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
            pindexWalk = pindexWalk->pskip;
            heightWalk = heightSkip;
        } else {
            pindexWalk = pindexWalk->pprev;
            heightWalk--;
        }
    }
    return pindexWalk;
}

const CBlockIndex* CBlockIndex::GetAncestor(int height) const
{
    return const_cast<CBlockIndex*>(this)->GetAncestor(height);
}

void CBlockIndex::BuildSkip()
{
    if (pprev)
        pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}

CBlockIndex::CBlockIndex(const CBlock& block):
        nVersion{block.nVersion},
        hashMerkleRoot{block.hashMerkleRoot},
        hashFinalSaplingRoot(block.hashFinalSaplingRoot),
        nTime{block.nTime},
        nBits{block.nBits},
        nNonce{block.nNonce}
{
    if(block.nVersion > 3 && block.nVersion < 7)
        nAccumulatorCheckpoint = block.nAccumulatorCheckpoint;
    if (block.IsProofOfStake())
        SetProofOfStake();
}

std::string CBlockIndex::ToString() const
{
    return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
        pprev, nHeight,
        hashMerkleRoot.ToString(),
        GetBlockHash().ToString());
}

CDiskBlockPos CBlockIndex::GetBlockPos() const
{
    CDiskBlockPos ret;
    if (nStatus & BLOCK_HAVE_DATA) {
        ret.nFile = nFile;
        ret.nPos = nDataPos;
    }
    return ret;
}

CDiskBlockPos CBlockIndex::GetUndoPos() const
{
    CDiskBlockPos ret;
    if (nStatus & BLOCK_HAVE_UNDO) {
        ret.nFile = nFile;
        ret.nPos = nUndoPos;
    }
    return ret;
}

CBlockHeader CBlockIndex::GetBlockHeader() const
{
    CBlockHeader block;
    block.nVersion = nVersion;
    if (pprev) block.hashPrevBlock = pprev->GetBlockHash();
    block.hashMerkleRoot = hashMerkleRoot;
    block.nTime = nTime;
    block.nBits = nBits;
    block.nNonce = nNonce;
    if (nVersion > 3 && nVersion < 7) block.nAccumulatorCheckpoint = nAccumulatorCheckpoint;
    if (nVersion >= 8) block.hashFinalSaplingRoot = hashFinalSaplingRoot;
    return block;
}

int64_t CBlockIndex::MaxFutureBlockTime() const
{
    return GetAdjustedTime() + Params().GetConsensus().FutureBlockTimeDrift(nHeight+1);
}

int64_t CBlockIndex::MinPastBlockTime() const
{
    const Consensus::Params& consensus = Params().GetConsensus();
    // Time Protocol v1: pindexPrev->MedianTimePast + 1
    if (!consensus.IsTimeProtocolV2(nHeight+1))
        return GetMedianTimePast();

    // on the transition from Time Protocol v1 to v2
    // pindexPrev->nTime might be in the future (up to the allowed drift)
    // so we allow the nBlockTimeProtocolV2 (PIVX v4.0) to be at most (180-14) seconds earlier than previous block
    if (nHeight + 1 == consensus.vUpgrades[Consensus::UPGRADE_V4_0].nActivationHeight)
        return GetBlockTime() - consensus.FutureBlockTimeDrift(nHeight) + consensus.FutureBlockTimeDrift(nHeight + 1);

    // Time Protocol v2: pindexPrev->nTime
    return GetBlockTime();
}

enum { nMedianTimeSpan = 11 };

int64_t CBlockIndex::GetMedianTimePast() const
{
    int64_t pmedian[nMedianTimeSpan];
    int64_t* pbegin = &pmedian[nMedianTimeSpan];
    int64_t* pend = &pmedian[nMedianTimeSpan];

    const CBlockIndex* pindex = this;
    for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
        *(--pbegin) = pindex->GetBlockTime();

    std::sort(pbegin, pend);
    return pbegin[(pend - pbegin) / 2];
}

unsigned int CBlockIndex::GetStakeEntropyBit() const
{
    unsigned int nEntropyBit = ((GetBlockHash().GetCheapHash()) & 1);
    if (gArgs.GetBoolArg("-printstakemodifier", false))
        LogPrintf("GetStakeEntropyBit: nHeight=%u hashBlock=%s nEntropyBit=%u\n", nHeight, GetBlockHash().ToString().c_str(), nEntropyBit);

    return nEntropyBit;
}

bool CBlockIndex::SetStakeEntropyBit(unsigned int nEntropyBit)
{
    if (nEntropyBit > 1)
        return false;
    nFlags |= (nEntropyBit ? BLOCK_STAKE_ENTROPY : 0);
    return true;
}

// Sets V1 stake modifier (uint64_t)
void CBlockIndex::SetStakeModifier(const uint64_t nStakeModifier, bool fGeneratedStakeModifier)
{
    vStakeModifier.clear();
    const size_t modSize = sizeof(nStakeModifier);
    vStakeModifier.resize(modSize);
    std::memcpy(vStakeModifier.data(), &nStakeModifier, modSize);
    if (fGeneratedStakeModifier)
        nFlags |= BLOCK_STAKE_MODIFIER;

}

// Generates and sets new V1 stake modifier
void CBlockIndex::SetNewStakeModifier()
{
    // compute stake entropy bit for stake modifier
    if (!SetStakeEntropyBit(GetStakeEntropyBit()))
        LogPrintf("%s : SetStakeEntropyBit() failed\n", __func__);
    uint64_t nStakeModifier = 0;
    bool fGeneratedStakeModifier = false;
    if (!ComputeNextStakeModifier(pprev, nStakeModifier, fGeneratedStakeModifier))
        LogPrintf("%s : ComputeNextStakeModifier() failed \n",  __func__);
    return SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
}

// Sets V2 stake modifiers (uint256)
void CBlockIndex::SetStakeModifier(const uint256& nStakeModifier)
{
    vStakeModifier.clear();
    vStakeModifier.insert(vStakeModifier.begin(), nStakeModifier.begin(), nStakeModifier.end());
}

// Generates and sets new V2 stake modifier
void CBlockIndex::SetNewStakeModifier(const uint256& prevoutId)
{
    // Shouldn't be called on V1 modifier's blocks (or before setting pprev)
    if (!Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4)) return;
    if (!pprev) throw std::runtime_error(strprintf("%s : ERROR: null pprev", __func__));

    // Generate Hash(prevoutId | prevModifier) - switch with genesis modifier (0) on upgrade block
    CHashWriter ss(SER_GETHASH, 0);
    ss << prevoutId;
    ss << pprev->GetStakeModifierV2();
    SetStakeModifier(ss.GetHash());
}

// Returns V1 stake modifier (uint64_t)
uint64_t CBlockIndex::GetStakeModifierV1() const
{
    if (vStakeModifier.empty() || Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4))
        return 0;
    uint64_t nStakeModifier;
    std::memcpy(&nStakeModifier, vStakeModifier.data(), vStakeModifier.size());
    return nStakeModifier;
}

// Returns V2 stake modifier (uint256)
uint256 CBlockIndex::GetStakeModifierV2() const
{
    if (vStakeModifier.empty() || !Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4))
        return UINT256_ZERO;
    uint256 nStakeModifier;
    std::memcpy(nStakeModifier.begin(), vStakeModifier.data(), vStakeModifier.size());
    return nStakeModifier;
}

void CBlockIndex::SetChainSaplingValue()
{
    // Sapling, update chain value
    if (pprev) {
        if (pprev->nChainSaplingValue) {
            nChainSaplingValue = *pprev->nChainSaplingValue + nSaplingValue;
        } else {
            nChainSaplingValue = nullopt;
        }
    } else {
        nChainSaplingValue = nSaplingValue;
    }
}

//! Check whether this block index entry is valid up to the passed validity level.
bool CBlockIndex::IsValid(enum BlockStatus nUpTo) const
{
    assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
    if (nStatus & BLOCK_FAILED_MASK)
        return false;
    return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
}

//! Raise the validity level of this block index entry.
//! Returns true if the validity was changed.
bool CBlockIndex::RaiseValidity(enum BlockStatus nUpTo)
{
    assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
    if (nStatus & BLOCK_FAILED_MASK)
        return false;
    if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
        nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
        return true;
    }
    return false;
}

/** Find the last common ancestor two blocks have.
 *  Both pa and pb must be non-NULL. */
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb)
{
    if (pa->nHeight > pb->nHeight) {
        pa = pa->GetAncestor(pb->nHeight);
    } else if (pb->nHeight > pa->nHeight) {
        pb = pb->GetAncestor(pa->nHeight);
    }

    while (pa != pb && pa && pb) {
        pa = pa->pprev;
        pb = pb->pprev;
    }

    // Eventually all chain branches meet at the genesis block.
    assert(pa == pb);
    return pa;
}

<commit_msg>chain: Add assertion in case of missing records in index db<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2016-2020 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chain.h"
#include "legacy/stakemodifier.h"  // for ComputeNextStakeModifier

/**
 * CChain implementation
 */
void CChain::SetTip(CBlockIndex* pindex)
{
    if (pindex == NULL) {
        vChain.clear();
        return;
    }
    vChain.resize(pindex->nHeight + 1);
    while (pindex && vChain[pindex->nHeight] != pindex) {
        vChain[pindex->nHeight] = pindex;
        pindex = pindex->pprev;
    }
}

CBlockLocator CChain::GetLocator(const CBlockIndex* pindex) const
{
    int nStep = 1;
    std::vector<uint256> vHave;
    vHave.reserve(32);

    if (!pindex)
        pindex = Tip();
    while (pindex) {
        vHave.push_back(pindex->GetBlockHash());
        // Stop when we have added the genesis block.
        if (pindex->nHeight == 0)
            break;
        // Exponentially larger steps back, plus the genesis block.
        int nHeight = std::max(pindex->nHeight - nStep, 0);
        if (Contains(pindex)) {
            // Use O(1) CChain index if possible.
            pindex = (*this)[nHeight];
        } else {
            // Otherwise, use O(log n) skiplist.
            pindex = pindex->GetAncestor(nHeight);
        }
        if (vHave.size() > 10)
            nStep *= 2;
    }

    return CBlockLocator(vHave);
}

const CBlockIndex* CChain::FindFork(const CBlockIndex* pindex) const
{
    if (pindex == nullptr)
        return nullptr;
    if (pindex->nHeight > Height())
        pindex = pindex->GetAncestor(Height());
    while (pindex && !Contains(pindex))
        pindex = pindex->pprev;
    return pindex;
}

CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime) const
{
    std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
        [](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
    return (lower == vChain.end() ? nullptr : *lower);
}

/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
int static inline InvertLowestOne(int n) { return n & (n - 1); }

/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
int static inline GetSkipHeight(int height)
{
    if (height < 2)
        return 0;
    // Determine which height to jump back to. Any number strictly lower than height is acceptable,
    // but the following expression seems to perform well in simulations (max 110 steps to go back
    // up to 2**18 blocks).
    return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
}

CBlockIndex* CBlockIndex::GetAncestor(int height)
{
    if (height > nHeight || height < 0)
        return NULL;

    CBlockIndex* pindexWalk = this;
    int heightWalk = nHeight;
    while (heightWalk > height) {
        int heightSkip = GetSkipHeight(heightWalk);
        int heightSkipPrev = GetSkipHeight(heightWalk - 1);
        if (heightSkip == height ||
            (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && heightSkipPrev >= height))) {
            // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
            pindexWalk = pindexWalk->pskip;
            heightWalk = heightSkip;
        } else {
            assert(pindexWalk->pprev);
            pindexWalk = pindexWalk->pprev;
            heightWalk--;
        }
    }
    return pindexWalk;
}

const CBlockIndex* CBlockIndex::GetAncestor(int height) const
{
    return const_cast<CBlockIndex*>(this)->GetAncestor(height);
}

void CBlockIndex::BuildSkip()
{
    if (pprev)
        pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}

CBlockIndex::CBlockIndex(const CBlock& block):
        nVersion{block.nVersion},
        hashMerkleRoot{block.hashMerkleRoot},
        hashFinalSaplingRoot(block.hashFinalSaplingRoot),
        nTime{block.nTime},
        nBits{block.nBits},
        nNonce{block.nNonce}
{
    if(block.nVersion > 3 && block.nVersion < 7)
        nAccumulatorCheckpoint = block.nAccumulatorCheckpoint;
    if (block.IsProofOfStake())
        SetProofOfStake();
}

std::string CBlockIndex::ToString() const
{
    return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
        pprev, nHeight,
        hashMerkleRoot.ToString(),
        GetBlockHash().ToString());
}

CDiskBlockPos CBlockIndex::GetBlockPos() const
{
    CDiskBlockPos ret;
    if (nStatus & BLOCK_HAVE_DATA) {
        ret.nFile = nFile;
        ret.nPos = nDataPos;
    }
    return ret;
}

CDiskBlockPos CBlockIndex::GetUndoPos() const
{
    CDiskBlockPos ret;
    if (nStatus & BLOCK_HAVE_UNDO) {
        ret.nFile = nFile;
        ret.nPos = nUndoPos;
    }
    return ret;
}

CBlockHeader CBlockIndex::GetBlockHeader() const
{
    CBlockHeader block;
    block.nVersion = nVersion;
    if (pprev) block.hashPrevBlock = pprev->GetBlockHash();
    block.hashMerkleRoot = hashMerkleRoot;
    block.nTime = nTime;
    block.nBits = nBits;
    block.nNonce = nNonce;
    if (nVersion > 3 && nVersion < 7) block.nAccumulatorCheckpoint = nAccumulatorCheckpoint;
    if (nVersion >= 8) block.hashFinalSaplingRoot = hashFinalSaplingRoot;
    return block;
}

int64_t CBlockIndex::MaxFutureBlockTime() const
{
    return GetAdjustedTime() + Params().GetConsensus().FutureBlockTimeDrift(nHeight+1);
}

int64_t CBlockIndex::MinPastBlockTime() const
{
    const Consensus::Params& consensus = Params().GetConsensus();
    // Time Protocol v1: pindexPrev->MedianTimePast + 1
    if (!consensus.IsTimeProtocolV2(nHeight+1))
        return GetMedianTimePast();

    // on the transition from Time Protocol v1 to v2
    // pindexPrev->nTime might be in the future (up to the allowed drift)
    // so we allow the nBlockTimeProtocolV2 (PIVX v4.0) to be at most (180-14) seconds earlier than previous block
    if (nHeight + 1 == consensus.vUpgrades[Consensus::UPGRADE_V4_0].nActivationHeight)
        return GetBlockTime() - consensus.FutureBlockTimeDrift(nHeight) + consensus.FutureBlockTimeDrift(nHeight + 1);

    // Time Protocol v2: pindexPrev->nTime
    return GetBlockTime();
}

enum { nMedianTimeSpan = 11 };

int64_t CBlockIndex::GetMedianTimePast() const
{
    int64_t pmedian[nMedianTimeSpan];
    int64_t* pbegin = &pmedian[nMedianTimeSpan];
    int64_t* pend = &pmedian[nMedianTimeSpan];

    const CBlockIndex* pindex = this;
    for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
        *(--pbegin) = pindex->GetBlockTime();

    std::sort(pbegin, pend);
    return pbegin[(pend - pbegin) / 2];
}

unsigned int CBlockIndex::GetStakeEntropyBit() const
{
    unsigned int nEntropyBit = ((GetBlockHash().GetCheapHash()) & 1);
    if (gArgs.GetBoolArg("-printstakemodifier", false))
        LogPrintf("GetStakeEntropyBit: nHeight=%u hashBlock=%s nEntropyBit=%u\n", nHeight, GetBlockHash().ToString().c_str(), nEntropyBit);

    return nEntropyBit;
}

bool CBlockIndex::SetStakeEntropyBit(unsigned int nEntropyBit)
{
    if (nEntropyBit > 1)
        return false;
    nFlags |= (nEntropyBit ? BLOCK_STAKE_ENTROPY : 0);
    return true;
}

// Sets V1 stake modifier (uint64_t)
void CBlockIndex::SetStakeModifier(const uint64_t nStakeModifier, bool fGeneratedStakeModifier)
{
    vStakeModifier.clear();
    const size_t modSize = sizeof(nStakeModifier);
    vStakeModifier.resize(modSize);
    std::memcpy(vStakeModifier.data(), &nStakeModifier, modSize);
    if (fGeneratedStakeModifier)
        nFlags |= BLOCK_STAKE_MODIFIER;

}

// Generates and sets new V1 stake modifier
void CBlockIndex::SetNewStakeModifier()
{
    // compute stake entropy bit for stake modifier
    if (!SetStakeEntropyBit(GetStakeEntropyBit()))
        LogPrintf("%s : SetStakeEntropyBit() failed\n", __func__);
    uint64_t nStakeModifier = 0;
    bool fGeneratedStakeModifier = false;
    if (!ComputeNextStakeModifier(pprev, nStakeModifier, fGeneratedStakeModifier))
        LogPrintf("%s : ComputeNextStakeModifier() failed \n",  __func__);
    return SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
}

// Sets V2 stake modifiers (uint256)
void CBlockIndex::SetStakeModifier(const uint256& nStakeModifier)
{
    vStakeModifier.clear();
    vStakeModifier.insert(vStakeModifier.begin(), nStakeModifier.begin(), nStakeModifier.end());
}

// Generates and sets new V2 stake modifier
void CBlockIndex::SetNewStakeModifier(const uint256& prevoutId)
{
    // Shouldn't be called on V1 modifier's blocks (or before setting pprev)
    if (!Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4)) return;
    if (!pprev) throw std::runtime_error(strprintf("%s : ERROR: null pprev", __func__));

    // Generate Hash(prevoutId | prevModifier) - switch with genesis modifier (0) on upgrade block
    CHashWriter ss(SER_GETHASH, 0);
    ss << prevoutId;
    ss << pprev->GetStakeModifierV2();
    SetStakeModifier(ss.GetHash());
}

// Returns V1 stake modifier (uint64_t)
uint64_t CBlockIndex::GetStakeModifierV1() const
{
    if (vStakeModifier.empty() || Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4))
        return 0;
    uint64_t nStakeModifier;
    std::memcpy(&nStakeModifier, vStakeModifier.data(), vStakeModifier.size());
    return nStakeModifier;
}

// Returns V2 stake modifier (uint256)
uint256 CBlockIndex::GetStakeModifierV2() const
{
    if (vStakeModifier.empty() || !Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4))
        return UINT256_ZERO;
    uint256 nStakeModifier;
    std::memcpy(nStakeModifier.begin(), vStakeModifier.data(), vStakeModifier.size());
    return nStakeModifier;
}

void CBlockIndex::SetChainSaplingValue()
{
    // Sapling, update chain value
    if (pprev) {
        if (pprev->nChainSaplingValue) {
            nChainSaplingValue = *pprev->nChainSaplingValue + nSaplingValue;
        } else {
            nChainSaplingValue = nullopt;
        }
    } else {
        nChainSaplingValue = nSaplingValue;
    }
}

//! Check whether this block index entry is valid up to the passed validity level.
bool CBlockIndex::IsValid(enum BlockStatus nUpTo) const
{
    assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
    if (nStatus & BLOCK_FAILED_MASK)
        return false;
    return ((nStatus & BLOCK_VALID_MASK) >= nUpTo);
}

//! Raise the validity level of this block index entry.
//! Returns true if the validity was changed.
bool CBlockIndex::RaiseValidity(enum BlockStatus nUpTo)
{
    assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed.
    if (nStatus & BLOCK_FAILED_MASK)
        return false;
    if ((nStatus & BLOCK_VALID_MASK) < nUpTo) {
        nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo;
        return true;
    }
    return false;
}

/** Find the last common ancestor two blocks have.
 *  Both pa and pb must be non-NULL. */
const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* pb)
{
    if (pa->nHeight > pb->nHeight) {
        pa = pa->GetAncestor(pb->nHeight);
    } else if (pb->nHeight > pa->nHeight) {
        pb = pb->GetAncestor(pa->nHeight);
    }

    while (pa != pb && pa && pb) {
        pa = pa->pprev;
        pb = pb->pprev;
    }

    // Eventually all chain branches meet at the genesis block.
    assert(pa == pb);
    return pa;
}

<|endoftext|>


<commit_before>/*
 * appacc_test.cpp
 *
 *  Created on: 2015329
 *      Author: ranger.shi
 */

#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "txdb.h"
#include "database.h"
#include <iostream>
#include  "boost/filesystem/operations.hpp"
#include  "boost/filesystem/path.hpp"
#include  "../vm/appaccount.h"
#include "../vm/vmrunevn.h"
#include "tx.h"
#include "util.h"

using namespace std;

int64_t opValue[8][8] = {
						{100*COIN, 10*COIN, 10*COIN, 30*COIN, 40*COIN, 30*COIN ,30*COIN, 20*COIN},    //false
						{1000*COIN, 200*COIN, 20*COIN, 30*COIN, 40*COIN, 20*COIN, 10*COIN, 20*COIN},  //false
						{500*COIN, 200*COIN, 20*COIN, 100*COIN, 200*COIN, 100*COIN, 300*COIN, 100*COIN}, //false
						{100*COIN, 10*COIN, 20*COIN, 50*COIN, 50*COIN, 10*COIN, 20*COIN, 30*COIN}, //false
						{200*COIN, 20*COIN, 30*COIN, 40*COIN, 30*COIN, 30*COIN, 40*COIN, 40*COIN},  //false
						{1000*COIN, 200*COIN, 20*COIN, 500*COIN, 800*COIN, 400*COIN, 200*COIN, 100*COIN}, //true
						{500*COIN, 200*COIN, 200*COIN, 300*COIN, 200*COIN, 50*COIN, 100*COIN, 50*COIN}, //true
						{600*COIN, 200*COIN, 20*COIN, 30*COIN, 50*COIN, 60*COIN, 70*COIN, 20*COIN}  //false
						};

// appacc_tests/key_test1

bool CheckAppAcct(int64_t opValue[]) {
	CRegID srcRegId(100,1);
	CRegID desRegId(100,2);
	CRegID desUser1RegId(100,3);
	CRegID desUser2RegId(100,4);
	CAccount contractAcct;
	contractAcct.llValues = 100 * COIN;  //ｫTX100 COINȳֵԼ˻Уϵͳ˻ɫ
	contractAcct.regID = desRegId;

	CUserID srcUserId= srcRegId;
	CUserID desUserId = desRegId;
	vector_unsigned_char pContract;
	CTransaction tx(srcUserId, desRegId, 10000, opValue[0], 1, pContract); //100 * COIN

	CVmRunEvn vmRunEvn;
	vector<CVmOperate> vAcctOper;

	vector_unsigned_char vDesUser1RegId = desUser1RegId.GetVec6();
	int64_t temp = opValue[1];  //10 * COIN
	CVmOperate acctAddOper;
	acctAddOper.nacctype = regid;
	acctAddOper.opeatortype = ADD_FREE;
	memcpy(acctAddOper.accountid, &vDesUser1RegId[0], 6);
	memcpy(acctAddOper.money, &temp, sizeof(temp));
	vAcctOper.push_back(acctAddOper);

	vector_unsigned_char vDesUser2RegId = desUser2RegId.GetVec6();
	temp = opValue[2];   //20 * COIN
	acctAddOper.nacctype = regid;
	acctAddOper.opeatortype = ADD_FREE;
	memcpy(acctAddOper.accountid, &vDesUser2RegId[0], 6);
	memcpy(acctAddOper.money, &temp, sizeof(temp));
	vAcctOper.push_back(acctAddOper);

	vector_unsigned_char vDesRegId = desRegId.GetVec6();
	temp = opValue[3];  //30 * COIN
	acctAddOper.nacctype = regid;
	acctAddOper.opeatortype = MINUS_FREE;
	memcpy(acctAddOper.accountid, &vDesRegId[0], 6);
	memcpy(acctAddOper.money, &temp, sizeof(temp));
	vAcctOper.push_back(acctAddOper);
	vmRunEvn.InsertOutputData(vAcctOper);

	CAppFundOperate appFundOper;
	appFundOper.opeatortype = ADD_FREE_OP;
	appFundOper.mMoney = opValue[4];       //20 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser1RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser1RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser1RegId, appFundOper);

	appFundOper.opeatortype = SUB_FREE_OP;
	appFundOper.mMoney = opValue[5];      //90 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser2RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser2RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser2RegId, appFundOper);

	appFundOper.opeatortype = ADD_TAG_OP;
	appFundOper.mMoney = opValue[6];     // 90 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser2RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser2RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser2RegId, appFundOper);

	appFundOper.opeatortype = SUB_TAG_OP;
	appFundOper.mMoney = opValue[7];  // 80 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser1RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser1RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser1RegId, appFundOper);

	return vmRunEvn.CheckAppAcctOperate(&tx);
}

BOOST_AUTO_TEST_SUITE(appacc_tests)

BOOST_AUTO_TEST_CASE(key_test1)
 {
	auto StrTVector = [&](string tag)
	{
		return vector<unsigned char>(tag.begin(),tag.end());
	};

	srand((int) time(NULL));

	vector<unsigned char> AppuserId = StrTVector("test1");
	vector<unsigned char> fundtag = StrTVector("foundtag");
	vector<unsigned char> fundtag2 = StrTVector("foundtag2");

	CAppFundOperate opTe(AppuserId,fundtag, ADD_TAG_OP, 500, 800000);
	BOOST_CHECK(opTe.GetFundTagV() == fundtag);
	BOOST_CHECK(opTe.GetUint64Value()== 800000);
	BOOST_CHECK(opTe.getopeatortype()== ADD_TAG_OP);

	vector<CAppFundOperate> OpArry;
	uint64_t allmoney = 0;
	int timeout = (rand() % 15000) + 51;
	int loop = 500;
	int maxtimeout = timeout + loop+1;
	for (int i = 0; i < loop; i++) {
		int64_t temp = ((rand() * rand()) % 15000000) + 20;
		allmoney += temp;
		CAppFundOperate op(AppuserId,fundtag, ADD_TAG_OP, timeout + i, temp);
		OpArry.insert(OpArry.end(), op);
	}

	CAppUserAccout AccCount(AppuserId);
	BOOST_CHECK(AccCount.getaccUserId() == AppuserId);      //ʼID
	BOOST_CHECK(AccCount.Operate(OpArry));               //ִеĲ
	BOOST_CHECK(AccCount.getllValues() == 0);            //ΪȫǼӶǮɽ0

	{
		CAppCFund tep;
		BOOST_CHECK(AccCount.GetAppCFund(tep, fundtag, timeout)); //ȡӦĶ
		BOOST_CHECK(tep.getvalue() == OpArry[0].GetUint64Value());                    //ĽҪû
		CAppCFund tep2;
		BOOST_CHECK(AccCount.GetAppCFund(tep2, fundtag, maxtimeout + 5) == false); //ȡӦĶ ʱʱ䲻ͬ ȡ

		AccCount.AutoMergeFreezeToFree(timeout - 1);               	   //Զϲ ʱ߶ûе   50 Ϊǩ time out de 51
		BOOST_CHECK(AccCount.GetAppCFund(tep, fundtag, timeout));			 //ûкϲûб䶯
		BOOST_CHECK(tep.getvalue() == OpArry[0].GetUint64Value());         	//ûкϲûб䶯
	}

	{
		vector<CAppFundOperate> OpArry2;
		CAppFundOperate subfreexeop(AppuserId,fundtag, SUB_TAG_OP, timeout, 8);
		OpArry2.insert(OpArry2.end(), subfreexeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               //ִеĲ
	}

	{
		CAppCFund subtemptep;
		BOOST_CHECK(AccCount.GetAppCFund(subtemptep, fundtag, timeout));        //ȡӦĶ
		BOOST_CHECK(subtemptep.getvalue() == (OpArry[0].GetUint64Value() - 8));    //ȥ8  Ƿ
	}

	{
		vector<CAppFundOperate> OpArry2;
		CAppFundOperate revertfreexeop(AppuserId,fundtag, ADD_TAG_OP, timeout, 8);
		OpArry2.clear();
		OpArry2.insert(OpArry2.end(), revertfreexeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               //ִеĲ
	}

	{
		CAppCFund reverttemptep;
		BOOST_CHECK(AccCount.GetAppCFund(reverttemptep, fundtag, timeout));			 //ûкϲûб䶯
		BOOST_CHECK(reverttemptep.getvalue() == OpArry[0].GetUint64Value());         	//ûкϲûб䶯
	}

	{         	//ϲһ
		CAppCFund tep;
		AccCount.AutoMergeFreezeToFree(timeout);                  				//Զϲ 0
		BOOST_CHECK(AccCount.GetAppCFund(tep, fundtag, timeout) == false); 		//Ҳ
		BOOST_CHECK(AccCount.getllValues() == OpArry[0].GetUint64Value());;          				//ϲɽû
	}

	{          				//ȥȫ
		CAppFundOperate subfreeop(AppuserId,fundtag, SUB_FREE_OP, timeout, OpArry[0].GetUint64Value());
		vector<CAppFundOperate> OpArry2;
		OpArry2.insert(OpArry2.end(), subfreeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               				//ִеĲ
		BOOST_CHECK(AccCount.getllValues() == 0);;                           //ǮԺ˶
	}

	{
		vector<CAppFundOperate> OpArry2;
		CAppFundOperate addfreeop(AppuserId,fundtag, ADD_FREE_OP, timeout, OpArry[0].GetUint64Value());    //ٴΰݼӽȥ
		OpArry2.clear();
		OpArry2.insert(OpArry2.end(), addfreeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               				//ִеĲ
		BOOST_CHECK(AccCount.getllValues() == OpArry[0].GetUint64Value());                //Ϻ ͻ
	}

	AccCount.AutoMergeFreezeToFree(maxtimeout);     				//ȫϲ
//	BOOST_CHECK_MESSAGE(AccCount.getllValues() == allmoney, "" << allmoney << ' ' << AccCount.getllValues());                //ƽ

}

BOOST_AUTO_TEST_CASE(checkappacct_test) {
	for(int j=0; j <8; ++j) {
		for(int i=0; i<8; ++i) {
			cout << opValue[j][i] <<" ";
		}
		cout << endl;
		int64_t txValue = opValue[j][0];
		int64_t acctMinusValue = opValue[j][3];
		int64_t acctSum = txValue - acctMinusValue;
		int64_t appAcctSum = opValue[j][4] - opValue[j][5] + opValue[j][6] - opValue[j][7];
		bool isCheck = (acctSum == appAcctSum);
		cout << "ischeck:" << isCheck << endl;
		BOOST_CHECK(CheckAppAcct(opValue[j]) == isCheck);
	}

}
BOOST_AUTO_TEST_SUITE_END()

<commit_msg>修改AutoMergeFreezeToFree函数调用<commit_after>/*
 * appacc_test.cpp
 *
 *  Created on: 2015329
 *      Author: ranger.shi
 */

#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
#include "txdb.h"
#include "database.h"
#include <iostream>
#include  "boost/filesystem/operations.hpp"
#include  "boost/filesystem/path.hpp"
#include  "../vm/appaccount.h"
#include "../vm/vmrunevn.h"
#include "tx.h"
#include "util.h"

using namespace std;

int64_t opValue[8][8] = {
						{100*COIN, 10*COIN, 10*COIN, 30*COIN, 40*COIN, 30*COIN ,30*COIN, 20*COIN},    //false
						{1000*COIN, 200*COIN, 20*COIN, 30*COIN, 40*COIN, 20*COIN, 10*COIN, 20*COIN},  //false
						{500*COIN, 200*COIN, 20*COIN, 100*COIN, 200*COIN, 100*COIN, 300*COIN, 100*COIN}, //false
						{100*COIN, 10*COIN, 20*COIN, 50*COIN, 50*COIN, 10*COIN, 20*COIN, 30*COIN}, //false
						{200*COIN, 20*COIN, 30*COIN, 40*COIN, 30*COIN, 30*COIN, 40*COIN, 40*COIN},  //false
						{1000*COIN, 200*COIN, 20*COIN, 500*COIN, 800*COIN, 400*COIN, 200*COIN, 100*COIN}, //true
						{500*COIN, 200*COIN, 200*COIN, 300*COIN, 200*COIN, 50*COIN, 100*COIN, 50*COIN}, //true
						{600*COIN, 200*COIN, 20*COIN, 30*COIN, 50*COIN, 60*COIN, 70*COIN, 20*COIN}  //false
						};

// appacc_tests/key_test1

bool CheckAppAcct(int64_t opValue[]) {
	CRegID srcRegId(100,1);
	CRegID desRegId(100,2);
	CRegID desUser1RegId(100,3);
	CRegID desUser2RegId(100,4);
	CAccount contractAcct;
	contractAcct.llValues = 100 * COIN;  //ｫTX100 COINȳֵԼ˻Уϵͳ˻ɫ
	contractAcct.regID = desRegId;

	CUserID srcUserId= srcRegId;
	CUserID desUserId = desRegId;
	vector_unsigned_char pContract;
	CTransaction tx(srcUserId, desRegId, 10000, opValue[0], 1, pContract); //100 * COIN

	CVmRunEvn vmRunEvn;
	vector<CVmOperate> vAcctOper;

	vector_unsigned_char vDesUser1RegId = desUser1RegId.GetVec6();
	int64_t temp = opValue[1];  //10 * COIN
	CVmOperate acctAddOper;
	acctAddOper.nacctype = regid;
	acctAddOper.opeatortype = ADD_FREE;
	memcpy(acctAddOper.accountid, &vDesUser1RegId[0], 6);
	memcpy(acctAddOper.money, &temp, sizeof(temp));
	vAcctOper.push_back(acctAddOper);

	vector_unsigned_char vDesUser2RegId = desUser2RegId.GetVec6();
	temp = opValue[2];   //20 * COIN
	acctAddOper.nacctype = regid;
	acctAddOper.opeatortype = ADD_FREE;
	memcpy(acctAddOper.accountid, &vDesUser2RegId[0], 6);
	memcpy(acctAddOper.money, &temp, sizeof(temp));
	vAcctOper.push_back(acctAddOper);

	vector_unsigned_char vDesRegId = desRegId.GetVec6();
	temp = opValue[3];  //30 * COIN
	acctAddOper.nacctype = regid;
	acctAddOper.opeatortype = MINUS_FREE;
	memcpy(acctAddOper.accountid, &vDesRegId[0], 6);
	memcpy(acctAddOper.money, &temp, sizeof(temp));
	vAcctOper.push_back(acctAddOper);
	vmRunEvn.InsertOutputData(vAcctOper);

	CAppFundOperate appFundOper;
	appFundOper.opeatortype = ADD_FREE_OP;
	appFundOper.mMoney = opValue[4];       //20 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser1RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser1RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser1RegId, appFundOper);

	appFundOper.opeatortype = SUB_FREE_OP;
	appFundOper.mMoney = opValue[5];      //90 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser2RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser2RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser2RegId, appFundOper);

	appFundOper.opeatortype = ADD_TAG_OP;
	appFundOper.mMoney = opValue[6];     // 90 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser2RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser2RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser2RegId, appFundOper);

	appFundOper.opeatortype = SUB_TAG_OP;
	appFundOper.mMoney = opValue[7];  // 80 * COIN
	appFundOper.appuserIDlen = 6;
	memcpy(appFundOper.vAppuser,  &vDesUser1RegId[0], 6);
	appFundOper.FundTaglen = 6;
	memcpy(appFundOper.vFundTag, &vDesUser1RegId[0], 6);
	vmRunEvn.InsertOutAPPOperte(vDesUser1RegId, appFundOper);

	return vmRunEvn.CheckAppAcctOperate(&tx);
}

BOOST_AUTO_TEST_SUITE(appacc_tests)

BOOST_AUTO_TEST_CASE(key_test1)
 {
	auto StrTVector = [&](string tag)
	{
		return vector<unsigned char>(tag.begin(),tag.end());
	};

	srand((int) time(NULL));

	vector<unsigned char> AppuserId = StrTVector("test1");
	vector<unsigned char> fundtag = StrTVector("foundtag");
	vector<unsigned char> fundtag2 = StrTVector("foundtag2");

	CAppFundOperate opTe(AppuserId,fundtag, ADD_TAG_OP, 500, 800000);
	BOOST_CHECK(opTe.GetFundTagV() == fundtag);
	BOOST_CHECK(opTe.GetUint64Value()== 800000);
	BOOST_CHECK(opTe.getopeatortype()== ADD_TAG_OP);

	vector<CAppFundOperate> OpArry;
	uint64_t allmoney = 0;
	int timeout = (rand() % 15000) + 51;
	int loop = 500;
	int maxtimeout = timeout + loop+1;
	for (int i = 0; i < loop; i++) {
		int64_t temp = ((rand() * rand()) % 15000000) + 20;
		allmoney += temp;
		CAppFundOperate op(AppuserId,fundtag, ADD_TAG_OP, timeout + i, temp);
		OpArry.insert(OpArry.end(), op);
	}

	CAppUserAccout AccCount(AppuserId);
	BOOST_CHECK(AccCount.getaccUserId() == AppuserId);      //ʼID
	BOOST_CHECK(AccCount.Operate(OpArry));               //ִеĲ
	BOOST_CHECK(AccCount.getllValues() == 0);            //ΪȫǼӶǮɽ0

	{
		CAppCFund tep;
		BOOST_CHECK(AccCount.GetAppCFund(tep, fundtag, timeout)); //ȡӦĶ
		BOOST_CHECK(tep.getvalue() == OpArry[0].GetUint64Value());                    //ĽҪû
		CAppCFund tep2;
		BOOST_CHECK(AccCount.GetAppCFund(tep2, fundtag, maxtimeout + 5) == false); //ȡӦĶ ʱʱ䲻ͬ ȡ

		AccCount.AutoMergeFreezeToFree(0, timeout - 1);               	   //Զϲ ʱ߶ûе   50 Ϊǩ time out de 51
		BOOST_CHECK(AccCount.GetAppCFund(tep, fundtag, timeout));			 //ûкϲûб䶯
		BOOST_CHECK(tep.getvalue() == OpArry[0].GetUint64Value());         	//ûкϲûб䶯
	}

	{
		vector<CAppFundOperate> OpArry2;
		CAppFundOperate subfreexeop(AppuserId,fundtag, SUB_TAG_OP, timeout, 8);
		OpArry2.insert(OpArry2.end(), subfreexeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               //ִеĲ
	}

	{
		CAppCFund subtemptep;
		BOOST_CHECK(AccCount.GetAppCFund(subtemptep, fundtag, timeout));        //ȡӦĶ
		BOOST_CHECK(subtemptep.getvalue() == (OpArry[0].GetUint64Value() - 8));    //ȥ8  Ƿ
	}

	{
		vector<CAppFundOperate> OpArry2;
		CAppFundOperate revertfreexeop(AppuserId,fundtag, ADD_TAG_OP, timeout, 8);
		OpArry2.clear();
		OpArry2.insert(OpArry2.end(), revertfreexeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               //ִеĲ
	}

	{
		CAppCFund reverttemptep;
		BOOST_CHECK(AccCount.GetAppCFund(reverttemptep, fundtag, timeout));			 //ûкϲûб䶯
		BOOST_CHECK(reverttemptep.getvalue() == OpArry[0].GetUint64Value());         	//ûкϲûб䶯
	}

	{         	//ϲһ
		CAppCFund tep;
		AccCount.AutoMergeFreezeToFree(0, timeout);                  				//Զϲ 0
		BOOST_CHECK(AccCount.GetAppCFund(tep, fundtag, timeout) == false); 		//Ҳ
		BOOST_CHECK(AccCount.getllValues() == OpArry[0].GetUint64Value());;          				//ϲɽû
	}

	{          				//ȥȫ
		CAppFundOperate subfreeop(AppuserId,fundtag, SUB_FREE_OP, timeout, OpArry[0].GetUint64Value());
		vector<CAppFundOperate> OpArry2;
		OpArry2.insert(OpArry2.end(), subfreeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               				//ִеĲ
		BOOST_CHECK(AccCount.getllValues() == 0);;                           //ǮԺ˶
	}

	{
		vector<CAppFundOperate> OpArry2;
		CAppFundOperate addfreeop(AppuserId,fundtag, ADD_FREE_OP, timeout, OpArry[0].GetUint64Value());    //ٴΰݼӽȥ
		OpArry2.clear();
		OpArry2.insert(OpArry2.end(), addfreeop);
		BOOST_CHECK(AccCount.Operate(OpArry2));               				//ִеĲ
		BOOST_CHECK(AccCount.getllValues() == OpArry[0].GetUint64Value());                //Ϻ ͻ
	}

	AccCount.AutoMergeFreezeToFree(0, maxtimeout);     				//ȫϲ
//	BOOST_CHECK_MESSAGE(AccCount.getllValues() == allmoney, "" << allmoney << ' ' << AccCount.getllValues());                //ƽ

}

BOOST_AUTO_TEST_CASE(checkappacct_test) {
	for(int j=0; j <8; ++j) {
		for(int i=0; i<8; ++i) {
			cout << opValue[j][i] <<" ";
		}
		cout << endl;
		int64_t txValue = opValue[j][0];
		int64_t acctMinusValue = opValue[j][3];
		int64_t acctSum = txValue - acctMinusValue;
		int64_t appAcctSum = opValue[j][4] - opValue[j][5] + opValue[j][6] - opValue[j][7];
		bool isCheck = (acctSum == appAcctSum);
		cout << "ischeck:" << isCheck << endl;
		BOOST_CHECK(CheckAppAcct(opValue[j]) == isCheck);
	}

}
BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>#include "taichi/ir/ir.h"
#include "taichi/ir/transforms.h"
#include "taichi/ir/visitors.h"

TLANG_NAMESPACE_BEGIN

// This pass manipulates the id of statements so that they are successive values
// starting from 0
class ReId : public BasicStmtVisitor {
 public:
  int id_counter;

  ReId() : id_counter(0) {
    allow_undefined_visitor = true;
    invoke_default_visitor = true;
  }

  void re_id(Stmt *stmt) {
    stmt->id = id_counter++;
  }

  void visit(Stmt *stmt) override {
    re_id(stmt);
  }

  void preprocess_container_stmt(Stmt *stmt) override {
    re_id(stmt);
  }

  static void run(IRNode *node) {
    ReId instance;
    node->accept(&instance);
  }
};

namespace irpass {
void re_id(IRNode *root) {
  ReId::run(root);
}
}  // namespace irpass

TLANG_NAMESPACE_END
<commit_msg>[misc] Fix compilation warning (#1320)<commit_after>#include "taichi/ir/ir.h"
#include "taichi/ir/transforms.h"
#include "taichi/ir/visitors.h"

TLANG_NAMESPACE_BEGIN

// This pass manipulates the id of statements so that they are successive values
// starting from 0
class ReId : public BasicStmtVisitor {
 public:
  using BasicStmtVisitor::visit;

  int id_counter;

  ReId() : id_counter(0) {
    allow_undefined_visitor = true;
    invoke_default_visitor = true;
  }

  void re_id(Stmt *stmt) {
    stmt->id = id_counter++;
  }

  void visit(Stmt *stmt) override {
    re_id(stmt);
  }

  void preprocess_container_stmt(Stmt *stmt) override {
    re_id(stmt);
  }

  static void run(IRNode *node) {
    ReId instance;
    node->accept(&instance);
  }
};

namespace irpass {
void re_id(IRNode *root) {
  ReId::run(root);
}
}  // namespace irpass

TLANG_NAMESPACE_END
<|endoftext|>


<commit_before>#include <stan/math/prim/mat/meta/get.hpp>
#include <stan/math/prim/arr/meta/get.hpp>
#include <stan/math/prim/mat/meta/length.hpp>
#include <stan/math/prim/mat/meta/is_vector.hpp>
#include <stan/math/prim/mat/meta/is_vector_like.hpp>
#include <stan/math/prim/mat/fun/value_of_rec.hpp>
#include <stan/math/prim/mat/err/check_pos_definite.hpp>
#include <gtest/gtest.h>
#include <test/unit/util.hpp>

const char* function = "function";
class ErrorHandlingMatrix : public ::testing::Test {
public:
  void SetUp() {
  }

  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y;
};

TEST_F(ErrorHandlingMatrix, checkPosDefinite) {
  using stan::math::check_pos_definite;

  y.resize(1,1);
  y << 1;
  EXPECT_TRUE(check_pos_definite(function, "y", y));

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_1(y);
  EXPECT_TRUE(check_pos_definite(function, "y", llt_1));

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_1 = y.ldlt();
  EXPECT_TRUE(check_pos_definite(function, "y", ldlt_1));

  y.resize(3,3);
  y <<
    1, 0, 0,
    0, 1, 0,
    0, 0, 1;
  EXPECT_TRUE(check_pos_definite(function, "y", y));

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_2(y);
  EXPECT_TRUE(check_pos_definite(function, "y", llt_2));

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_2 = y.ldlt();
  EXPECT_TRUE(check_pos_definite(function, "y", ldlt_2));
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_not_square) {
  using stan::math::check_pos_definite;
  std::stringstream expected_msg;

  y.resize(3, 4);
  expected_msg << "Expecting a square matrix; rows of y (3) and columns of y (4) must match in size";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::invalid_argument,
                   expected_msg.str());
  y.resize(2,3);
  y <<
    1, 1,
    1, 1,
    1, 1;
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt(y.rows());
 // EXPECT_DEATH(llt.compute(y),"");
  llt.compute(y)
  EXPECT_DEATH(y.ldlt(), "");
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_0_size) {
  using stan::math::check_pos_definite;
  std::string expected_msg;

  expected_msg = "y must have a positive size, but is 0; dimension size expression = rows";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::invalid_argument,
                   expected_msg);
  Eigen::MatrixXd x;
  x.resize(0,0);
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt(x.rows());
  llt.compute(x);
  EXPECT_NO_THROW(check_pos_definite(function, "x", llt));
  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt(x.rows());
  EXPECT_DEATH(ldlt.compute(x),"");
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_non_symmetric) {
  using stan::math::check_pos_definite;
  std::string expected_msg;

  y.resize(3,3);
  y <<
    1, 0, 0,
    0, 1, 0.5,
    0, 0, 1;

  expected_msg = "y is not symmetric. y[2,3] = 0.5, but y[3,2] = 0";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg);

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt(y);
  EXPECT_NO_THROW(check_pos_definite(function, "y", llt));

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt = y.ldlt();
  EXPECT_NO_THROW(check_pos_definite(function, "y", ldlt));
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_non_pos_definite) {
  using stan::math::check_pos_definite;
  std::stringstream expected_msg1_mat;
  std::stringstream expected_msg1_llt;
  std::stringstream expected_msg1_ldlt;
  std::stringstream expected_msg2_mat;
  std::stringstream expected_msg3_mat;
  std::stringstream expected_msg4;

  y.resize(3,3);
  y <<
    -1, 0, 0,
    0, -1, 0,
    0, 0, -1;

  expected_msg1_mat << "function: y is not positive definite:\n" <<
    "-1  0  0\n 0 -1  0\n 0  0 -1";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg1_mat.str());

  expected_msg1_llt << "function: Cholesky decomposition of y failed";
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err1(y);
  EXPECT_THROW_MSG(check_pos_definite(function, "y", llt_err1),
                   std::domain_error,
                   expected_msg1_llt.str());
  expected_msg1_ldlt << "function: LDLT decomposition of y failed";
  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err1 = y.ldlt();
  EXPECT_THROW_MSG(check_pos_definite(function, "y", ldlt_err1),
                   std::domain_error,
                   expected_msg1_ldlt.str());
  y.resize(2,2);
  y <<
    1, 2,
    2, 1;
  expected_msg2_mat << "function: y is not positive definite:\n" <<
    "1 2\n2 1";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg2_mat.str());
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err2(y);
  EXPECT_THROW_MSG(check_pos_definite(function, "y", llt_err2),
                   std::domain_error,
                   expected_msg1_llt.str());

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err2 = y.ldlt();
  EXPECT_THROW_MSG(check_pos_definite(function, "y", ldlt_err2),
                   std::domain_error,
                   expected_msg1_ldlt.str());
  y <<
    1, 1,
    1, 1;
  expected_msg3_mat << "function: y is not positive definite:\n" <<
    "1 1\n1 1";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg3_mat.str());

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err3(y);
  EXPECT_THROW_MSG(check_pos_definite(function, "y", llt_err3),
                   std::domain_error,
                   expected_msg1_llt.str());
  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err3 = y.ldlt();
  EXPECT_THROW_MSG(check_pos_definite(function, "y", ldlt_err3),
                   std::domain_error,
                   expected_msg1_ldlt.str());
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_nan) {
  double nan = std::numeric_limits<double>::quiet_NaN();
  using stan::math::check_pos_definite;

  y.resize(1,1);
  y << nan;

  std::stringstream expected_msg;
  expected_msg << "function: y is not positive definite: "
               << nan;
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg.str());

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err1(y);
  EXPECT_THROW(check_pos_definite(function, "y", llt_err1),std::domain_error);

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err1 = y.ldlt();
  EXPECT_THROW(check_pos_definite(function, "y", ldlt_err1),std::domain_error);

  y.resize(3,3);
  y << 2, -1, 0,
    -1, 2, -1,
    0, -1, 2;
  EXPECT_TRUE(check_pos_definite(function,
                                 "y", y));
  for (int i = 0; i < y.rows(); i++)
    for (int j = 0; j < y.cols(); j++) {
      y << 2, -1, 0, -1, 2, -1, 0, -1, 2;
      y(i,j) = nan;
      if (i >= j) {
        expected_msg.str("");
        if (i == j)
          expected_msg << "function: y["
                       << j*y.cols() + i + 1
                       << "] is " << nan
                       << ", but must not be nan!";
        else
          expected_msg << "function: y is not symmetric. "
                       << "y[" << j+1 << "," << i+1 << "] = " << y(j,i)
                       << ", but y[" << i+1 << "," << j+1 << "] = " << y(i,j);
        EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                         std::domain_error,
                         expected_msg.str());
      }
    }

  y << 2, -1, nan,
    -1, 2, -1,
    nan, -1, nan;
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err2(y);
  EXPECT_THROW(check_pos_definite(function, "y", llt_err2),std::domain_error);

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err2 = y.ldlt();
  EXPECT_THROW(check_pos_definite(function, "y", ldlt_err2),std::domain_error);

  y << 0, 0, 0, 0, 0, 0, 0, 0, 0;
  expected_msg.str("");
  expected_msg << "function: y is not positive definite:\n"
               << y;
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg.str());
}

<commit_msg>b f/i-48 fixed typo<commit_after>#include <stan/math/prim/mat/meta/get.hpp>
#include <stan/math/prim/arr/meta/get.hpp>
#include <stan/math/prim/mat/meta/length.hpp>
#include <stan/math/prim/mat/meta/is_vector.hpp>
#include <stan/math/prim/mat/meta/is_vector_like.hpp>
#include <stan/math/prim/mat/fun/value_of_rec.hpp>
#include <stan/math/prim/mat/err/check_pos_definite.hpp>
#include <gtest/gtest.h>
#include <test/unit/util.hpp>

const char* function = "function";
class ErrorHandlingMatrix : public ::testing::Test {
public:
  void SetUp() {
  }

  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> y;
};

TEST_F(ErrorHandlingMatrix, checkPosDefinite) {
  using stan::math::check_pos_definite;

  y.resize(1,1);
  y << 1;
  EXPECT_TRUE(check_pos_definite(function, "y", y));

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_1(y);
  EXPECT_TRUE(check_pos_definite(function, "y", llt_1));

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_1 = y.ldlt();
  EXPECT_TRUE(check_pos_definite(function, "y", ldlt_1));

  y.resize(3,3);
  y <<
    1, 0, 0,
    0, 1, 0,
    0, 0, 1;
  EXPECT_TRUE(check_pos_definite(function, "y", y));

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_2(y);
  EXPECT_TRUE(check_pos_definite(function, "y", llt_2));

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_2 = y.ldlt();
  EXPECT_TRUE(check_pos_definite(function, "y", ldlt_2));
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_not_square) {
  using stan::math::check_pos_definite;
  std::stringstream expected_msg;

  y.resize(3, 4);
  expected_msg << "Expecting a square matrix; rows of y (3) and columns of y (4) must match in size";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::invalid_argument,
                   expected_msg.str());
  y.resize(2,3);
  y <<
    1, 1,
    1, 1,
    1, 1;
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt(y.rows());
 // EXPECT_DEATH(llt.compute(y),"");
  llt.compute(y);
  EXPECT_DEATH(y.ldlt(), "");
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_0_size) {
  using stan::math::check_pos_definite;
  std::string expected_msg;

  expected_msg = "y must have a positive size, but is 0; dimension size expression = rows";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::invalid_argument,
                   expected_msg);
  Eigen::MatrixXd x;
  x.resize(0,0);
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt(x.rows());
  llt.compute(x);
  EXPECT_NO_THROW(check_pos_definite(function, "x", llt));
  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt(x.rows());
  EXPECT_DEATH(ldlt.compute(x),"");
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_non_symmetric) {
  using stan::math::check_pos_definite;
  std::string expected_msg;

  y.resize(3,3);
  y <<
    1, 0, 0,
    0, 1, 0.5,
    0, 0, 1;

  expected_msg = "y is not symmetric. y[2,3] = 0.5, but y[3,2] = 0";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg);

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt(y);
  EXPECT_NO_THROW(check_pos_definite(function, "y", llt));

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt = y.ldlt();
  EXPECT_NO_THROW(check_pos_definite(function, "y", ldlt));
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_non_pos_definite) {
  using stan::math::check_pos_definite;
  std::stringstream expected_msg1_mat;
  std::stringstream expected_msg1_llt;
  std::stringstream expected_msg1_ldlt;
  std::stringstream expected_msg2_mat;
  std::stringstream expected_msg3_mat;
  std::stringstream expected_msg4;

  y.resize(3,3);
  y <<
    -1, 0, 0,
    0, -1, 0,
    0, 0, -1;

  expected_msg1_mat << "function: y is not positive definite:\n" <<
    "-1  0  0\n 0 -1  0\n 0  0 -1";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg1_mat.str());

  expected_msg1_llt << "function: Cholesky decomposition of y failed";
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err1(y);
  EXPECT_THROW_MSG(check_pos_definite(function, "y", llt_err1),
                   std::domain_error,
                   expected_msg1_llt.str());
  expected_msg1_ldlt << "function: LDLT decomposition of y failed";
  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err1 = y.ldlt();
  EXPECT_THROW_MSG(check_pos_definite(function, "y", ldlt_err1),
                   std::domain_error,
                   expected_msg1_ldlt.str());
  y.resize(2,2);
  y <<
    1, 2,
    2, 1;
  expected_msg2_mat << "function: y is not positive definite:\n" <<
    "1 2\n2 1";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg2_mat.str());
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err2(y);
  EXPECT_THROW_MSG(check_pos_definite(function, "y", llt_err2),
                   std::domain_error,
                   expected_msg1_llt.str());

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err2 = y.ldlt();
  EXPECT_THROW_MSG(check_pos_definite(function, "y", ldlt_err2),
                   std::domain_error,
                   expected_msg1_ldlt.str());
  y <<
    1, 1,
    1, 1;
  expected_msg3_mat << "function: y is not positive definite:\n" <<
    "1 1\n1 1";
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg3_mat.str());

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err3(y);
  EXPECT_THROW_MSG(check_pos_definite(function, "y", llt_err3),
                   std::domain_error,
                   expected_msg1_llt.str());
  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err3 = y.ldlt();
  EXPECT_THROW_MSG(check_pos_definite(function, "y", ldlt_err3),
                   std::domain_error,
                   expected_msg1_ldlt.str());
}

TEST_F(ErrorHandlingMatrix, checkPosDefinite_nan) {
  double nan = std::numeric_limits<double>::quiet_NaN();
  using stan::math::check_pos_definite;

  y.resize(1,1);
  y << nan;

  std::stringstream expected_msg;
  expected_msg << "function: y is not positive definite: "
               << nan;
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg.str());

  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err1(y);
  EXPECT_THROW(check_pos_definite(function, "y", llt_err1),std::domain_error);

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err1 = y.ldlt();
  EXPECT_THROW(check_pos_definite(function, "y", ldlt_err1),std::domain_error);

  y.resize(3,3);
  y << 2, -1, 0,
    -1, 2, -1,
    0, -1, 2;
  EXPECT_TRUE(check_pos_definite(function,
                                 "y", y));
  for (int i = 0; i < y.rows(); i++)
    for (int j = 0; j < y.cols(); j++) {
      y << 2, -1, 0, -1, 2, -1, 0, -1, 2;
      y(i,j) = nan;
      if (i >= j) {
        expected_msg.str("");
        if (i == j)
          expected_msg << "function: y["
                       << j*y.cols() + i + 1
                       << "] is " << nan
                       << ", but must not be nan!";
        else
          expected_msg << "function: y is not symmetric. "
                       << "y[" << j+1 << "," << i+1 << "] = " << y(j,i)
                       << ", but y[" << i+1 << "," << j+1 << "] = " << y(i,j);
        EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                         std::domain_error,
                         expected_msg.str());
      }
    }

  y << 2, -1, nan,
    -1, 2, -1,
    nan, -1, nan;
  Eigen::LLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > llt_err2(y);
  EXPECT_THROW(check_pos_definite(function, "y", llt_err2),std::domain_error);

  Eigen::LDLT<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> > ldlt_err2 = y.ldlt();
  EXPECT_THROW(check_pos_definite(function, "y", ldlt_err2),std::domain_error);

  y << 0, 0, 0, 0, 0, 0, 0, 0, 0;
  expected_msg.str("");
  expected_msg << "function: y is not positive definite:\n"
               << y;
  EXPECT_THROW_MSG(check_pos_definite(function, "y", y),
                   std::domain_error,
                   expected_msg.str());
}

<|endoftext|>


<commit_before>#include "test.h"

static auto Job0 = JobQueueT<1>();
static auto Job1 = JobQueueT<1>();
static auto Job2 = JobQueueT<1>();
static auto Job3 = JobQueueT<1>();

static int counter;

static void proc()
{
	CriticalSection cs;

		        counter++;
}

static void proc3()
{
	unsigned event;

	event = Job3.wait();                         assert_success(event);
	                                             assert(counter == 4);
	event = Job2.give(proc);                     assert_success(event);
	        ThisTask::stop();
}

static void proc2()
{
	unsigned event;
		                                         assert(!Tsk3);
	        Tsk3.startFrom(proc3);               assert(!!Tsk3);
	event = Job2.wait();                         assert_success(event);
	                                             assert(counter == 3);
	event = Job3.give(proc);                     assert_success(event);
	event = Job2.wait();                         assert_success(event);
	                                             assert(counter == 5);
	event = Job1.give(proc);                     assert_success(event);
	event = Tsk3.join();                         assert_success(event);
	        ThisTask::stop();
}

static void proc1()
{
	unsigned event;
		                                         assert(!Tsk2);
	        Tsk2.startFrom(proc2);               assert(!!Tsk2);
	event = Job1.wait();                         assert_success(event);
	                                             assert(counter == 2);
	event = Job2.give(proc);                     assert_success(event);
	event = Job1.wait();                         assert_success(event);
	                                             assert(counter == 6);
	event = Job0.give(proc);                     assert_success(event);
	event = Tsk2.join();                         assert_success(event);
	        ThisTask::stop();
}

static void proc0()
{
	unsigned event;
		                                         assert(!Tsk1);
	        Tsk1.startFrom(proc1);               assert(!!Tsk1);
	event = Job0.wait();                         assert_success(event);
	                                             assert(counter == 1);
	event = Job1.give(proc);                     assert_success(event);
	event = Job0.wait();                         assert_success(event);
	                                             assert(counter == 7);
	event = Tsk1.join();                         assert_success(event);
	        ThisTask::stop();
}

static void test()
{
	unsigned event;
	                                             assert(!Tsk0);
	        Tsk0.startFrom(proc0);               assert(!!Tsk0);
	        ThisTask::yield();
	        ThisTask::yield();
	        counter = 0;
	event = Job0.give(proc);                     assert_success(event);
	event = Tsk0.join();                         assert_success(event);
}

extern "C"
void test_job_queue_3()
{
	TEST_Notify();
	TEST_Call();
}
<commit_msg>Update test_job_queue_3.cpp<commit_after>#include "test.h"

static auto Job0 = JobQueueT<1>();
static auto Job1 = JobQueueT<1>();
static auto Job2 = JobQueueT<1>();
static auto Job3 = JobQueueT<1>();

static int counter;

static void proc()
{
	CriticalSection cs;

		    counter++;
}

static void proc3()
{
	unsigned event;

	event = Job3.wait();                         assert_success(event);
	                                             assert(counter == 4);
	event = Job2.give(proc);                     assert_success(event);
	        ThisTask::stop();
}

static void proc2()
{
	unsigned event;
		                                         assert(!Tsk3);
	        Tsk3.startFrom(proc3);               assert(!!Tsk3);
	event = Job2.wait();                         assert_success(event);
	                                             assert(counter == 3);
	event = Job3.give(proc);                     assert_success(event);
	event = Job2.wait();                         assert_success(event);
	                                             assert(counter == 5);
	event = Job1.give(proc);                     assert_success(event);
	event = Tsk3.join();                         assert_success(event);
	        ThisTask::stop();
}

static void proc1()
{
	unsigned event;
		                                         assert(!Tsk2);
	        Tsk2.startFrom(proc2);               assert(!!Tsk2);
	event = Job1.wait();                         assert_success(event);
	                                             assert(counter == 2);
	event = Job2.give(proc);                     assert_success(event);
	event = Job1.wait();                         assert_success(event);
	                                             assert(counter == 6);
	event = Job0.give(proc);                     assert_success(event);
	event = Tsk2.join();                         assert_success(event);
	        ThisTask::stop();
}

static void proc0()
{
	unsigned event;
		                                         assert(!Tsk1);
	        Tsk1.startFrom(proc1);               assert(!!Tsk1);
	event = Job0.wait();                         assert_success(event);
	                                             assert(counter == 1);
	event = Job1.give(proc);                     assert_success(event);
	event = Job0.wait();                         assert_success(event);
	                                             assert(counter == 7);
	event = Tsk1.join();                         assert_success(event);
	        ThisTask::stop();
}

static void test()
{
	unsigned event;
	                                             assert(!Tsk0);
	        Tsk0.startFrom(proc0);               assert(!!Tsk0);
	        ThisTask::yield();
	        ThisTask::yield();
	        counter = 0;
	event = Job0.give(proc);                     assert_success(event);
	event = Tsk0.join();                         assert_success(event);
}

extern "C"
void test_job_queue_3()
{
	TEST_Notify();
	TEST_Call();
}
<|endoftext|>


<commit_before>#include "packets/radius_packet.h"
#include "packets/eap_packet.h"
#include "logging.h"
#include <sstream>
#include <string>
#include <iostream>
#include "typedefs.h"
#include "catch.hpp"
#include "constants.h"

namespace radius {
namespace packets {

namespace {
const std::vector<radius::byte> RADIUS_BASE_BUF = {
    0x01,       // code
    0x01,       // identifier
    0x00, 0x14, // length
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
}

TEST_CASE("Print bytes of RadiusPacket", "[packet2LogBytes]") {
    REQUIRE(packet2LogBytes(RADIUS_BASE_BUF) ==
            "01 01 00 14 00 01 02 03 04 05 " + NL +
                "06 07 08 09 0A 0B 0C 0D 0E 0F ");
}

TEST_CASE("Print RadiusPacket") {
    RadiusPacket packet(RADIUS_BASE_BUF);
    std::ostringstream stream;
    stream << packet;
    REQUIRE(stream.str() ==
            "1 Code = 1(Access-Request)" + NL + "1 ID = 1" + NL +
                "2 Length = 20" + NL + "16 Authenticator" + NL + "Attributes:" +
                NL + "    None" + NL);
}
TEST_CASE("Print RadiusPacket with AVPs") {
    RadiusPacket packet(RADIUS_BASE_BUF);
    packet.setCode(RadiusPacket::ACCESS_ACCEPT);
    MessageAuthenticator ma;
    EapMessage em;
    packet.addAVP(static_cast<const RadiusAVP &>(ma));
    packet.addAVP(static_cast<const RadiusAVP &>(em));
    std::ostringstream stream;
    stream << packet;
    REQUIRE(stream.str() ==
            "1 Code = 2(Access-Accept)" + NL + "1 ID = 1" + NL +
                "2 Length = 42" + NL + "16 Authenticator" + NL + "Attributes:" +
                NL + "    18 Message Authenticator" + NL + "    4 Eap-Message" +
                NL);
}

TEST_CASE("Print EapPacket") {
    EapPacket packet;
    std::string foo("foo");

    EapIdentity eapId;
    eapId.setIdentity(foo);

    packet.setIdentifier(1);
    packet.setType(EapPacket::SUCCESS);

    std::ostringstream stream;
    stream << packet;

    REQUIRE(stream.str() ==
            "1 Type = 3(Success)" + NL + "1 ID = 1" + NL + "2 Length = 4" + NL +
                "Type-data:" + NL + "    None" + NL);
    packet.setType(EapPacket::REQUEST);
    packet.setData(eapId);

    stream.str("");
    stream.clear();

    stream << packet;
    REQUIRE(stream.str() ==
            "1 Type = 1(Request)" + NL + "1 ID = 1" + NL + "2 Length = 8" + NL +
                "Type-data:" + NL + "    4 Identity: foo" + NL);
}
}
}
<commit_msg>fixed broken formatting<commit_after>#include "packets/radius_packet.h"
#include "packets/eap_packet.h"
#include "logging.h"
#include <sstream>
#include <string>
#include <iostream>
#include "typedefs.h"
#include "catch.hpp"
#include "constants.h"

namespace radius {
namespace packets {

namespace {
const std::vector<radius::byte> RADIUS_BASE_BUF = {
    0x01,       // code
    0x01,       // identifier
    0x00, 0x14, // length
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
}

TEST_CASE("Print bytes of RadiusPacket", "[packet2LogBytes]") {
    REQUIRE(packet2LogBytes(RADIUS_BASE_BUF) ==
            "01 01 00 14 00 01 02 03 04 05 " + NL +
                "06 07 08 09 0A 0B 0C 0D 0E 0F ");
}

TEST_CASE("Print RadiusPacket") {
    RadiusPacket packet(RADIUS_BASE_BUF);
    std::ostringstream stream;
    stream << packet;
    // clang-format off
    REQUIRE(stream.str() ==
            "1 Code = 1(Access-Request)" + NL +
            "1 ID = 1" + NL +
            "2 Length = 20" + NL +
            "16 Authenticator" + NL +
            "Attributes:" + NL +
            "    None" + NL);
    // clang-format on
}
TEST_CASE("Print RadiusPacket with AVPs") {
    RadiusPacket packet(RADIUS_BASE_BUF);
    packet.setCode(RadiusPacket::ACCESS_ACCEPT);
    MessageAuthenticator ma;
    EapMessage em;
    packet.addAVP(static_cast<const RadiusAVP &>(ma));
    packet.addAVP(static_cast<const RadiusAVP &>(em));
    std::ostringstream stream;
    stream << packet;
    // clang-format off
    REQUIRE(stream.str() ==
            "1 Code = 2(Access-Accept)" + NL +
            "1 ID = 1" + NL +
            "2 Length = 42" + NL +
            "16 Authenticator" + NL +
            "Attributes:" + NL +
            "    18 Message Authenticator" + NL +
            "    4 Eap-Message" + NL);
    // clang-format on
}

TEST_CASE("Print EapPacket") {
    EapPacket packet;
    std::string foo("foo");

    EapIdentity eapId;
    eapId.setIdentity(foo);

    packet.setIdentifier(1);
    packet.setType(EapPacket::SUCCESS);

    std::ostringstream stream;
    stream << packet;

    // clang-format off
    REQUIRE(stream.str() ==
            "1 Type = 3(Success)" + NL +
            "1 ID = 1" + NL +
            "2 Length = 4" + NL +
            "Type-data:" + NL +
            "    None" + NL);
    // clang-format on
    packet.setType(EapPacket::REQUEST);
    packet.setData(eapId);

    stream.str("");
    stream.clear();

    stream << packet;
    // clang-format off
    REQUIRE(stream.str() ==
            "1 Type = 1(Request)" + NL +
            "1 ID = 1" + NL +
            "2 Length = 8" + NL +
            "Type-data:" + NL +
            "    4 Identity: foo" + NL);
    // clang-format on
}
}
}
<|endoftext|>