<commit_before>#include <cassert>
#include <iostream>
#include "ch_frb_io.hpp"

#include "assembled_chunk_msgpack.hpp"

using namespace std;
using namespace ch_frb_io;

int main(int argc, char **argv)
{
    /*
     cout << "Warning: this will create a ~100 MB file in the current directory!\n"
     << "If this is OK press return.  If not, press control-C!\n"
     << "I AM WAITING, HUMAN: "
     << flush;
    string dummy;
    getline(cin, dummy);
     */

    uint64_t beam_id = 42;
    int nupfreq = 16;
    int nt_per_packet = 16;
    int fpga_counts_per_sample = 400;
    uint64_t ichunk = 1000;

    std::random_device rd;
    std::mt19937 rng(rd());

    shared_ptr<assembled_chunk> chunk = assembled_chunk::make(beam_id, nupfreq, nt_per_packet, fpga_counts_per_sample, ichunk);
    chunk->randomize(rng);

    /*
     const char *filename = "test_assembled_chunk.hdf5";
     chunk->write_hdf5_file(string(filename));
     */

    chunk->msgpack_bitshuffle = true;
    string fn = "test_assembled_chunk.msgpack";
    chunk->write_msgpack_file(fn);
    cout << "Wrote to " << fn << endl;

    shared_ptr<assembled_chunk> inchunk = assembled_chunk::read_msgpack_file(fn);
    cout << "Read " << inchunk << endl;
    if (memcmp(inchunk->data, chunk->data, chunk->ndata)) {
        cout << "MISMATCH in data" << endl;
    }

    // Now fill with constant values and see that it compresses
    memset(chunk->data, 42, chunk->ndata);

    fn = "test_assembled_chunk_2.msgpack";
    chunk->write_msgpack_file(fn);
    cout << "Wrote to " << fn << endl;

    shared_ptr<assembled_chunk> inchunk2 = assembled_chunk::read_msgpack_file(fn);
    cout << "Read " << inchunk2 << endl;
    if (memcmp(inchunk2->data, chunk->data, chunk->ndata)) {
        cout << "MISMATCH in data 2" << endl;
    }

    return 0;
}
<commit_msg>add test code to write out downsampled assembled_chunks.<commit_after>#include <cassert>
#include <iostream>
#include "ch_frb_io.hpp"

#include "assembled_chunk_msgpack.hpp"

#include "ch_frb_io_internals.hpp"

using namespace std;
using namespace ch_frb_io;

int main(int argc, char **argv)
{
    /*
     cout << "Warning: this will create a ~100 MB file in the current directory!\n"
     << "If this is OK press return.  If not, press control-C!\n"
     << "I AM WAITING, HUMAN: "
     << flush;
    string dummy;
    getline(cin, dummy);
     */

    uint64_t beam_id = 42;
    int nupfreq = 16;
    int nt_per_packet = 16;
    int fpga_counts_per_sample = 400;
    uint64_t ichunk = 1000;

    std::random_device rd;
    std::mt19937 rng(rd());

    unique_ptr<assembled_chunk> chunk = assembled_chunk::make(beam_id, nupfreq, nt_per_packet, fpga_counts_per_sample, ichunk);
    chunk->randomize(rng);

    /*
     const char *filename = "test_assembled_chunk.hdf5";
     chunk->write_hdf5_file(string(filename));
     */

    chunk->msgpack_bitshuffle = true;
    string fn = "test_assembled_chunk.msgpack";
    chunk->write_msgpack_file(fn);
    cout << "Wrote to " << fn << endl;

    shared_ptr<assembled_chunk> inchunk = assembled_chunk::read_msgpack_file(fn);
    //cout << "Read " << inchunk << endl;
    if (memcmp(inchunk->data, chunk->data, chunk->ndata)) {
        cout << "MISMATCH in data" << endl;
    }

    // Now fill with constant values and see that it compresses
    memset(chunk->data, 42, chunk->ndata);

    fn = "test_assembled_chunk_2.msgpack";
    chunk->write_msgpack_file(fn);
    cout << "Wrote to " << fn << endl;

    shared_ptr<assembled_chunk> inchunk2 = assembled_chunk::read_msgpack_file(fn);
    //cout << "Read " << inchunk2 << endl;
    if (memcmp(inchunk2->data, chunk->data, chunk->ndata)) {
        cout << "MISMATCH in data 2" << endl;
    }

    unique_ptr<assembled_chunk> uchunk2 = assembled_chunk::make(beam_id, nupfreq, nt_per_packet, fpga_counts_per_sample, ichunk+1);

    assembled_chunk* chunk2 = uchunk2.get();
    assembled_chunk* chunk1 = chunk.get();

    // Set up both chunk1 and chunk2 to contain ramps.

    for (int i=0; i<chunk1->nscales; i++) {
        chunk1->offsets[i] = uniform_rand(rng, 0, 10);
        chunk1->scales [i] = uniform_rand(rng, 1, 2);
    }
    for (int i=0; i<chunk2->nscales; i++) {
        chunk2->offsets[i] = uniform_rand(rng, 0, 10);
        chunk2->scales [i] = uniform_rand(rng, 1, 2);
    }

    for (int i=0; i<constants::nfreq_coarse_tot * chunk1->nupfreq; i++) {
        for (int j=0; j<constants::nt_per_assembled_chunk; j++) {
            int k = ((i / chunk1->nupfreq) * chunk1->nt_coarse +
                     (j / nt_per_packet));
            float offset = chunk1->offsets[k];
            float scale  = chunk1->scales [k];

            float fi = (float)i / (float)(constants::nfreq_coarse_tot * chunk1->nupfreq);
            float fj = (float)j / (float)constants::nt_per_assembled_chunk;
            float val = 20 + fi * 25 + fj * 50;

            chunk1->data[i * constants::nt_per_assembled_chunk + j] = (val - offset) / scale;

            offset = chunk2->offsets[k];
            scale  = chunk2->scales [k];

            val = 20 + fi * 25 + (fj+1) * 50;
            chunk2->data[i * constants::nt_per_assembled_chunk + j] = (val - offset) / scale;
        }
    }

    chunk1->write_msgpack_file("test-chunk1.msgpack");
    chunk2->write_msgpack_file("test-chunk2.msgpack");

    assembled_chunk* chunk3 = assembled_chunk::downsample(NULL, chunk1, chunk2);
    chunk3->write_msgpack_file("test-chunk3.msgpack");

    float* intensity = (float*)malloc(chunk1->ndata * sizeof(float));
    float* weight    = (float*)malloc(chunk1->ndata * sizeof(float));

    chunk1->decode(intensity, weight, constants::nt_per_assembled_chunk);

    FILE* f = fopen("chunk1-decoded.raw", "w");
    fwrite(intensity, 1, chunk1->ndata * sizeof(float), f);
    fclose(f);

    chunk2->decode(intensity, weight, constants::nt_per_assembled_chunk);

    f = fopen("chunk2-decoded.raw", "w");
    fwrite(intensity, 1, chunk1->ndata * sizeof(float), f);
    fclose(f);

    chunk3->decode(intensity, weight, constants::nt_per_assembled_chunk);
    f = fopen("chunk3-decoded.raw", "w");
    fwrite(intensity, 1, chunk1->ndata * sizeof(float), f);
    fclose(f);

    return 0;
}
<|endoftext|>


<commit_before>// RUN: cat %s | %cling -Xclang -verify -I%p
// XFAIL: vg
// We expect for now this to fail, because the access to the invalid memory comes
// from the fact that we invalidate the included file cache and when we are in
// verify mode the verifier notifies about errors at the end of the source file.
//
// Tests the ChainedConsumer's ability to recover from errors. .x produces
// #include \"CannotDotX.h\" \n void wrapper() {CannotDotX();}, which causes
// a TagDecl to be passed trough the consumers. This TagDecl is caught twice by
// the ChainedConsumer and cached is the queue of incoming declaration twice.
// If we encounter error the ChainedConsumer shouldn't try to remove the
// declaration twice and this test makes sure of that.

.x CannotDotX.h() // expected-error {{use of undeclared identifier 'CannotDotX'}}
.x CannotDotX.h() // expected-error {{use of undeclared identifier 'CannotDotX'}}

 // Uses a bug in the implementation of .L, which must be fixed soon.
 // Exposes another issue with the VerifyDiagnosticConsumer in the context of
 // cling. The first .L shouldn't cause errors . However when using the
 // preprocessor most probably we lose track of the errors source locations
 // and files.
.L CannotDotX.h "// expected-error {{redefinition of 'MyClass'}} expected-error {{expected member name or ';' after declaration specifiers}} expected-node {{previous definition is here}}

.L CannotDotX.h

.q
<commit_msg>Do not issue error in case: .x MyFile() - where no string is between the parenthesis.<commit_after>// RUN: cat %s | %cling -Xclang -verify -I%p
// XFAIL: vg
.x CannotDotX.h() // expected-error {{use of undeclared identifier 'CannotDotX'}}
.x CannotDotX.h() // expected-error {{use of undeclared identifier 'CannotDotX'}}

 // Uses a bug in the implementation of .L, which must be fixed soon.
 // Exposes another issue with the VerifyDiagnosticConsumer in the context of
 // cling. The first .L shouldn't cause errors . However when using the
 // preprocessor most probably we lose track of the errors source locations
 // and files.
.L CannotDotX.h "// expected-error {{redefinition of 'MyClass'}} expected-error {{expected member name or ';' after declaration specifiers}} expected-node {{previous definition is here}}

.L CannotDotX.h

.q
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2020 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#include "common/DebugLog.h"
#include "common/ReaperRoot.h"

#include "renderer/Renderer.h"
#include "renderer/vulkan/Test.h"
#include "renderer/vulkan/VulkanRenderer.h"

#include "core/Profile.h"

int main(int /*ac*/, char** /*av*/)
{
#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileOnThreadCreate("Main");
    MicroProfileSetEnableAllGroups(true);
    MicroProfileSetForceMetaCounters(true);
    MicroProfileStartContextSwitchTrace();
#endif

    {
        using namespace Reaper;

        ReaperRoot root = {};

        root.log = new DebugLog();

        log_info(root, "engine: startup");
        {
            if (create_renderer(root))
            {
                vulkan_test(root, *root.renderer->backend);
                destroy_renderer(root);
            }
        }
        log_info(root, "engine: shutdown");

        delete root.log;
        root.log = nullptr;
    }

#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileDumpFileImmediately("profile.html", nullptr, nullptr);
    MicroProfileShutdown();
#endif

    return 0;
}
<commit_msg>microprofile: do not write html at the end of the session<commit_after>////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2020 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#include "common/DebugLog.h"
#include "common/ReaperRoot.h"

#include "renderer/Renderer.h"
#include "renderer/vulkan/Test.h"
#include "renderer/vulkan/VulkanRenderer.h"

#include "core/Profile.h"

int main(int /*ac*/, char** /*av*/)
{
#if defined(REAPER_USE_MICROPROFILE)
    MicroProfileOnThreadCreate("Main");
    MicroProfileSetEnableAllGroups(true);
    MicroProfileSetForceMetaCounters(true);
    MicroProfileStartContextSwitchTrace();
#endif

    {
        using namespace Reaper;

        ReaperRoot root = {};

        root.log = new DebugLog();

        log_info(root, "engine: startup");
        {
            if (create_renderer(root))
            {
                vulkan_test(root, *root.renderer->backend);
                destroy_renderer(root);
            }
        }
        log_info(root, "engine: shutdown");

        delete root.log;
        root.log = nullptr;
    }

#if defined(REAPER_USE_MICROPROFILE)
    // MicroProfileDumpFileImmediately("profile.html", nullptr, nullptr);
    MicroProfileShutdown();
#endif

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2017 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 "tx_verify.h"

#include "consensus.h"
#include "primitives/transaction.h"
#include "script/interpreter.h"
#include "validation.h"

// TODO remove the following dependencies
#include "chain.h"
#include "coins.h"
#include "utilmoneystr.h"

bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
    if (tx.nLockTime == 0)
        return true;
    if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
        return true;
    for (const auto& txin : tx.vin) {
        if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
            return false;
    }
    return true;
}

std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    assert(prevHeights->size() == tx.vin.size());

    // Will be set to the equivalent height- and time-based nLockTime
    // values that would be necessary to satisfy all relative lock-
    // time constraints given our view of block chain history.
    // The semantics of nLockTime are the last invalid height/time, so
    // use -1 to have the effect of any height or time being valid.
    int nMinHeight = -1;
    int64_t nMinTime = -1;

    // tx.nVersion is signed integer so requires cast to unsigned otherwise
    // we would be doing a signed comparison and half the range of nVersion
    // wouldn't support BIP 68.
    bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
                      && flags & LOCKTIME_VERIFY_SEQUENCE;

    // Do not enforce sequence numbers as a relative lock time
    // unless we have been instructed to
    if (!fEnforceBIP68) {
        return std::make_pair(nMinHeight, nMinTime);
    }

    for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
        const CTxIn& txin = tx.vin[txinIndex];

        // Sequence numbers with the most significant bit set are not
        // treated as relative lock-times, nor are they given any
        // consensus-enforced meaning at this point.
        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
            // The height of this input is not relevant for sequence locks
            (*prevHeights)[txinIndex] = 0;
            continue;
        }

        int nCoinHeight = (*prevHeights)[txinIndex];

        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
            int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
            // NOTE: Subtract 1 to maintain nLockTime semantics
            // BIP 68 relative lock times have the semantics of calculating
            // the first block or time at which the transaction would be
            // valid. When calculating the effective block time or height
            // for the entire transaction, we switch to using the
            // semantics of nLockTime which is the last invalid block
            // time or height.  Thus we subtract 1 from the calculated
            // time or height.

            // Time-based relative lock-times are measured from the
            // smallest allowed timestamp of the block containing the
            // txout being spent, which is the median time past of the
            // block prior.
            nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
        } else {
            nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
        }
    }

    return std::make_pair(nMinHeight, nMinTime);
}

bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
{
    assert(block.pprev);
    int64_t nBlockTime = block.pprev->GetMedianTimePast();
    if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
        return false;

    return true;
}

bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}

unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
    unsigned int nSigOps = 0;
    for (const auto& txin : tx.vin)
    {
        nSigOps += txin.scriptSig.GetSigOpCount(false);
    }
    for (const auto& txout : tx.vout)
    {
        nSigOps += txout.scriptPubKey.GetSigOpCount(false);
    }
    return nSigOps;
}

unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
{
    if (tx.IsCoinBase())
        return 0;

    unsigned int nSigOps = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        if (prevout.scriptPubKey.IsPayToScriptHash())
            nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
    }
    return nSigOps;
}

int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
{
    int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;

    if (tx.IsCoinBase())
        return nSigOps;

    if (flags & SCRIPT_VERIFY_P2SH) {
        nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
    }

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
    }
    return nSigOps;
}

bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
{
    // Basic checks that don't depend on any context
    if (tx.vin.empty())
        return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
    if (tx.vout.empty())
        return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
    // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
    if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
        return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");

    // Check for negative or overflow output values
    CAmount nValueOut = 0;
    for (const auto& txout : tx.vout)
    {
        if (txout.nValue < 0)
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
        if (txout.nValue > MAX_MONEY)
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
        nValueOut += txout.nValue;
        if (!MoneyRange(nValueOut))
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
    }

    // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
    if (fCheckDuplicateInputs) {
        std::set<COutPoint> vInOutPoints;
        for (const auto& txin : tx.vin)
        {
            if (!vInOutPoints.insert(txin.prevout).second)
                return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
        }
    }

    if (tx.IsCoinBase())
    {
        if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
            return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
    }
    else
    {
        for (const auto& txin : tx.vin)
            if (txin.prevout.IsNull())
                return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
    }

    return true;
}

bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
{
        // This doesn't trigger the DoS code on purpose; if it did, it would make it easier
        // for an attacker to attempt to split the network.
        if (!inputs.HaveInputs(tx))
            return state.Invalid(false, 0, "", "Inputs unavailable");

        CAmount nValueIn = 0;
        CAmount nFees = 0;
        for (unsigned int i = 0; i < tx.vin.size(); i++)
        {
            const COutPoint &prevout = tx.vin[i].prevout;
            const Coin& coin = inputs.AccessCoin(prevout);
            assert(!coin.IsSpent());

            // If prev is coinbase, check that it's matured
            if (coin.IsCoinBase()) {
                if (nSpendHeight - coin.nHeight < COINBASE_MATURITY)
                    return state.Invalid(false,
                        REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
                        strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
            }

            // Check for negative or overflow input values
            nValueIn += coin.out.nValue;
            if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn))
                return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");

        }

        if (nValueIn < tx.GetValueOut())
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
                strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())));

        // Tally transaction fees
        CAmount nTxFee = nValueIn - tx.GetValueOut();
        if (nTxFee < 0)
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative");
        nFees += nTxFee;
        if (!MoneyRange(nFees))
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
    return true;
}
<commit_msg>Proper indentation for CheckTxInputs and other minor fixes<commit_after>// Copyright (c) 2017-2017 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 "tx_verify.h"

#include "consensus.h"
#include "primitives/transaction.h"
#include "script/interpreter.h"
#include "validation.h"

// TODO remove the following dependencies
#include "chain.h"
#include "coins.h"
#include "utilmoneystr.h"

bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
    if (tx.nLockTime == 0)
        return true;
    if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
        return true;
    for (const auto& txin : tx.vin) {
        if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
            return false;
    }
    return true;
}

std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    assert(prevHeights->size() == tx.vin.size());

    // Will be set to the equivalent height- and time-based nLockTime
    // values that would be necessary to satisfy all relative lock-
    // time constraints given our view of block chain history.
    // The semantics of nLockTime are the last invalid height/time, so
    // use -1 to have the effect of any height or time being valid.
    int nMinHeight = -1;
    int64_t nMinTime = -1;

    // tx.nVersion is signed integer so requires cast to unsigned otherwise
    // we would be doing a signed comparison and half the range of nVersion
    // wouldn't support BIP 68.
    bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
                      && flags & LOCKTIME_VERIFY_SEQUENCE;

    // Do not enforce sequence numbers as a relative lock time
    // unless we have been instructed to
    if (!fEnforceBIP68) {
        return std::make_pair(nMinHeight, nMinTime);
    }

    for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
        const CTxIn& txin = tx.vin[txinIndex];

        // Sequence numbers with the most significant bit set are not
        // treated as relative lock-times, nor are they given any
        // consensus-enforced meaning at this point.
        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
            // The height of this input is not relevant for sequence locks
            (*prevHeights)[txinIndex] = 0;
            continue;
        }

        int nCoinHeight = (*prevHeights)[txinIndex];

        if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
            int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
            // NOTE: Subtract 1 to maintain nLockTime semantics
            // BIP 68 relative lock times have the semantics of calculating
            // the first block or time at which the transaction would be
            // valid. When calculating the effective block time or height
            // for the entire transaction, we switch to using the
            // semantics of nLockTime which is the last invalid block
            // time or height.  Thus we subtract 1 from the calculated
            // time or height.

            // Time-based relative lock-times are measured from the
            // smallest allowed timestamp of the block containing the
            // txout being spent, which is the median time past of the
            // block prior.
            nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
        } else {
            nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
        }
    }

    return std::make_pair(nMinHeight, nMinTime);
}

bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
{
    assert(block.pprev);
    int64_t nBlockTime = block.pprev->GetMedianTimePast();
    if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
        return false;

    return true;
}

bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
{
    return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}

unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
    unsigned int nSigOps = 0;
    for (const auto& txin : tx.vin)
    {
        nSigOps += txin.scriptSig.GetSigOpCount(false);
    }
    for (const auto& txout : tx.vout)
    {
        nSigOps += txout.scriptPubKey.GetSigOpCount(false);
    }
    return nSigOps;
}

unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
{
    if (tx.IsCoinBase())
        return 0;

    unsigned int nSigOps = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        if (prevout.scriptPubKey.IsPayToScriptHash())
            nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
    }
    return nSigOps;
}

int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
{
    int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;

    if (tx.IsCoinBase())
        return nSigOps;

    if (flags & SCRIPT_VERIFY_P2SH) {
        nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
    }

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
        assert(!coin.IsSpent());
        const CTxOut &prevout = coin.out;
        nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
    }
    return nSigOps;
}

bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
{
    // Basic checks that don't depend on any context
    if (tx.vin.empty())
        return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
    if (tx.vout.empty())
        return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
    // Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
    if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
        return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");

    // Check for negative or overflow output values
    CAmount nValueOut = 0;
    for (const auto& txout : tx.vout)
    {
        if (txout.nValue < 0)
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
        if (txout.nValue > MAX_MONEY)
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
        nValueOut += txout.nValue;
        if (!MoneyRange(nValueOut))
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
    }

    // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
    if (fCheckDuplicateInputs) {
        std::set<COutPoint> vInOutPoints;
        for (const auto& txin : tx.vin)
        {
            if (!vInOutPoints.insert(txin.prevout).second)
                return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
        }
    }

    if (tx.IsCoinBase())
    {
        if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
            return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
    }
    else
    {
        for (const auto& txin : tx.vin)
            if (txin.prevout.IsNull())
                return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
    }

    return true;
}

bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
{
    // This doesn't trigger the DoS code on purpose; if it did, it would make it easier
    // for an attacker to attempt to split the network.
    if (!inputs.HaveInputs(tx)) {
        return state.Invalid(false, 0, "", "Inputs unavailable");
    }

    CAmount nValueIn = 0;
    CAmount nFees = 0;
    for (unsigned int i = 0; i < tx.vin.size(); ++i) {
        const COutPoint &prevout = tx.vin[i].prevout;
        const Coin& coin = inputs.AccessCoin(prevout);
        assert(!coin.IsSpent());

        // If prev is coinbase, check that it's matured
        if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
            return state.Invalid(false,
                REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
                strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
        }

        // Check for negative or overflow input values
        nValueIn += coin.out.nValue;
        if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
            return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
        }
    }

    if (nValueIn < tx.GetValueOut()) {
        return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
            strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())));
    }

    // Tally transaction fees
    CAmount nTxFee = nValueIn - tx.GetValueOut();
    if (nTxFee < 0) {
        return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative");
    }
    nFees += nTxFee;
    if (!MoneyRange(nFees)) {
        return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
    }
    return true;
}
<|endoftext|>


<commit_before>// RUN: %clangxx_asan -DWAIT4 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAIT4 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s

// RUN: %clangxx_asan -DWAIT4_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s

// XFAIL: android

#include <assert.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char **argv) {
  // This test passes on some versions of Android NDK and fails on other.
  // https://code.google.com/p/memory-sanitizer/issues/detail?id=64
  // Make it fail unconditionally on Android.
#ifdef __ANDROID__
  return 0;
#endif

  pid_t pid = fork();
  if (pid) { // parent
    int x[3];
    int *status = x + argc * 3;
    int res;
#if defined(WAIT4)
    res = wait4(pid, status, WNOHANG, NULL);
#elif defined(WAIT4_RUSAGE)
    struct rusage *ru = (struct rusage*)(x + argc * 3);
    int good_status;
    res = wait4(pid, &good_status, WNOHANG, ru);
#endif
    // CHECK: stack-buffer-overflow
    // CHECK: {{WRITE of size .* at 0x.* thread T0}}
    // CHECK: {{in .*wait}}
    // CHECK: {{in main .*wait.cc:}}
    // CHECK: is located in stack of thread T0 at offset
    // CHECK: {{in main}}
    return res == -1 ? 1 : 0;
  }
  // child
  return 0;
}
<commit_msg>[asan] Fix path in test.<commit_after>// RUN: %clangxx_asan -DWAIT4 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAIT4 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s

// RUN: %clangxx_asan -DWAIT4_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s

// XFAIL: android

#include <assert.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char **argv) {
  // This test passes on some versions of Android NDK and fails on other.
  // https://code.google.com/p/memory-sanitizer/issues/detail?id=64
  // Make it fail unconditionally on Android.
#ifdef __ANDROID__
  return 0;
#endif

  pid_t pid = fork();
  if (pid) { // parent
    int x[3];
    int *status = x + argc * 3;
    int res;
#if defined(WAIT4)
    res = wait4(pid, status, WNOHANG, NULL);
#elif defined(WAIT4_RUSAGE)
    struct rusage *ru = (struct rusage*)(x + argc * 3);
    int good_status;
    res = wait4(pid, &good_status, WNOHANG, ru);
#endif
    // CHECK: stack-buffer-overflow
    // CHECK: {{WRITE of size .* at 0x.* thread T0}}
    // CHECK: {{in .*wait}}
    // CHECK: {{in main .*wait4.cc:}}
    // CHECK: is located in stack of thread T0 at offset
    // CHECK: {{in main}}
    return res == -1 ? 1 : 0;
  }
  // child
  return 0;
}
<|endoftext|>


<commit_before>#include "curvetree_view.h"
#include "curvelist_panel.h"
#include <QFontDatabase>
#include <QObject>

class TreeWidgetItem : public QTreeWidgetItem
{
   public:
    TreeWidgetItem(QTreeWidgetItem *parent) : QTreeWidgetItem(parent) {}

    bool operator< (const QTreeWidgetItem &other) const
    {
        return doj::alphanum_impl(this->text(0).toLocal8Bit(),
                                  other.text(0).toLocal8Bit()) < 0;
    }
};

CurveTreeView::CurveTreeView(CurveListPanel* parent) : QTreeWidget(parent), CurvesView(parent)
{
    setColumnCount(2);
    setEditTriggers(NoEditTriggers);
    setDragEnabled(false);
    setDefaultDropAction(Qt::IgnoreAction);
    setDragDropOverwriteMode(false);
    setDragDropMode(NoDragDrop);
    viewport()->installEventFilter(this);
    setSelectionMode(ExtendedSelection);

    header()->setVisible(false);
    header()->setStretchLastSection(true);
    header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}

void CurveTreeView::addItem(const QString& item_name)
{
    auto parts = item_name.split('/', QString::SplitBehavior::SkipEmptyParts);
    if (parts.size() == 0)
    {
        return;
    }

    QTreeWidgetItem* tree_parent = this->invisibleRootItem();

    for (int i = 0; i < parts.size(); i++)
    {
        bool is_leaf = (i == parts.size() - 1);
        const auto& part = parts[ i ];

        QTreeWidgetItem* matching_child = nullptr;

        for (int c = 0; c < tree_parent->childCount(); c++)
        {
            QTreeWidgetItem* tree_child = tree_parent->child(c);
            if (tree_child->text(0) == part)
            {
                matching_child = tree_child;
                break;
            }
        }

        if (matching_child)
        {
            tree_parent = matching_child;
        }
        else
        {
            QTreeWidgetItem* child_item = new TreeWidgetItem(tree_parent);
            child_item->setText(0, part);
            child_item->setText(1, is_leaf ? "-" : "");

            QFont font = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
            font.setPointSize(_point_size);
            child_item->setFont(0, font);

            font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
            font.setPointSize(_point_size);
            child_item->setFont(1, font);
            child_item->setTextAlignment(1, Qt::AlignRight);

            tree_parent = child_item;

            auto current_flag = child_item->flags();

            if (is_leaf)
            {
                child_item->setFlags(current_flag | Qt::ItemIsSelectable);
                child_item->setData(0, Qt::UserRole, item_name);
            }
            else
            {
                child_item->setFlags(current_flag & (~Qt::ItemIsSelectable));
            }
        }
    }
    _leaf_count++;
}

void CurveTreeView::refreshColumns()
{
    invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
    treeVisitor([&](QTreeWidgetItem* item){
                    item->sortChildren(0, Qt::AscendingOrder);
                } );
    header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    // TODO emit updateFilter();
}

std::vector<std::string> CurveTreeView::getSelectedNames()
{
    std::vector<std::string> non_hidden_list;

    for (const auto& item : selectedItems())
    {
        non_hidden_list.push_back(
            item->data(0, Qt::UserRole).toString().toStdString());
    }
    return non_hidden_list;
}

void CurveTreeView::refreshFontSize()
{
    header()->setSectionResizeMode(0, QHeaderView::Fixed);
    header()->setSectionResizeMode(1, QHeaderView::Fixed);

    treeVisitor([this](QTreeWidgetItem* item) {
        auto font = item->font(0);
        font.setPointSize(_point_size);
        item->setFont(0, font);
        font = item->font(1);
        font.setPointSize(_point_size);
        item->setFont(1, font);
    });

    header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    header()->setSectionResizeMode(1, QHeaderView::Stretch);
}

bool CurveTreeView::applyVisibilityFilter(CurvesView::FilterType type,
                                          const QString& search_string)
{
    bool updated = false;
    _hidden_count = 0;
    QRegExp regexp(search_string, Qt::CaseInsensitive, QRegExp::Wildcard);
    QRegExpValidator v(regexp, nullptr);

    QStringList spaced_items = search_string.split(' ');

    auto hideFunc = [&](QTreeWidgetItem* item)
    {
        QString name = item->data(0, Qt::UserRole).toString();
        if( name.isEmpty() )
        {
            return; // not a leaf
        }
        bool toHide = false;

        if (search_string.isEmpty() == false)
        {
            if (type == REGEX)
            {
                int pos = 0;
                toHide = (v.validate(name, pos) != QValidator::Acceptable);
            }
            else if (type == CONTAINS)
            {
                for (const auto& item : spaced_items)
                {
                    if (name.contains(item, Qt::CaseInsensitive) == false)
                    {
                        toHide = true;
                        break;
                    }
                }
            }
        }
        if (toHide)
        {
            _hidden_count++;
        }

        if (toHide != item->isHidden())
        {
            updated = true;
        }

        item->setHidden(toHide);

        // hide the parent if necessary
        auto parent = item->parent();
        while( parent )
        {
            bool all_children_hidden = true;
            for (int c = 0; c < parent->childCount(); c++)
            {
                if( !parent->child(c)->isHidden() )
                {
                    all_children_hidden = false;
                    break;
                }
            }
            auto parent_hidden = parent->isHidden();
            if( all_children_hidden != parent_hidden)
            {
                parent->setHidden( all_children_hidden );
                parent = parent->parent();
            }
            else{
                break;
            }
        }
    };

   treeVisitor( hideFunc );
   //-------------

   return updated;
}

void CurveTreeView::removeCurve(const QString &to_be_deleted)
{
    auto removeFunc = [&](QTreeWidgetItem* item)
    {
        QString curve_name = item->data(0, Qt::UserRole).toString();
        if( curve_name == to_be_deleted)
        {
            _leaf_count --;
            auto parent_item = item->parent();
            parent_item->removeChild(item);

            while (parent_item->childCount() == 0 &&
                   parent_item != invisibleRootItem())
            {
                auto prev_item = parent_item;
                parent_item = parent_item->parent();
                if(!parent_item)
                {
                    parent_item = invisibleRootItem();
                }
                parent_item->removeChild(prev_item);
            }
        }
    };

    treeVisitor( removeFunc );
}

void CurveTreeView::hideValuesColumn(bool hide)
{
    if(hide){
        hideColumn(1);
    }
    else  {
        showColumn(1);
    }
}

void CurveTreeView::treeVisitor(std::function<void(QTreeWidgetItem*)> visitor)
{
    std::function<void(QTreeWidgetItem*)> recursiveFunction;
    recursiveFunction = [&](QTreeWidgetItem* item)
    {
        visitor(item);
        for (int c = 0; c < item->childCount(); c++)
        {
            recursiveFunction(item->child(c));
        }
    };

    for (int c = 0; c < invisibleRootItem()->childCount(); c++)
    {
        recursiveFunction(invisibleRootItem()->child(c));
    }
}
<commit_msg>bug fix<commit_after>#include "curvetree_view.h"
#include "curvelist_panel.h"
#include <QFontDatabase>
#include <QObject>

class TreeWidgetItem : public QTreeWidgetItem
{
   public:
    TreeWidgetItem(QTreeWidgetItem *parent) : QTreeWidgetItem(parent) {}

    bool operator< (const QTreeWidgetItem &other) const
    {
        return doj::alphanum_impl(this->text(0).toLocal8Bit(),
                                  other.text(0).toLocal8Bit()) < 0;
    }
};

CurveTreeView::CurveTreeView(CurveListPanel* parent) : QTreeWidget(parent), CurvesView(parent)
{
    setColumnCount(2);
    setEditTriggers(NoEditTriggers);
    setDragEnabled(false);
    setDefaultDropAction(Qt::IgnoreAction);
    setDragDropOverwriteMode(false);
    setDragDropMode(NoDragDrop);
    viewport()->installEventFilter(this);
    setSelectionMode(ExtendedSelection);

    header()->setVisible(false);
    header()->setStretchLastSection(true);
    header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
}

void CurveTreeView::addItem(const QString& item_name)
{
    auto parts = item_name.split('/', QString::SplitBehavior::SkipEmptyParts);
    if (parts.size() == 0)
    {
        return;
    }

    QTreeWidgetItem* tree_parent = this->invisibleRootItem();

    for (int i = 0; i < parts.size(); i++)
    {
        bool is_leaf = (i == parts.size() - 1);
        const auto& part = parts[ i ];

        QTreeWidgetItem* matching_child = nullptr;

        for (int c = 0; c < tree_parent->childCount(); c++)
        {
            QTreeWidgetItem* tree_child = tree_parent->child(c);
            if (tree_child->text(0) == part)
            {
                matching_child = tree_child;
                break;
            }
        }

        if (matching_child)
        {
            tree_parent = matching_child;
        }
        else
        {
            QTreeWidgetItem* child_item = new TreeWidgetItem(tree_parent);
            child_item->setText(0, part);
            child_item->setText(1, is_leaf ? "-" : "");

            QFont font = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
            font.setPointSize(_point_size);
            child_item->setFont(0, font);

            font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
            font.setPointSize(_point_size);
            child_item->setFont(1, font);
            child_item->setTextAlignment(1, Qt::AlignRight);

            tree_parent = child_item;

            auto current_flag = child_item->flags();

            if (is_leaf)
            {
                child_item->setFlags(current_flag | Qt::ItemIsSelectable);
                child_item->setData(0, Qt::UserRole, item_name);
            }
            else
            {
                child_item->setFlags(current_flag & (~Qt::ItemIsSelectable));
            }
        }
    }
    _leaf_count++;
}

void CurveTreeView::refreshColumns()
{
    invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
    treeVisitor([&](QTreeWidgetItem* item){
                    item->sortChildren(0, Qt::AscendingOrder);
                } );
    header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    // TODO emit updateFilter();
}

std::vector<std::string> CurveTreeView::getSelectedNames()
{
    std::vector<std::string> non_hidden_list;

    for (const auto& item : selectedItems())
    {
        non_hidden_list.push_back(
            item->data(0, Qt::UserRole).toString().toStdString());
    }
    return non_hidden_list;
}

void CurveTreeView::refreshFontSize()
{
    header()->setSectionResizeMode(0, QHeaderView::Fixed);
    header()->setSectionResizeMode(1, QHeaderView::Fixed);

    treeVisitor([this](QTreeWidgetItem* item) {
        auto font = item->font(0);
        font.setPointSize(_point_size);
        item->setFont(0, font);
        font = item->font(1);
        font.setPointSize(_point_size);
        item->setFont(1, font);
    });

    header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    header()->setSectionResizeMode(1, QHeaderView::Stretch);
}

bool CurveTreeView::applyVisibilityFilter(CurvesView::FilterType type,
                                          const QString& search_string)
{
    bool updated = false;
    _hidden_count = 0;
    QRegExp regexp(search_string, Qt::CaseInsensitive, QRegExp::Wildcard);
    QRegExpValidator v(regexp, nullptr);

    QStringList spaced_items = search_string.split(' ');

    auto hideFunc = [&](QTreeWidgetItem* item)
    {
        QString name = item->data(0, Qt::UserRole).toString();
        if( name.isEmpty() )
        {
            return; // not a leaf
        }
        bool toHide = false;

        if (search_string.isEmpty() == false)
        {
            if (type == REGEX)
            {
                int pos = 0;
                toHide = (v.validate(name, pos) != QValidator::Acceptable);
            }
            else if (type == CONTAINS)
            {
                for (const auto& item : spaced_items)
                {
                    if (name.contains(item, Qt::CaseInsensitive) == false)
                    {
                        toHide = true;
                        break;
                    }
                }
            }
        }
        if (toHide)
        {
            _hidden_count++;
        }

        if (toHide != item->isHidden())
        {
            updated = true;
        }

        item->setHidden(toHide);

        // hide the parent if necessary
        auto parent = item->parent();
        while( parent )
        {
            bool all_children_hidden = true;
            for (int c = 0; c < parent->childCount(); c++)
            {
                if( !parent->child(c)->isHidden() )
                {
                    all_children_hidden = false;
                    break;
                }
            }
            auto parent_hidden = parent->isHidden();
            if( all_children_hidden != parent_hidden)
            {
                parent->setHidden( all_children_hidden );
                parent = parent->parent();
            }
            else{
                break;
            }
        }
    };

   treeVisitor( hideFunc );
   //-------------

   return updated;
}

void CurveTreeView::removeCurve(const QString &to_be_deleted)
{
    auto removeFunc = [&](QTreeWidgetItem* item)
    {
        QString curve_name = item->data(0, Qt::UserRole).toString();
        if( curve_name == to_be_deleted)
        {
            _leaf_count --;
            auto parent_item = item->parent();
            if(!parent_item)
            {
                parent_item = invisibleRootItem();
            }
            parent_item->removeChild(item);

            while (parent_item->childCount() == 0 &&
                   parent_item != invisibleRootItem())
            {
                auto prev_item = parent_item;
                parent_item = parent_item->parent();
                if(!parent_item)
                {
                    parent_item = invisibleRootItem();
                }
                parent_item->removeChild(prev_item);
            }
        }
    };

    treeVisitor( removeFunc );
}

void CurveTreeView::hideValuesColumn(bool hide)
{
    if(hide){
        hideColumn(1);
    }
    else  {
        showColumn(1);
    }
}

void CurveTreeView::treeVisitor(std::function<void(QTreeWidgetItem*)> visitor)
{
    std::function<void(QTreeWidgetItem*)> recursiveFunction;
    recursiveFunction = [&](QTreeWidgetItem* item)
    {
        visitor(item);
        for (int c = 0; c < item->childCount(); c++)
        {
            recursiveFunction(item->child(c));
        }
    };

    for (int c = 0; c < invisibleRootItem()->childCount(); c++)
    {
        recursiveFunction(invisibleRootItem()->child(c));
    }
}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Łukasz Twarduś <ltwardus@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.

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

#include "lxqtsensors.h"
#include "lxqtsensorsconfiguration.h"
#include "../panel/ilxqtpanelplugin.h"
#include "../panel/ilxqtpanel.h"
#include <QBoxLayout>
#include <QDebug>
#include <QMessageBox>
#include <QPalette>

LXQtSensors::LXQtSensors(ILXQtPanelPlugin *plugin, QWidget* parent):
    QFrame(parent),
    mPlugin(plugin),
    mSettings(plugin->settings())
{

    mDetectedChips = mSensors.getDetectedChips();

    /**
     * We have all needed data to initialize default settings, we have to do it here as later
     * we are using them.
     */
    initDefaultSettings();

    // Add GUI elements
    ProgressBar* pg = NULL;

    mLayout = new QBoxLayout(QBoxLayout::LeftToRight, this);
    mLayout->setSpacing(0);
    mLayout->setContentsMargins(0, 0, 0, 0);

    QString chipFeatureLabel;

    mSettings->beginGroup("chips");

    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        mSettings->beginGroup(mDetectedChips[i].getName());
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                chipFeatureLabel = features[j].getLabel();
                mSettings->beginGroup(chipFeatureLabel);

                pg = new ProgressBar(this);
                pg->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

                // Hide progress bar if it is not enabled
                if (!mSettings->value("enabled").toBool())
                {
                    pg->hide();
                }

                pg->setToolTip(chipFeatureLabel);
                pg->setTextVisible(false);

                QPalette pal = pg->palette();
                QColor color(mSettings->value("color").toString());
                pal.setColor(QPalette::Active, QPalette::Highlight, color);
                pal.setColor(QPalette::Inactive, QPalette::Highlight, color);
                pg->setPalette(pal);

                mTemperatureProgressBars.push_back(pg);
                mLayout->addWidget(pg);

                mSettings->endGroup();
            }
        }
        mSettings->endGroup();
    }

    mSettings->endGroup();

    // Fit plugin to current panel
    realign();

    // Updated sensors readings to display actual values at start
    updateSensorReadings();

    // Run timer that will be updating sensor readings
    connect(&mUpdateSensorReadingsTimer, SIGNAL(timeout()), this, SLOT(updateSensorReadings()));
    mUpdateSensorReadingsTimer.start(mSettings->value("updateInterval").toInt() * 1000);

    // Run timer that will be showin warning
    mWarningAboutHighTemperatureTimer.setInterval(500);
    connect(&mWarningAboutHighTemperatureTimer, SIGNAL(timeout()), this,
            SLOT(warningAboutHighTemperature()));
    if (mSettings->value("warningAboutHighTemperature").toBool())
    {
        mWarningAboutHighTemperatureTimer.start();
    }
}

LXQtSensors::~LXQtSensors()
{
}

void LXQtSensors::updateSensorReadings()
{
    QString tooltip;

    double critTemp = 0;
    double maxTemp = 0;
    double minTemp = 0;
    double curTemp = 0;
    bool highTemperature = false;

    // Iterator for temperature progress bars
    QList<ProgressBar*>::iterator temperatureProgressBarsIt =
        mTemperatureProgressBars.begin();

    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                tooltip = features[j].getLabel() + " (" + QChar(0x00B0);

                if (mSettings->value("useFahrenheitScale").toBool())
                {
                    critTemp = celsiusToFahrenheit(
                        features[j].getValue(SENSORS_SUBFEATURE_TEMP_CRIT));
                    maxTemp = celsiusToFahrenheit(
                        features[j].getValue(SENSORS_SUBFEATURE_TEMP_MAX));
                    minTemp = celsiusToFahrenheit(
                        features[j].getValue(SENSORS_SUBFEATURE_TEMP_MIN));
                    curTemp = celsiusToFahrenheit(
                        features[j].getValue(SENSORS_SUBFEATURE_TEMP_INPUT));

                    tooltip += "F)";
                }
                else
                {
                    critTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_CRIT);
                    maxTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_MAX);
                    minTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_MIN);
                    curTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_INPUT);

                    tooltip += "C)";
                }

                // Check if temperature is too high
                if (curTemp >= maxTemp)
                {
                    if (mSettings->value("warningAboutHighTemperature").toBool())
                    {
                        // Add current progress bar to the "warning container"
                        mHighTemperatureProgressBars.insert(*temperatureProgressBarsIt);
                    }

                    highTemperature = true;
                }
                else
                {
                    mHighTemperatureProgressBars.remove(*temperatureProgressBarsIt);

                    highTemperature = false;
                }

                // Set maximum temperature
                (*temperatureProgressBarsIt)->setMaximum(critTemp);
                // Set minimum temperature
                (*temperatureProgressBarsIt)->setMinimum(minTemp);
                // Set current temperature
                (*temperatureProgressBarsIt)->setValue(curTemp);

                tooltip += "

Crit: ";
                tooltip += QString::number((*temperatureProgressBarsIt)->maximum());
                tooltip += "
Max: ";
                tooltip += QString::number(int(maxTemp));
                tooltip += "
Cur: ";

                // Mark high temperature in the tooltip
                if (highTemperature)
                {
                    tooltip += "";
                    tooltip += QString::number((*temperatureProgressBarsIt)->value());
                    tooltip += " !";
                }
                else
                {
                    tooltip += QString::number((*temperatureProgressBarsIt)->value());
                }

                tooltip += "
Min: ";
                tooltip += QString::number((*temperatureProgressBarsIt)->minimum());
                (*temperatureProgressBarsIt)->setToolTip(tooltip);

                // Go to the next temperature progress bar
                ++temperatureProgressBarsIt;
            }
        }
    }

    update();
}

void LXQtSensors::warningAboutHighTemperature()
{
    // Iterator for temperature progress bars
    QSet<ProgressBar*>::iterator temperatureProgressBarsIt =
        mHighTemperatureProgressBars.begin();

    int curValue;
    int maxValue;

    for (; temperatureProgressBarsIt != mHighTemperatureProgressBars.end();
         ++temperatureProgressBarsIt)
    {
        curValue = (*temperatureProgressBarsIt)->value();
        maxValue = (*temperatureProgressBarsIt)->maximum();

        if (maxValue > curValue)
        {
            (*temperatureProgressBarsIt)->setValue(maxValue);
        }
        else
        {
            (*temperatureProgressBarsIt)->setValue((*temperatureProgressBarsIt)->minimum());
        }

    }
    update();
}

void LXQtSensors::settingsChanged()
{
    mUpdateSensorReadingsTimer.setInterval(mSettings->value("updateInterval").toInt() * 1000);

    // Iterator for temperature progress bars
    QList<ProgressBar*>::iterator temperatureProgressBarsIt =
        mTemperatureProgressBars.begin();

    mSettings->beginGroup("chips");

    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        mSettings->beginGroup(mDetectedChips[i].getName());
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                mSettings->beginGroup(features[j].getLabel());

                if (mSettings->value("enabled").toBool())
                {
                    (*temperatureProgressBarsIt)->show();
                }
                else
                {
                    (*temperatureProgressBarsIt)->hide();
                }

                QPalette pal = (*temperatureProgressBarsIt)->palette();
                QColor color(mSettings->value("color").toString());
                pal.setColor(QPalette::Active, QPalette::Highlight, color);
                pal.setColor(QPalette::Inactive, QPalette::Highlight, color);
                (*temperatureProgressBarsIt)->setPalette(pal);

                mSettings->endGroup();

                // Go to the next temperature progress bar
                ++temperatureProgressBarsIt;
            }
        }

        mSettings->endGroup();
    }

    mSettings->endGroup();

    if (mSettings->value("warningAboutHighTemperature").toBool())
    {
        // Update sensors readings to get the list of high temperature progress bars
        updateSensorReadings();

        if (!mWarningAboutHighTemperatureTimer.isActive())
            mWarningAboutHighTemperatureTimer.start();
    }
    else if (mWarningAboutHighTemperatureTimer.isActive())
    {
        mWarningAboutHighTemperatureTimer.stop();

        // Update sensors readings to set progress bar values to "normal" height
        updateSensorReadings();
    }

    realign();
    update();
}

void LXQtSensors::realign()
{
    // Default values for LXQtPanel::PositionBottom or LXQtPanel::PositionTop
    Qt::Orientation cur_orient = Qt::Vertical;
    Qt::LayoutDirection cur_layout_dir = Qt::LeftToRight;

    if (mPlugin->panel()->isHorizontal())
    {
        mLayout->setDirection(QBoxLayout::LeftToRight);
    }
    else
    {
        mLayout->setDirection(QBoxLayout::TopToBottom);
    }

    switch (mPlugin->panel()->position())
    {
    case ILXQtPanel::PositionLeft:
        cur_orient = Qt::Horizontal;
        break;

    case ILXQtPanel::PositionRight:
        cur_orient = Qt::Horizontal;
        cur_layout_dir = Qt::RightToLeft;
        break;

    default:
        break;
    }

    for (int i = 0; i < mTemperatureProgressBars.size(); ++i)
    {
        mTemperatureProgressBars[i]->setOrientation(cur_orient);
        mTemperatureProgressBars[i]->setLayoutDirection(cur_layout_dir);

        if (mPlugin->panel()->isHorizontal())
        {
            mTemperatureProgressBars[i]->setFixedWidth(mPlugin->settings()->value("tempBarWidth").toInt());
            mTemperatureProgressBars[i]->setFixedHeight(QWIDGETSIZE_MAX);
        }
        else
        {
            mTemperatureProgressBars[i]->setFixedHeight(mPlugin->settings()->value("tempBarWidth").toInt());
            mTemperatureProgressBars[i]->setFixedWidth(QWIDGETSIZE_MAX);
        }
    }
}

double LXQtSensors::celsiusToFahrenheit(double celsius)
{
    // Fahrenheit = 32 * (9/5) * Celsius
    return 32 + 1.8 * celsius;
}

void LXQtSensors::initDefaultSettings()
{
    if (!mSettings->contains("updateInterval"))
    {
        mSettings->setValue("updateInterval", 1);
    }

    if (!mSettings->contains("tempBarWidth"))
    {
        mSettings->setValue("tempBarWidth", 8);
    }

    if (!mSettings->contains("useFahrenheitScale"))
    {
        mSettings->setValue("useFahrenheitScale", false);
    }

    mSettings->beginGroup("chips");

    // Initialize default sensors settings
    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        mSettings->beginGroup(mDetectedChips[i].getName());
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                mSettings->beginGroup(features[j].getLabel());
                if (!mSettings->contains("enabled"))
                {
                    mSettings->setValue("enabled", true);
                }

                if (!mSettings->contains("color"))
                {
                    // This is the default from QtDesigner
                    mSettings->setValue("color", QColor(qRgb(98, 140, 178)).name());
                }
                mSettings->endGroup();
            }
        }
        mSettings->endGroup();
    }

    mSettings->endGroup();

    if (!mSettings->contains("warningAboutHighTemperature"))
    {
        mSettings->setValue("warningAboutHighTemperature", true);
    }
}

ProgressBar::ProgressBar(QWidget *parent):
    QProgressBar(parent)
{
}

QSize ProgressBar::sizeHint() const
{
    return QSize(20, 20);
}
<commit_msg>sensors: Add minor code optimization<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Łukasz Twarduś <ltwardus@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.

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

#include "lxqtsensors.h"
#include "lxqtsensorsconfiguration.h"
#include "../panel/ilxqtpanelplugin.h"
#include "../panel/ilxqtpanel.h"
#include <QBoxLayout>
#include <QDebug>
#include <QMessageBox>
#include <QPalette>

LXQtSensors::LXQtSensors(ILXQtPanelPlugin *plugin, QWidget* parent):
    QFrame(parent),
    mPlugin(plugin),
    mSettings(plugin->settings())
{

    mDetectedChips = mSensors.getDetectedChips();

    /**
     * We have all needed data to initialize default settings, we have to do it here as later
     * we are using them.
     */
    initDefaultSettings();

    // Add GUI elements
    ProgressBar* pg = NULL;

    mLayout = new QBoxLayout(QBoxLayout::LeftToRight, this);
    mLayout->setSpacing(0);
    mLayout->setContentsMargins(0, 0, 0, 0);

    QString chipFeatureLabel;

    mSettings->beginGroup("chips");

    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        mSettings->beginGroup(mDetectedChips[i].getName());
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                chipFeatureLabel = features[j].getLabel();
                mSettings->beginGroup(chipFeatureLabel);

                pg = new ProgressBar(this);
                pg->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

                // Hide progress bar if it is not enabled
                if (!mSettings->value("enabled").toBool())
                {
                    pg->hide();
                }

                pg->setToolTip(chipFeatureLabel);
                pg->setTextVisible(false);

                QPalette pal = pg->palette();
                QColor color(mSettings->value("color").toString());
                pal.setColor(QPalette::Active, QPalette::Highlight, color);
                pal.setColor(QPalette::Inactive, QPalette::Highlight, color);
                pg->setPalette(pal);

                mTemperatureProgressBars.push_back(pg);
                mLayout->addWidget(pg);

                mSettings->endGroup();
            }
        }
        mSettings->endGroup();
    }

    mSettings->endGroup();

    // Fit plugin to current panel
    realign();

    // Updated sensors readings to display actual values at start
    updateSensorReadings();

    // Run timer that will be updating sensor readings
    connect(&mUpdateSensorReadingsTimer, SIGNAL(timeout()), this, SLOT(updateSensorReadings()));
    mUpdateSensorReadingsTimer.start(mSettings->value("updateInterval").toInt() * 1000);

    // Run timer that will be showin warning
    mWarningAboutHighTemperatureTimer.setInterval(500);
    connect(&mWarningAboutHighTemperatureTimer, SIGNAL(timeout()), this,
            SLOT(warningAboutHighTemperature()));
    if (mSettings->value("warningAboutHighTemperature").toBool())
    {
        mWarningAboutHighTemperatureTimer.start();
    }
}

LXQtSensors::~LXQtSensors()
{
}

void LXQtSensors::updateSensorReadings()
{
    QString tooltip;

    double critTemp = 0;
    double maxTemp = 0;
    double minTemp = 0;
    double curTemp = 0;
    bool highTemperature = false;

    // Iterator for temperature progress bars
    QList<ProgressBar*>::iterator temperatureProgressBarsIt =
        mTemperatureProgressBars.begin();
    const bool use_fahrenheit = mSettings->value("useFahrenheitScale").toBool();
    const bool warn_high = mSettings->value("warningAboutHighTemperature").toBool();

    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                tooltip = features[j].getLabel() + " (" + QChar(0x00B0);

                critTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_CRIT);
                maxTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_MAX);
                minTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_MIN);
                curTemp = features[j].getValue(SENSORS_SUBFEATURE_TEMP_INPUT);

                // Check if temperature is too high
                if (curTemp >= maxTemp)
                {
                    if (warn_high)
                    {
                        // Add current progress bar to the "warning container"
                        mHighTemperatureProgressBars.insert(*temperatureProgressBarsIt);
                    }

                    highTemperature = true;
                }
                else
                {
                    mHighTemperatureProgressBars.remove(*temperatureProgressBarsIt);

                    highTemperature = false;
                }

                if (use_fahrenheit)
                {
                    critTemp = celsiusToFahrenheit(critTemp);
                    maxTemp = celsiusToFahrenheit(maxTemp);
                    minTemp = celsiusToFahrenheit(minTemp);
                    curTemp = celsiusToFahrenheit(curTemp);

                    tooltip += "F)";
                }
                else
                {
                    tooltip += "C)";
                }

                // Set maximum temperature
                (*temperatureProgressBarsIt)->setMaximum(critTemp);
                // Set minimum temperature
                (*temperatureProgressBarsIt)->setMinimum(minTemp);
                // Set current temperature
                (*temperatureProgressBarsIt)->setValue(curTemp);

                tooltip += "

Crit: ";
                tooltip += QString::number((*temperatureProgressBarsIt)->maximum());
                tooltip += "
Max: ";
                tooltip += QString::number(int(maxTemp));
                tooltip += "
Cur: ";

                // Mark high temperature in the tooltip
                if (highTemperature)
                {
                    tooltip += "";
                    tooltip += QString::number((*temperatureProgressBarsIt)->value());
                    tooltip += " !";
                }
                else
                {
                    tooltip += QString::number((*temperatureProgressBarsIt)->value());
                }

                tooltip += "
Min: ";
                tooltip += QString::number((*temperatureProgressBarsIt)->minimum());
                (*temperatureProgressBarsIt)->setToolTip(tooltip);

                // Go to the next temperature progress bar
                ++temperatureProgressBarsIt;
            }
        }
    }

    update();
}

void LXQtSensors::warningAboutHighTemperature()
{
    // Iterator for temperature progress bars
    QSet<ProgressBar*>::iterator temperatureProgressBarsIt =
        mHighTemperatureProgressBars.begin();

    int curValue;
    int maxValue;

    for (; temperatureProgressBarsIt != mHighTemperatureProgressBars.end();
         ++temperatureProgressBarsIt)
    {
        curValue = (*temperatureProgressBarsIt)->value();
        maxValue = (*temperatureProgressBarsIt)->maximum();

        if (maxValue > curValue)
        {
            (*temperatureProgressBarsIt)->setValue(maxValue);
        }
        else
        {
            (*temperatureProgressBarsIt)->setValue((*temperatureProgressBarsIt)->minimum());
        }

    }
    update();
}

void LXQtSensors::settingsChanged()
{
    mUpdateSensorReadingsTimer.setInterval(mSettings->value("updateInterval").toInt() * 1000);

    // Iterator for temperature progress bars
    QList<ProgressBar*>::iterator temperatureProgressBarsIt =
        mTemperatureProgressBars.begin();

    mSettings->beginGroup("chips");

    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        mSettings->beginGroup(mDetectedChips[i].getName());
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                mSettings->beginGroup(features[j].getLabel());

                if (mSettings->value("enabled").toBool())
                {
                    (*temperatureProgressBarsIt)->show();
                }
                else
                {
                    (*temperatureProgressBarsIt)->hide();
                }

                QPalette pal = (*temperatureProgressBarsIt)->palette();
                QColor color(mSettings->value("color").toString());
                pal.setColor(QPalette::Active, QPalette::Highlight, color);
                pal.setColor(QPalette::Inactive, QPalette::Highlight, color);
                (*temperatureProgressBarsIt)->setPalette(pal);

                mSettings->endGroup();

                // Go to the next temperature progress bar
                ++temperatureProgressBarsIt;
            }
        }

        mSettings->endGroup();
    }

    mSettings->endGroup();

    if (mSettings->value("warningAboutHighTemperature").toBool())
    {
        // Update sensors readings to get the list of high temperature progress bars
        updateSensorReadings();

        if (!mWarningAboutHighTemperatureTimer.isActive())
            mWarningAboutHighTemperatureTimer.start();
    }
    else if (mWarningAboutHighTemperatureTimer.isActive())
    {
        mWarningAboutHighTemperatureTimer.stop();

        // Update sensors readings to set progress bar values to "normal" height
        updateSensorReadings();
    }

    realign();
    update();
}

void LXQtSensors::realign()
{
    // Default values for LXQtPanel::PositionBottom or LXQtPanel::PositionTop
    Qt::Orientation cur_orient = Qt::Vertical;
    Qt::LayoutDirection cur_layout_dir = Qt::LeftToRight;

    if (mPlugin->panel()->isHorizontal())
    {
        mLayout->setDirection(QBoxLayout::LeftToRight);
    }
    else
    {
        mLayout->setDirection(QBoxLayout::TopToBottom);
    }

    switch (mPlugin->panel()->position())
    {
    case ILXQtPanel::PositionLeft:
        cur_orient = Qt::Horizontal;
        break;

    case ILXQtPanel::PositionRight:
        cur_orient = Qt::Horizontal;
        cur_layout_dir = Qt::RightToLeft;
        break;

    default:
        break;
    }

    for (int i = 0; i < mTemperatureProgressBars.size(); ++i)
    {
        mTemperatureProgressBars[i]->setOrientation(cur_orient);
        mTemperatureProgressBars[i]->setLayoutDirection(cur_layout_dir);

        if (mPlugin->panel()->isHorizontal())
        {
            mTemperatureProgressBars[i]->setFixedWidth(mPlugin->settings()->value("tempBarWidth").toInt());
            mTemperatureProgressBars[i]->setFixedHeight(QWIDGETSIZE_MAX);
        }
        else
        {
            mTemperatureProgressBars[i]->setFixedHeight(mPlugin->settings()->value("tempBarWidth").toInt());
            mTemperatureProgressBars[i]->setFixedWidth(QWIDGETSIZE_MAX);
        }
    }
}

double LXQtSensors::celsiusToFahrenheit(double celsius)
{
    // Fahrenheit = 32 * (9/5) * Celsius
    return 32 + 1.8 * celsius;
}

void LXQtSensors::initDefaultSettings()
{
    if (!mSettings->contains("updateInterval"))
    {
        mSettings->setValue("updateInterval", 1);
    }

    if (!mSettings->contains("tempBarWidth"))
    {
        mSettings->setValue("tempBarWidth", 8);
    }

    if (!mSettings->contains("useFahrenheitScale"))
    {
        mSettings->setValue("useFahrenheitScale", false);
    }

    mSettings->beginGroup("chips");

    // Initialize default sensors settings
    for (int i = 0; i < mDetectedChips.size(); ++i)
    {
        mSettings->beginGroup(mDetectedChips[i].getName());
        const QList<Feature>& features = mDetectedChips[i].getFeatures();

        for (int j = 0; j < features.size(); ++j)
        {
            if (features[j].getType() == SENSORS_FEATURE_TEMP)
            {
                mSettings->beginGroup(features[j].getLabel());
                if (!mSettings->contains("enabled"))
                {
                    mSettings->setValue("enabled", true);
                }

                if (!mSettings->contains("color"))
                {
                    // This is the default from QtDesigner
                    mSettings->setValue("color", QColor(qRgb(98, 140, 178)).name());
                }
                mSettings->endGroup();
            }
        }
        mSettings->endGroup();
    }

    mSettings->endGroup();

    if (!mSettings->contains("warningAboutHighTemperature"))
    {
        mSettings->setValue("warningAboutHighTemperature", true);
    }
}

ProgressBar::ProgressBar(QWidget *parent):
    QProgressBar(parent)
{
}

QSize ProgressBar::sizeHint() const
{
    return QSize(20, 20);
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "test/core/bad_client/bad_client.h"

#include <stdio.h>

#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>

#include "src/core/ext/filters/http/server/http_server_filter.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/endpoint_pair.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/murmur_hash.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/server.h"
#include "test/core/end2end/cq_verifier.h"

#define MIN_HTTP2_FRAME_SIZE 9

/* Args to provide to thread running server side validator */
typedef struct {
  grpc_server* server;
  grpc_completion_queue* cq;
  grpc_bad_client_server_side_validator validator;
  void* registered_method;
  gpr_event done_thd;
} thd_args;

/* Run the server side validator and set done_thd once done */
static void thd_func(void* arg) {
  thd_args* a = (thd_args*)arg;
  if (a->validator != nullptr) {
    a->validator(a->server, a->cq, a->registered_method);
  }
  gpr_event_set(&a->done_thd, (void*)1);
}

/* Sets the done_write event */
static void set_done_write(void* arg, grpc_error* error) {
  gpr_log(GPR_INFO, "done writing");
  gpr_event* done_write = (gpr_event*)arg;
  gpr_event_set(done_write, (void*)1);
}

static void server_setup_transport(void* ts, grpc_transport* transport) {
  thd_args* a = (thd_args*)ts;
  grpc_core::ExecCtx exec_ctx;
  grpc_server_setup_transport(a->server, transport, nullptr,
                              grpc_server_get_channel_args(a->server));
}

/* Sets the read_done event */
static void set_read_done(void* arg, grpc_error* error) {
  gpr_event* read_done = (gpr_event*)arg;
  gpr_event_set(read_done, (void*)1);
}

/* Runs client side validator */
void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags,
                                    grpc_endpoint_pair* sfd,
                                    grpc_completion_queue* client_cq) {
  char* hex;
  gpr_event done_write;
  if (arg->client_payload_length < 4 * 1024) {
    hex = gpr_dump(arg->client_payload, arg->client_payload_length,
                   GPR_DUMP_HEX | GPR_DUMP_ASCII);
    /* Add a debug log */
    gpr_log(GPR_INFO, "TEST: %s", hex);
    gpr_free(hex);
  } else {
    gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)",
            arg->client_payload_length);
  }

  grpc_slice slice = grpc_slice_from_copied_buffer(arg->client_payload,
                                                   arg->client_payload_length);
  grpc_slice_buffer outgoing;
  grpc_closure done_write_closure;
  gpr_event_init(&done_write);

  grpc_slice_buffer_init(&outgoing);
  grpc_slice_buffer_add(&outgoing, slice);
  GRPC_CLOSURE_INIT(&done_write_closure, set_done_write, &done_write,
                    grpc_schedule_on_exec_ctx);

  /* Write data */
  grpc_endpoint_write(sfd->client, &outgoing, &done_write_closure);
  grpc_core::ExecCtx::Get()->Flush();

  /* Await completion, unless the request is large and write may not finish
   * before the peer shuts down. */
  if (!(flags & GRPC_BAD_CLIENT_LARGE_REQUEST)) {
    GPR_ASSERT(
        gpr_event_wait(&done_write, grpc_timeout_seconds_to_deadline(5)));
  }

  if (flags & GRPC_BAD_CLIENT_DISCONNECT) {
    grpc_endpoint_shutdown(
        sfd->client, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Disconnect"));
    grpc_endpoint_destroy(sfd->client);
    grpc_core::ExecCtx::Get()->Flush();
    sfd->client = nullptr;
  }

  if (sfd->client != nullptr) {
    /* Validate client stream, if requested. */
    if (arg->client_validator != nullptr) {
      gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
      grpc_slice_buffer incoming;
      grpc_slice_buffer_init(&incoming);
      /* We may need to do multiple reads to read the complete server
       * response. */
      while (true) {
        gpr_event read_done_event;
        gpr_event_init(&read_done_event);
        grpc_closure read_done_closure;
        GRPC_CLOSURE_INIT(&read_done_closure, set_read_done, &read_done_event,
                          grpc_schedule_on_exec_ctx);
        grpc_endpoint_read(sfd->client, &incoming, &read_done_closure);
        grpc_core::ExecCtx::Get()->Flush();
        do {
          GPR_ASSERT(gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0);
          /* Perform a cq next just to provide a thread that can read incoming
           bytes on the client fd */
          GPR_ASSERT(grpc_completion_queue_next(
                         client_cq, grpc_timeout_milliseconds_to_deadline(100),
                         nullptr)
                         .type == GRPC_QUEUE_TIMEOUT);
        } while (!gpr_event_get(&read_done_event));
        if (arg->client_validator(&incoming, arg->client_validator_arg)) break;
        gpr_log(GPR_INFO,
                "client validator failed; trying additional read "
                "in case we didn't get all the data");
      }
      grpc_slice_buffer_destroy_internal(&incoming);
    }
    grpc_core::ExecCtx::Get()->Flush();
  }
  GPR_ASSERT(gpr_event_wait(&done_write, grpc_timeout_seconds_to_deadline(1)));
  grpc_slice_buffer_destroy_internal(&outgoing);
  grpc_core::ExecCtx::Get()->Flush();
}

void grpc_run_bad_client_test(
    grpc_bad_client_server_side_validator server_validator,
    grpc_bad_client_arg args[], int num_args, uint32_t flags) {
  grpc_endpoint_pair sfd;
  thd_args a;
  grpc_transport* transport;
  grpc_core::ExecCtx exec_ctx;
  grpc_completion_queue* shutdown_cq;
  grpc_completion_queue* client_cq;

  /* Init grpc */
  grpc_init();

  /* Create endpoints */
  sfd = grpc_iomgr_create_endpoint_pair("fixture", nullptr);

  /* Create server, completion events */
  a.server = grpc_server_create(nullptr, nullptr);
  a.cq = grpc_completion_queue_create_for_next(nullptr);
  client_cq = grpc_completion_queue_create_for_next(nullptr);

  grpc_server_register_completion_queue(a.server, a.cq, nullptr);
  a.registered_method =
      grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD,
                                  GRPC_BAD_CLIENT_REGISTERED_HOST,
                                  GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
  grpc_server_start(a.server);
  transport = grpc_create_chttp2_transport(nullptr, sfd.server, false);
  server_setup_transport(&a, transport);
  grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);

  /* Bind fds to pollsets */
  grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(client_cq));
  grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq));

  /* Check a ground truth */
  GPR_ASSERT(grpc_server_has_open_connections(a.server));

  gpr_thd_id id;
  gpr_event_init(&a.done_thd);
  a.validator = server_validator;
  /* Start validator */
  gpr_thd_new(&id, "grpc_bad_client", thd_func, &a, nullptr);
  for (int i = 0; i < num_args; i++) {
    grpc_run_client_side_validator(&args[i], flags, &sfd, client_cq);
  }
  /* Wait for server thread to finish */
  GPR_ASSERT(gpr_event_wait(&a.done_thd, grpc_timeout_seconds_to_deadline(1)));

  /* Shutdown. */
  if (sfd.client != nullptr) {
    grpc_endpoint_shutdown(
        sfd.client, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
    grpc_endpoint_destroy(sfd.client);
    grpc_core::ExecCtx::Get()->Flush();
  }

  shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
  grpc_server_shutdown_and_notify(a.server, shutdown_cq, nullptr);
  GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, nullptr,
                                         grpc_timeout_seconds_to_deadline(1),
                                         nullptr)
                 .type == GRPC_OP_COMPLETE);
  grpc_completion_queue_destroy(shutdown_cq);
  grpc_server_destroy(a.server);
  grpc_completion_queue_destroy(a.cq);
  grpc_completion_queue_destroy(client_cq);
  grpc_shutdown();
}

bool client_connection_preface_validator(grpc_slice_buffer* incoming,
                                         void* arg) {
  if (incoming->count < 1) {
    return false;
  }
  grpc_slice slice = incoming->slices[0];
  /* There should be atleast a settings frame present */
  if (GRPC_SLICE_LENGTH(slice) < MIN_HTTP2_FRAME_SIZE) {
    return false;
  }
  const uint8_t* p = GRPC_SLICE_START_PTR(slice);
  /* Check the frame type (SETTINGS) */
  if (*(p + 3) != 4) {
    return false;
  }
  return true;
}

/* connection preface and settings frame to be sent by the client */
#define CONNECTION_PREFACE_FROM_CLIENT \
  "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"   \
  "\x00\x00\x00\x04\x00\x00\x00\x00\x00"

grpc_bad_client_arg connection_preface_arg = {
    client_connection_preface_validator, nullptr,
    CONNECTION_PREFACE_FROM_CLIENT, sizeof(CONNECTION_PREFACE_FROM_CLIENT) - 1};

bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* arg) {
  // Get last frame from incoming slice buffer.
  grpc_slice_buffer last_frame_buffer;
  grpc_slice_buffer_init(&last_frame_buffer);
  grpc_slice_buffer_trim_end(incoming, 13, &last_frame_buffer);
  GPR_ASSERT(last_frame_buffer.count == 1);
  grpc_slice last_frame = last_frame_buffer.slices[0];

  const uint8_t* p = GRPC_SLICE_START_PTR(last_frame);
  bool success =
      // Length == 4
      *p++ != 0 || *p++ != 0 || *p++ != 4 ||
      // Frame type (RST_STREAM)
      *p++ != 3 ||
      // Flags
      *p++ != 0 ||
      // Stream ID.
      *p++ != 0 || *p++ != 0 || *p++ != 0 || *p++ != 1 ||
      // Payload (error code)
      *p++ == 0 || *p++ == 0 || *p++ == 0 || *p == 0 || *p == 11;

  if (!success) {
    gpr_log(GPR_INFO, "client expected RST_STREAM frame, not found");
  }

  grpc_slice_buffer_destroy(&last_frame_buffer);
  return success;
}

static void* tag(intptr_t t) { return (void*)t; }

void server_verifier_request_call(grpc_server* server,
                                  grpc_completion_queue* cq,
                                  void* registered_method) {
  grpc_call_error error;
  grpc_call* s;
  grpc_call_details call_details;
  cq_verifier* cqv = cq_verifier_create(cq);
  grpc_metadata_array request_metadata_recv;

  grpc_call_details_init(&call_details);
  grpc_metadata_array_init(&request_metadata_recv);

  error = grpc_server_request_call(server, &s, &call_details,
                                   &request_metadata_recv, cq, cq, tag(101));
  GPR_ASSERT(GRPC_CALL_OK == error);
  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
  cq_verify(cqv);

  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));

  grpc_metadata_array_destroy(&request_metadata_recv);
  grpc_call_details_destroy(&call_details);
  grpc_call_unref(s);
  cq_verifier_destroy(cqv);
}
<commit_msg>remove unnecessary assert<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "test/core/bad_client/bad_client.h"

#include <stdio.h>

#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>

#include "src/core/ext/filters/http/server/http_server_filter.h"
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/endpoint_pair.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/murmur_hash.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/server.h"
#include "test/core/end2end/cq_verifier.h"

#define MIN_HTTP2_FRAME_SIZE 9

/* Args to provide to thread running server side validator */
typedef struct {
  grpc_server* server;
  grpc_completion_queue* cq;
  grpc_bad_client_server_side_validator validator;
  void* registered_method;
  gpr_event done_thd;
} thd_args;

/* Run the server side validator and set done_thd once done */
static void thd_func(void* arg) {
  thd_args* a = (thd_args*)arg;
  if (a->validator != nullptr) {
    a->validator(a->server, a->cq, a->registered_method);
  }
  gpr_event_set(&a->done_thd, (void*)1);
}

/* Sets the done_write event */
static void set_done_write(void* arg, grpc_error* error) {
  gpr_event* done_write = (gpr_event*)arg;
  gpr_event_set(done_write, (void*)1);
}

static void server_setup_transport(void* ts, grpc_transport* transport) {
  thd_args* a = (thd_args*)ts;
  grpc_core::ExecCtx exec_ctx;
  grpc_server_setup_transport(a->server, transport, nullptr,
                              grpc_server_get_channel_args(a->server));
}

/* Sets the read_done event */
static void set_read_done(void* arg, grpc_error* error) {
  gpr_event* read_done = (gpr_event*)arg;
  gpr_event_set(read_done, (void*)1);
}

/* Runs client side validator */
void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags,
                                    grpc_endpoint_pair* sfd,
                                    grpc_completion_queue* client_cq) {
  char* hex;
  gpr_event done_write;
  if (arg->client_payload_length < 4 * 1024) {
    hex = gpr_dump(arg->client_payload, arg->client_payload_length,
                   GPR_DUMP_HEX | GPR_DUMP_ASCII);
    /* Add a debug log */
    gpr_log(GPR_INFO, "TEST: %s", hex);
    gpr_free(hex);
  } else {
    gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)",
            arg->client_payload_length);
  }

  grpc_slice slice = grpc_slice_from_copied_buffer(arg->client_payload,
                                                   arg->client_payload_length);
  grpc_slice_buffer outgoing;
  grpc_closure done_write_closure;
  gpr_event_init(&done_write);

  grpc_slice_buffer_init(&outgoing);
  grpc_slice_buffer_add(&outgoing, slice);
  GRPC_CLOSURE_INIT(&done_write_closure, set_done_write, &done_write,
                    grpc_schedule_on_exec_ctx);

  /* Write data */
  grpc_endpoint_write(sfd->client, &outgoing, &done_write_closure);
  grpc_core::ExecCtx::Get()->Flush();

  /* Await completion, unless the request is large and write may not finish
   * before the peer shuts down. */
  if (!(flags & GRPC_BAD_CLIENT_LARGE_REQUEST)) {
    GPR_ASSERT(
        gpr_event_wait(&done_write, grpc_timeout_seconds_to_deadline(5)));
  }

  if (flags & GRPC_BAD_CLIENT_DISCONNECT) {
    grpc_endpoint_shutdown(
        sfd->client, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Forced Disconnect"));
    grpc_endpoint_destroy(sfd->client);
    grpc_core::ExecCtx::Get()->Flush();
    sfd->client = nullptr;
  }

  if (sfd->client != nullptr) {
    /* Validate client stream, if requested. */
    if (arg->client_validator != nullptr) {
      gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
      grpc_slice_buffer incoming;
      grpc_slice_buffer_init(&incoming);
      /* We may need to do multiple reads to read the complete server
       * response. */
      while (true) {
        gpr_event read_done_event;
        gpr_event_init(&read_done_event);
        grpc_closure read_done_closure;
        GRPC_CLOSURE_INIT(&read_done_closure, set_read_done, &read_done_event,
                          grpc_schedule_on_exec_ctx);
        grpc_endpoint_read(sfd->client, &incoming, &read_done_closure);
        grpc_core::ExecCtx::Get()->Flush();
        do {
          GPR_ASSERT(gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) > 0);
          /* Perform a cq next just to provide a thread that can read incoming
           bytes on the client fd */
          GPR_ASSERT(grpc_completion_queue_next(
                         client_cq, grpc_timeout_milliseconds_to_deadline(100),
                         nullptr)
                         .type == GRPC_QUEUE_TIMEOUT);
        } while (!gpr_event_get(&read_done_event));
        if (arg->client_validator(&incoming, arg->client_validator_arg)) break;
        gpr_log(GPR_INFO,
                "client validator failed; trying additional read "
                "in case we didn't get all the data");
      }
      grpc_slice_buffer_destroy_internal(&incoming);
    }
    grpc_core::ExecCtx::Get()->Flush();
  }
  grpc_slice_buffer_destroy_internal(&outgoing);
  grpc_core::ExecCtx::Get()->Flush();
}

void grpc_run_bad_client_test(
    grpc_bad_client_server_side_validator server_validator,
    grpc_bad_client_arg args[], int num_args, uint32_t flags) {
  grpc_endpoint_pair sfd;
  thd_args a;
  grpc_transport* transport;
  grpc_core::ExecCtx exec_ctx;
  grpc_completion_queue* shutdown_cq;
  grpc_completion_queue* client_cq;

  /* Init grpc */
  grpc_init();

  /* Create endpoints */
  sfd = grpc_iomgr_create_endpoint_pair("fixture", nullptr);

  /* Create server, completion events */
  a.server = grpc_server_create(nullptr, nullptr);
  a.cq = grpc_completion_queue_create_for_next(nullptr);
  client_cq = grpc_completion_queue_create_for_next(nullptr);

  grpc_server_register_completion_queue(a.server, a.cq, nullptr);
  a.registered_method =
      grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD,
                                  GRPC_BAD_CLIENT_REGISTERED_HOST,
                                  GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
  grpc_server_start(a.server);
  transport = grpc_create_chttp2_transport(nullptr, sfd.server, false);
  server_setup_transport(&a, transport);
  grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);

  /* Bind fds to pollsets */
  grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(client_cq));
  grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq));

  /* Check a ground truth */
  GPR_ASSERT(grpc_server_has_open_connections(a.server));

  gpr_thd_id id;
  gpr_event_init(&a.done_thd);
  a.validator = server_validator;
  /* Start validator */
  gpr_thd_new(&id, "grpc_bad_client", thd_func, &a, nullptr);
  for (int i = 0; i < num_args; i++) {
    grpc_run_client_side_validator(&args[i], flags, &sfd, client_cq);
  }
  /* Wait for server thread to finish */
  GPR_ASSERT(gpr_event_wait(&a.done_thd, grpc_timeout_seconds_to_deadline(1)));

  /* Shutdown. */
  if (sfd.client != nullptr) {
    grpc_endpoint_shutdown(
        sfd.client, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown"));
    grpc_endpoint_destroy(sfd.client);
    grpc_core::ExecCtx::Get()->Flush();
  }

  shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
  grpc_server_shutdown_and_notify(a.server, shutdown_cq, nullptr);
  GPR_ASSERT(grpc_completion_queue_pluck(shutdown_cq, nullptr,
                                         grpc_timeout_seconds_to_deadline(1),
                                         nullptr)
                 .type == GRPC_OP_COMPLETE);
  grpc_completion_queue_destroy(shutdown_cq);
  grpc_server_destroy(a.server);
  grpc_completion_queue_destroy(a.cq);
  grpc_completion_queue_destroy(client_cq);
  grpc_shutdown();
}

bool client_connection_preface_validator(grpc_slice_buffer* incoming,
                                         void* arg) {
  if (incoming->count < 1) {
    return false;
  }
  grpc_slice slice = incoming->slices[0];
  /* There should be atleast a settings frame present */
  if (GRPC_SLICE_LENGTH(slice) < MIN_HTTP2_FRAME_SIZE) {
    return false;
  }
  const uint8_t* p = GRPC_SLICE_START_PTR(slice);
  /* Check the frame type (SETTINGS) */
  if (*(p + 3) != 4) {
    return false;
  }
  return true;
}

/* connection preface and settings frame to be sent by the client */
#define CONNECTION_PREFACE_FROM_CLIENT \
  "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"   \
  "\x00\x00\x00\x04\x00\x00\x00\x00\x00"

grpc_bad_client_arg connection_preface_arg = {
    client_connection_preface_validator, nullptr,
    CONNECTION_PREFACE_FROM_CLIENT, sizeof(CONNECTION_PREFACE_FROM_CLIENT) - 1};

bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* arg) {
  // Get last frame from incoming slice buffer.
  grpc_slice_buffer last_frame_buffer;
  grpc_slice_buffer_init(&last_frame_buffer);
  grpc_slice_buffer_trim_end(incoming, 13, &last_frame_buffer);
  GPR_ASSERT(last_frame_buffer.count == 1);
  grpc_slice last_frame = last_frame_buffer.slices[0];

  const uint8_t* p = GRPC_SLICE_START_PTR(last_frame);
  bool success =
      // Length == 4
      *p++ != 0 || *p++ != 0 || *p++ != 4 ||
      // Frame type (RST_STREAM)
      *p++ != 3 ||
      // Flags
      *p++ != 0 ||
      // Stream ID.
      *p++ != 0 || *p++ != 0 || *p++ != 0 || *p++ != 1 ||
      // Payload (error code)
      *p++ == 0 || *p++ == 0 || *p++ == 0 || *p == 0 || *p == 11;

  if (!success) {
    gpr_log(GPR_INFO, "client expected RST_STREAM frame, not found");
  }

  grpc_slice_buffer_destroy(&last_frame_buffer);
  return success;
}

static void* tag(intptr_t t) { return (void*)t; }

void server_verifier_request_call(grpc_server* server,
                                  grpc_completion_queue* cq,
                                  void* registered_method) {
  grpc_call_error error;
  grpc_call* s;
  grpc_call_details call_details;
  cq_verifier* cqv = cq_verifier_create(cq);
  grpc_metadata_array request_metadata_recv;

  grpc_call_details_init(&call_details);
  grpc_metadata_array_init(&request_metadata_recv);

  error = grpc_server_request_call(server, &s, &call_details,
                                   &request_metadata_recv, cq, cq, tag(101));
  GPR_ASSERT(GRPC_CALL_OK == error);
  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
  cq_verify(cqv);

  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "localhost"));
  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo/bar"));

  grpc_metadata_array_destroy(&request_metadata_recv);
  grpc_call_details_destroy(&call_details);
  grpc_call_unref(s);
  cq_verifier_destroy(cqv);
}
<|endoftext|>