<commit_before>//=============================================================================================================
/**
* @file     test_spectral_connectivity.cpp
* @author   Daniel Strohmeier <daniel.strohmeier@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May, 2018
*
* @section  LICENSE
*
* Copyright (C) 2018, Daniel Strohmeier and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    The spectral connectivity test implementation
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <mne/mne.h>
#include <utils/ioutils.h>
#include "connectivity/metrics/coherence.h"
#include "connectivity/metrics/imagcoherence.h"
#include "connectivity/metrics/phaselockingvalue.h"
#include "connectivity/metrics/phaselagindex.h"
#include "connectivity/metrics/unbiasedsquaredphaselagindex.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// Eigen INCLUDES
//=============================================================================================================

#include <Eigen/Core>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace Eigen;
using namespace CONNECTIVITYLIB;
using namespace UTILSLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestSpectralConnectivity
*
* @brief The TestSpectralConnectivity class provides spectral connectivity tests
*
*/
class TestSpectralConnectivity: public QObject
{
    Q_OBJECT

public:
    TestSpectralConnectivity();

private slots:
    void initTestCase();
    void spectralConnectivityCoherence();
    void spectralConnectivityImagCoherence();
    void spectralConnectivityPLV();
    void spectralConnectivityPLI();
    void spectralConnectivityPLI2();
    void spectralConnectivityWPLI();
    void spectralConnectivityWPLI2();
    void cleanupTestCase();

private:
    void compareConnectivity();
    double epsilon;
    RowVectorXd m_ConnectivityOutput;
    RowVectorXd m_RefConnectivityOutput;
};

//*************************************************************************************************************

TestSpectralConnectivity::TestSpectralConnectivity()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestSpectralConnectivity::TestSpectralConnectivity()
{

}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> Coh = Coherence::computeCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = Coh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivity/ref_spectral_connectivity_coh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityImagCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> ImagCoh = ImagCoherence::computeImagCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = ImagCoh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_icoh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityPLV()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> PLV = PhaseLockingValue::computePLV(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = PLV.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_plv.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityPLI()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> PLI = PhaseLagIndex::computePLI(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = PLI.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_pli.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityPLI2()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> PLI2 = UnbiasedSquaredPhaseLagIndex::computeUnbiasedSquaredPLI(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = PLI2.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_pli.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::compareConnectivity()
{
    //*********************************************************************************************************
    // Compare Spectral Connectvitity Result to MNE-PYTHON
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compare Spectral Connectivities >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    QVERIFY( m_ConnectivityOutput.cols() == m_RefConnectivityOutput.cols() );
    for (int i = 0; i < m_ConnectivityOutput.cols(); ++i)
    {
        QVERIFY( (m_ConnectivityOutput(i) - m_RefConnectivityOutput(i)) / m_RefConnectivityOutput(i) < epsilon );
    }

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compare Spectral Connectivities Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

//*************************************************************************************************************

void TestSpectralConnectivity::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestSpectralConnectivity)
<commit_msg>test wpli<commit_after>//=============================================================================================================
/**
* @file     test_spectral_connectivity.cpp
* @author   Daniel Strohmeier <daniel.strohmeier@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     May, 2018
*
* @section  LICENSE
*
* Copyright (C) 2018, Daniel Strohmeier and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    The spectral connectivity test implementation
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <mne/mne.h>
#include <utils/ioutils.h>
#include "connectivity/metrics/coherence.h"
#include "connectivity/metrics/imagcoherence.h"
#include "connectivity/metrics/phaselockingvalue.h"
#include "connectivity/metrics/phaselagindex.h"
#include "connectivity/metrics/unbiasedsquaredphaselagindex.h"
#include "connectivity/metrics/weightedphaselagindex.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// Eigen INCLUDES
//=============================================================================================================

#include <Eigen/Core>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace Eigen;
using namespace CONNECTIVITYLIB;
using namespace UTILSLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestSpectralConnectivity
*
* @brief The TestSpectralConnectivity class provides spectral connectivity tests
*
*/
class TestSpectralConnectivity: public QObject
{
    Q_OBJECT

public:
    TestSpectralConnectivity();

private slots:
    void initTestCase();
    void spectralConnectivityCoherence();
    void spectralConnectivityImagCoherence();
    void spectralConnectivityPLV();
    void spectralConnectivityPLI();
    void spectralConnectivityPLI2();
    void spectralConnectivityWPLI();
    void spectralConnectivityWPLI2();
    void cleanupTestCase();

private:
    void compareConnectivity();
    double epsilon;
    RowVectorXd m_ConnectivityOutput;
    RowVectorXd m_RefConnectivityOutput;
};

//*************************************************************************************************************

TestSpectralConnectivity::TestSpectralConnectivity()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestSpectralConnectivity::TestSpectralConnectivity()
{

}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> Coh = Coherence::computeCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = Coh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivity/ref_spectral_connectivity_coh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityImagCoherence()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> ImagCoh = ImagCoherence::computeImagCoherence(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = ImagCoh.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_icoh.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityPLV()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> PLV = PhaseLockingValue::computePLV(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = PLV.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_plv.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityPLI()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> PLI = PhaseLagIndex::computePLI(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = PLI.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_pli.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityPLI2()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> PLI2 = UnbiasedSquaredPhaseLagIndex::computeUnbiasedSquaredPLI(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = PLI2.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_pli2.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::spectralConnectivityWPLI()
{
    //*********************************************************************************************************
    // Load Data
    //*********************************************************************************************************

    inputTrials = MatrixXd();
    QString dataFileName(QDir::currentPath()+"/mne-cpp-test-data/MEG/sample/data_spectral_connectivity.txt");
    IOUtils::read_eigen_matrix(inputTrials, dataFileName);
    int iNTrials = inputTrials.rows() / 2;
    int iNfft = inputTrials.cols();
    QString sWindowType = "hanning";

    QList<MatrixXd> matDataList;
    for (int i = 0; i < iNTrials; ++i)
    {
        matDataList.append(inputTrials.middleRows(i * 2, 2));
    }

    //*********************************************************************************************************
    // Compute Connectivity
    //*********************************************************************************************************

    QVector<MatrixXd> WPLI = WeightedPhaseLagIndex::computeWPLI(matDataList, iNfft, sWindowType);
    m_ConnectivityOutput = WPLI.at(0).row(1);

    //*********************************************************************************************************
    // Load MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    refConnectivity = MatrixXd();
    QString refFileName(QDir::currentPath()+"/mne-cpp-test-data/Result/Connectivty/ref_spectral_connectivity_wpli.txt");
    IOUtils::read_eigen_matrix(refConnectivity, refFileName);
    m_RefConnectivityOutput = refConnectivity.row(0);

    //*********************************************************************************************************
    // Compare Connectivity
    //*********************************************************************************************************

    compareConnectivity();
}

//*************************************************************************************************************

void TestSpectralConnectivity::compareConnectivity()
{
    //*********************************************************************************************************
    // Compare Spectral Connectvitity Result to MNE-PYTHON
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compare Spectral Connectivities >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    QVERIFY( m_ConnectivityOutput.cols() == m_RefConnectivityOutput.cols() );
    for (int i = 0; i < m_ConnectivityOutput.cols(); ++i)
    {
        QVERIFY( (m_ConnectivityOutput(i) - m_RefConnectivityOutput(i)) / m_RefConnectivityOutput(i) < epsilon );
    }

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compare Spectral Connectivities Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

//*************************************************************************************************************

void TestSpectralConnectivity::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestSpectralConnectivity)
<|endoftext|>


<commit_before>#include "../include/label.hpp"

label::label(const std::string &text, ALLEGRO_BITMAP *img, ALLEGRO_FONT *font, ALLEGRO_COLOR *color):
    color_(nullptr),
    font_(nullptr),
    img_(nullptr),
    text_(text),
    show_(true),
    x_(.0),
    y_(.0),
    w_(.0),
    h_(.0),
    text_x_(.0),
    text_y_(.0),
    img_x_(.0),
    img_y_(.0),
    text_w_(.0),
    text_h_(.0),
    img_w_(.0),
    img_h_(.0),
    v_aling_(dir::CENTER),
    h_aling_(dir::CENTER),
    mouse_over_(false),
    press_state_(0U),
    clicks_(0)
{
    setText(text);
    setFont(font);
    setColor(color);
    setImg(img);
}

label::label(ALLEGRO_BITMAP *img, ALLEGRO_FONT *font, ALLEGRO_COLOR *color):
    label("", img, font, color)
{}

label::label(const std::string &text, ALLEGRO_FONT *font, ALLEGRO_COLOR *color):
    label(text, nullptr, font, color)
{}

label::~label()
{}

void label::resize(const double x, const double y, const double w, const double h)
{
    double min_w = getMinWidth();
    double min_h = getMinHeight();

    x_ = x;
    y_ = y;
    w_ = w < min_w ? min_w : w;
    h_ = h < min_h ? min_h : h;

    switch (h_aling_)
    {
        case dir::LEFT:  img_x_ = 0;                     break;
        case dir::RIGHT: img_x_ = w_ - min_w;            break;
        default:         img_x_ = (w_-text_w_+img_w_)/2; break;
    }
    switch (v_aling_)
    {
        case dir::UP:   img_y_ =    (min_h-img_h_)/2; text_y_ =    (min_h-text_h_)/2; break;
        case dir::DOWN: img_y_ = h_-(min_h-img_h_)/2; text_y_ = h_-(min_h-text_h_)/2; break;
        default:        img_y_ =    (h_   -img_h_)/2; text_y_ =    (h_-   text_h_)/2; break;
    }

    text_x_ = img_x_ + img_w_;
}

void label::update()
{
    if (!show_)
    {
        mouse_over_ = false;
        press_state_ = 0;
        return;
    }

    mouse_over_ = mouse.insideBox(x_, y_, x_+w_, y_+h_);

    if (!mouse_over_)
        press_state_ = 0;

    else
    {
        if (press_state_==0 && !mouse.leftPressed())
            press_state_++;
        if (press_state_==1 &&  mouse.leftPressed())
            press_state_++;
        if (press_state_==2 && !mouse.leftPressed())
        {
            press_state_=0;
            clicks_++;
        }
    }
}

void label::draw()
{
    if (!show_) return;

    if (img_)
        al_draw_bitmap(img_, img_x_, img_y_, 0);
    if (font_ && color_)
        al_draw_text(font_, *color_, text_x_, text_y_, ALLEGRO_ALIGN_CENTER, text_.c_str());
}

bool label::mouseOver()
{
    return mouse_over_;
}

bool label::mouseClicked()
{
    if (!clicks_) return 0;
    return clicks_--;
}

void label::setText(const std::string &text)
{
    text_ = text;
    text_w_ = al_get_text_width(font_, text_.c_str());
    text_h_ = al_get_font_line_height(font_);
    resize(x_, y_, w_, h_);
}

void label::setImg(ALLEGRO_BITMAP *img)
{
    img_ = img;
    img_w_ = img ? al_get_bitmap_width(img_) : 0;
    img_h_ = img ? al_get_bitmap_height(img_) : 0;
    resize(x_, y_, w_, h_);
}

void label::setFont(ALLEGRO_FONT *font)
{
    font_ = font;
    text_w_ = font ? al_get_text_width(font_, text_.c_str()) : 0;
    text_h_ = font ? al_get_font_line_height(font_) : 0;
    resize(x_, y_, w_, h_);
}

void label::setColor(ALLEGRO_COLOR *color)
{
    color_ = color;
}

void label::setVerticalTextAling(const dir v_aling)
{
    v_aling_ = v_aling;
    resize(x_, y_, w_, h_);
}

void label::setHorizontalTextAling(const dir h_aling)
{
    h_aling_ = h_aling;
    resize(x_, y_, w_, h_);
}

double label::getMinWidth() const
{
    return text_w_ + img_w_;
}

double label::getMinHeight() const
{
    return text_h_ > img_h_ ? text_h_ : img_h_;
}

void label::show()
{
    show_ = true;
}

void label::hide()
{
    show_ = false;
}
<commit_msg>Fixed function name<commit_after>#include "../include/label.hpp"

label::label(const std::string &text, ALLEGRO_BITMAP *img, ALLEGRO_FONT *font, ALLEGRO_COLOR *color):
    color_(nullptr),
    font_(nullptr),
    img_(nullptr),
    text_(text),
    show_(true),
    x_(.0),
    y_(.0),
    w_(.0),
    h_(.0),
    text_x_(.0),
    text_y_(.0),
    img_x_(.0),
    img_y_(.0),
    text_w_(.0),
    text_h_(.0),
    img_w_(.0),
    img_h_(.0),
    v_aling_(dir::CENTER),
    h_aling_(dir::CENTER),
    mouse_over_(false),
    press_state_(0U),
    clicks_(0)
{
    setText(text);
    setFont(font);
    setColor(color);
    setImg(img);
}

label::label(ALLEGRO_BITMAP *img, ALLEGRO_FONT *font, ALLEGRO_COLOR *color):
    label("", img, font, color)
{}

label::label(const std::string &text, ALLEGRO_FONT *font, ALLEGRO_COLOR *color):
    label(text, nullptr, font, color)
{}

label::~label()
{}

void label::resize(const double x, const double y, const double w, const double h)
{
    double min_w = getMinWidth();
    double min_h = getMinHeight();

    x_ = x;
    y_ = y;
    w_ = w < min_w ? min_w : w;
    h_ = h < min_h ? min_h : h;

    switch (h_aling_)
    {
        case dir::LEFT:  img_x_ = 0;                     break;
        case dir::RIGHT: img_x_ = w_ - min_w;            break;
        default:         img_x_ = (w_-text_w_+img_w_)/2; break;
    }
    switch (v_aling_)
    {
        case dir::UP:   img_y_ =    (min_h-img_h_)/2; text_y_ =    (min_h-text_h_)/2; break;
        case dir::DOWN: img_y_ = h_-(min_h-img_h_)/2; text_y_ = h_-(min_h-text_h_)/2; break;
        default:        img_y_ =    (h_   -img_h_)/2; text_y_ =    (h_-   text_h_)/2; break;
    }

    text_x_ = img_x_ + img_w_;
}

void label::update()
{
    if (!show_)
    {
        mouse_over_ = false;
        press_state_ = 0;
        return;
    }

    mouse_over_ = mouse.insideBox(x_, y_, x_+w_, y_+h_);

    if (!mouse_over_)
        press_state_ = 0;

    else
    {
        if (press_state_==0 && !mouse.leftDown())
            press_state_++;
        if (press_state_==1 &&  mouse.leftDown())
            press_state_++;
        if (press_state_==2 && !mouse.leftDown())
        {
            press_state_=0;
            clicks_++;
        }
    }
}

void label::draw()
{
    if (!show_) return;

    if (img_)
        al_draw_bitmap(img_, img_x_, img_y_, 0);
    if (font_ && color_)
        al_draw_text(font_, *color_, text_x_, text_y_, ALLEGRO_ALIGN_CENTER, text_.c_str());
}

bool label::mouseOver()
{
    return mouse_over_;
}

bool label::mouseClicked()
{
    if (!clicks_) return 0;
    return clicks_--;
}

void label::setText(const std::string &text)
{
    text_ = text;
    text_w_ = al_get_text_width(font_, text_.c_str());
    text_h_ = al_get_font_line_height(font_);
    resize(x_, y_, w_, h_);
}

void label::setImg(ALLEGRO_BITMAP *img)
{
    img_ = img;
    img_w_ = img ? al_get_bitmap_width(img_) : 0;
    img_h_ = img ? al_get_bitmap_height(img_) : 0;
    resize(x_, y_, w_, h_);
}

void label::setFont(ALLEGRO_FONT *font)
{
    font_ = font;
    text_w_ = font ? al_get_text_width(font_, text_.c_str()) : 0;
    text_h_ = font ? al_get_font_line_height(font_) : 0;
    resize(x_, y_, w_, h_);
}

void label::setColor(ALLEGRO_COLOR *color)
{
    color_ = color;
}

void label::setVerticalTextAling(const dir v_aling)
{
    v_aling_ = v_aling;
    resize(x_, y_, w_, h_);
}

void label::setHorizontalTextAling(const dir h_aling)
{
    h_aling_ = h_aling;
    resize(x_, y_, w_, h_);
}

double label::getMinWidth() const
{
    return text_w_ + img_w_;
}

double label::getMinHeight() const
{
    return text_h_ > img_h_ ? text_h_ : img_h_;
}

void label::show()
{
    show_ = true;
}

void label::hide()
{
    show_ = false;
}
<|endoftext|>


<commit_before>#include "content/nw/src/api/nw_clipboard_api.h"

#include "base/base64.h"
#include "base/logging.h"
#include "base/test/bind.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/devtools_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "content/nw/src/api/nw_clipboard.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/error_utils.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "third_party/skia/include/core/SkBitmap.h"

using namespace extensions::nwapi::nw__clipboard;

namespace extensions {

namespace {
  const char* kPNGDataUriPrefix = "data:image/png;base64,";
  const char* kJPEGDataUriPrefix = "data:image/jpeg;base64,";
  const int   kQuality = 100;

class ReadImageHelper {
public:
  ReadImageHelper() = default;
  ~ReadImageHelper() = default;
  SkBitmap ReadImage(ui::Clipboard* clipboard) {
    base::WaitableEvent event;
    SkBitmap bitmap;
    clipboard->ReadImage(
                         ui::ClipboardBuffer::kCopyPaste,
                         nullptr,
                         base::BindLambdaForTesting([&](const SkBitmap& result) {
                                                      bitmap = result;
                                                      event.Signal();
                                                    }));
    event.Wait();
    return bitmap;
  }
};

SkBitmap _ReadImage(ui::Clipboard* clipboard) {
  ReadImageHelper read_image_helper;
  return read_image_helper.ReadImage(clipboard);
}
  class ClipboardReader {
  public:
    ClipboardReader() {
      clipboard_ = ui::Clipboard::GetForCurrentThread();
    }

    bool Read(ClipboardData& data) {
      switch(data.type) {
        case TYPE_TEXT:
        return ReadText(data);
        break;
        case TYPE_HTML:
        return ReadHTML(data);
        break;
        case TYPE_RTF:
        return ReadRTF(data);
        break;
        case TYPE_PNG:
        case TYPE_JPEG:
        return ReadImage(data);
        break;
        case TYPE_NONE:
        NOTREACHED();
        return false;
      }
      NOTREACHED();
      return false;
    }

    std::string error() {
      return error_;
    }

  private:
    bool ReadText(ClipboardData& data) {
      DCHECK(data.type == TYPE_TEXT);
      std::u16string text;
      clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste, nullptr, &text);
      data.data.reset(new std::string(base::UTF16ToUTF8(text)));
      return true;
    }

    bool ReadHTML(ClipboardData& data) {
      DCHECK(data.type == TYPE_HTML);
      std::u16string text;
      std::string src_url;
      uint32_t fragment_start, fragment_end;
      clipboard_->ReadHTML(ui::ClipboardBuffer::kCopyPaste, nullptr,
                           &text, &src_url, &fragment_start, &fragment_end);
      data.data.reset(new std::string(base::UTF16ToUTF8(text)));
      return true;
    }

    bool ReadRTF(ClipboardData& data) {
      DCHECK(data.type == TYPE_RTF);
      std::string text;
      clipboard_->ReadRTF(ui::ClipboardBuffer::kCopyPaste, nullptr, &text);
      data.data.reset(new std::string(text));
      return true;
    }

    bool ReadImage(ClipboardData& data) {
      DCHECK(data.type == TYPE_PNG || data.type == TYPE_JPEG);
      std::vector<unsigned char> encoded_image;
      SkBitmap bitmap = _ReadImage(clipboard_);

      if (bitmap.isNull()) {
        return true;
      }

      if (data.type == TYPE_PNG &&
         !gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &encoded_image)) {
        LOG(INFO) << "NwClipboardGetSyncFunction::RunSync(" << nwapi::nw__clipboard::ToString(data.type) << ") failed when converting to PNG";
        error_ = "Failed to encode as PNG";
        return false;
      } else if (data.type == TYPE_JPEG &&
                 !gfx::JPEGCodec::Encode(bitmap, kQuality, &encoded_image)) {
        LOG(INFO) << "NwClipboardGetSyncFunction::RunSync(" << nwapi::nw__clipboard::ToString(data.type) << ") failed when converting to JPEG";
        error_ = "Failed to encode as JPEG";
        return false;
      }

      std::string encoded_image_base64;
      std::string encoded_image_str(encoded_image.data(), encoded_image.data() + encoded_image.size());
      base::Base64Encode(encoded_image_str, &encoded_image_base64);

      if (!(data.raw.get() && *(data.raw))) {
        if (data.type == TYPE_PNG) {
          encoded_image_base64.insert(0, kPNGDataUriPrefix);
        } else {
          DCHECK(data.type == TYPE_JPEG);
          encoded_image_base64.insert(0, kJPEGDataUriPrefix);
        }
      }

      data.data.reset(new std::string(encoded_image_base64));
      LOG(INFO) << "NwClipboardGetSyncFunction::RunSync(" << nwapi::nw__clipboard::ToString(data.type) << ")";
      return true;
    }

    ui::Clipboard* clipboard_;
    std::string error_;
  };

  class ClipboardWriter {
  public:
    ClipboardWriter() {
      scw_.reset(new ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste));
    }

    ~ClipboardWriter() {
      scw_.reset();
    }

    bool Write(ClipboardData& data) {
      switch(data.type) {
        case TYPE_TEXT:
        return WriteText(data);
        break;
        case TYPE_HTML:
        return WriteHTML(data);
        break;
        case TYPE_RTF:
        return WriteRTF(data);
        break;
        case TYPE_PNG:
        case TYPE_JPEG:
        return WriteImage(data);
        break;
        case TYPE_NONE:
        NOTREACHED();
        return false;
      }
      NOTREACHED();
      return false;
    }

    std::string error() const {
      return error_;
    }

    void Reset() {
      scw_->Reset();
    }

  private:
    bool WriteText(ClipboardData& data) {
      DCHECK(data.type == TYPE_TEXT);
      scw_->WriteText(base::UTF8ToUTF16(*(data.data)));
      return true;
    }

    bool WriteHTML(ClipboardData& data) {
      DCHECK(data.type == TYPE_HTML);
      scw_->WriteHTML(base::UTF8ToUTF16(*(data.data)), std::string());
      return true;
    }

    bool WriteRTF(ClipboardData& data) {
      DCHECK(data.type == TYPE_RTF);
      scw_->WriteRTF(*(data.data));
      return true;
    }

    bool WriteImage(ClipboardData& data) {
      DCHECK(data.type == TYPE_PNG || data.type == TYPE_JPEG);
      std::string content = *(data.data);

      // strip off data uri header if raw is set
      if (!(data.raw.get() && *(data.raw))) {
        if (data.type == TYPE_PNG && base::StartsWith(content, kPNGDataUriPrefix, base::CompareCase::INSENSITIVE_ASCII)) {
          content = content.substr(strlen(kPNGDataUriPrefix));
        } else if (data.type == TYPE_JPEG && base::StartsWith(content, kJPEGDataUriPrefix, base::CompareCase::INSENSITIVE_ASCII)) {
          content = content.substr(strlen(kJPEGDataUriPrefix));
        } else {
          error_ = base::StringPrintf("Invalid data URI. Only \"%s\" or \"%s\" is accepted.", kPNGDataUriPrefix, kJPEGDataUriPrefix);
          return false;
        }
      }

      std::string decoded_str;
      if (!base::Base64Decode(content, &decoded_str)) {
        error_ = "Bad base64 string";
        return false;
      }

      std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
      if (data.type == TYPE_PNG &&
        !gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(decoded_str.c_str()), decoded_str.size(), bitmap.get())) {
        error_ = "Failed to decode as PNG";
        return false;
      } else if (data.type == TYPE_JPEG) {
        std::unique_ptr<SkBitmap> tmp_bitmap = gfx::JPEGCodec::Decode(reinterpret_cast<const unsigned char*>(decoded_str.c_str()), decoded_str.size());
        if (tmp_bitmap == NULL) {
          error_ = "Failed to decode as JPEG";
          return false;
        }
        bitmap = std::move(tmp_bitmap);
      }

      scw_->WriteImage(*bitmap);

      return true;
    }

    std::string error_;
    std::unique_ptr<ui::ScopedClipboardWriter> scw_;
  };
}

NwClipboardGetListSyncFunction::NwClipboardGetListSyncFunction() {
}

NwClipboardGetListSyncFunction::~NwClipboardGetListSyncFunction() {
}

bool NwClipboardGetListSyncFunction::RunNWSync(base::ListValue* response, std::string* error) {
  std::unique_ptr<GetListSync::Params> params(GetListSync::Params::Create(args()));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  std::unique_ptr<ClipboardReader> reader(new ClipboardReader());

  for(auto& data : params->data) {
    if (!reader->Read(data)) {
      *error = reader->error();
      return false;
    }
    response->Append(data.ToValue());
  }

  return true;
}

NwClipboardSetListSyncFunction::NwClipboardSetListSyncFunction() {
}

NwClipboardSetListSyncFunction::~NwClipboardSetListSyncFunction() {
}

bool NwClipboardSetListSyncFunction::RunNWSync(base::ListValue* response, std::string* error) {
  std::unique_ptr<SetListSync::Params> params(SetListSync::Params::Create(args()));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  std::unique_ptr<ClipboardWriter> writer(new ClipboardWriter());

  for(auto& data : params->data) {
    if (!writer->Write(data)) {
      *error = writer->error();
      writer->Reset();
      return false;
    }
  }

  return true;
}

NwClipboardClearSyncFunction::NwClipboardClearSyncFunction() {

}

NwClipboardClearSyncFunction::~NwClipboardClearSyncFunction() {

}

bool NwClipboardClearSyncFunction::RunNWSync(base::ListValue* response, std::string* error) {
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  clipboard->Clear(ui::ClipboardBuffer::kCopyPaste);
  return true;
}

NwClipboardReadAvailableTypesFunction::NwClipboardReadAvailableTypesFunction() {

}

NwClipboardReadAvailableTypesFunction::~NwClipboardReadAvailableTypesFunction() {

}

bool NwClipboardReadAvailableTypesFunction::RunNWSync(base::ListValue* response, std::string* error) {
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  std::vector<std::u16string> types;
  clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste, nullptr, &types);
  for(std::vector<std::u16string>::iterator it = types.begin(); it != types.end(); it++) {
    if (base::EqualsASCII(*it, ui::kMimeTypeText)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_TEXT))));
    } else if (base::EqualsASCII(*it, ui::kMimeTypeHTML)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_HTML))));
    } else if (base::EqualsASCII(*it, ui::kMimeTypeRTF)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_RTF))));
    } else if (base::EqualsASCII(*it, ui::kMimeTypePNG)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_PNG))));
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_JPEG))));
    }
  }
  return true;
}

} // namespace extensions
<commit_msg>ignore unreachable-code-break warning<commit_after>#include "content/nw/src/api/nw_clipboard_api.h"

#include "base/base64.h"
#include "base/logging.h"
#include "base/test/bind.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/devtools_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "content/nw/src/api/nw_clipboard.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/error_utils.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "third_party/skia/include/core/SkBitmap.h"

#pragma clang diagnostic ignored "-Wunreachable-code-break"

using namespace extensions::nwapi::nw__clipboard;

namespace extensions {

namespace {
  const char* kPNGDataUriPrefix = "data:image/png;base64,";
  const char* kJPEGDataUriPrefix = "data:image/jpeg;base64,";
  const int   kQuality = 100;

class ReadImageHelper {
public:
  ReadImageHelper() = default;
  ~ReadImageHelper() = default;
  SkBitmap ReadImage(ui::Clipboard* clipboard) {
    base::WaitableEvent event;
    SkBitmap bitmap;
    clipboard->ReadImage(
                         ui::ClipboardBuffer::kCopyPaste,
                         nullptr,
                         base::BindLambdaForTesting([&](const SkBitmap& result) {
                                                      bitmap = result;
                                                      event.Signal();
                                                    }));
    event.Wait();
    return bitmap;
  }
};

SkBitmap _ReadImage(ui::Clipboard* clipboard) {
  ReadImageHelper read_image_helper;
  return read_image_helper.ReadImage(clipboard);
}
  class ClipboardReader {
  public:
    ClipboardReader() {
      clipboard_ = ui::Clipboard::GetForCurrentThread();
    }

    bool Read(ClipboardData& data) {
      switch(data.type) {
        case TYPE_TEXT:
        return ReadText(data);
        break;
        case TYPE_HTML:
        return ReadHTML(data);
        break;
        case TYPE_RTF:
        return ReadRTF(data);
        break;
        case TYPE_PNG:
        case TYPE_JPEG:
        return ReadImage(data);
        break;
        case TYPE_NONE:
        NOTREACHED();
        return false;
      }
      NOTREACHED();
      return false;
    }

    std::string error() {
      return error_;
    }

  private:
    bool ReadText(ClipboardData& data) {
      DCHECK(data.type == TYPE_TEXT);
      std::u16string text;
      clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste, nullptr, &text);
      data.data.reset(new std::string(base::UTF16ToUTF8(text)));
      return true;
    }

    bool ReadHTML(ClipboardData& data) {
      DCHECK(data.type == TYPE_HTML);
      std::u16string text;
      std::string src_url;
      uint32_t fragment_start, fragment_end;
      clipboard_->ReadHTML(ui::ClipboardBuffer::kCopyPaste, nullptr,
                           &text, &src_url, &fragment_start, &fragment_end);
      data.data.reset(new std::string(base::UTF16ToUTF8(text)));
      return true;
    }

    bool ReadRTF(ClipboardData& data) {
      DCHECK(data.type == TYPE_RTF);
      std::string text;
      clipboard_->ReadRTF(ui::ClipboardBuffer::kCopyPaste, nullptr, &text);
      data.data.reset(new std::string(text));
      return true;
    }

    bool ReadImage(ClipboardData& data) {
      DCHECK(data.type == TYPE_PNG || data.type == TYPE_JPEG);
      std::vector<unsigned char> encoded_image;
      SkBitmap bitmap = _ReadImage(clipboard_);

      if (bitmap.isNull()) {
        return true;
      }

      if (data.type == TYPE_PNG &&
         !gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &encoded_image)) {
        LOG(INFO) << "NwClipboardGetSyncFunction::RunSync(" << nwapi::nw__clipboard::ToString(data.type) << ") failed when converting to PNG";
        error_ = "Failed to encode as PNG";
        return false;
      } else if (data.type == TYPE_JPEG &&
                 !gfx::JPEGCodec::Encode(bitmap, kQuality, &encoded_image)) {
        LOG(INFO) << "NwClipboardGetSyncFunction::RunSync(" << nwapi::nw__clipboard::ToString(data.type) << ") failed when converting to JPEG";
        error_ = "Failed to encode as JPEG";
        return false;
      }

      std::string encoded_image_base64;
      std::string encoded_image_str(encoded_image.data(), encoded_image.data() + encoded_image.size());
      base::Base64Encode(encoded_image_str, &encoded_image_base64);

      if (!(data.raw.get() && *(data.raw))) {
        if (data.type == TYPE_PNG) {
          encoded_image_base64.insert(0, kPNGDataUriPrefix);
        } else {
          DCHECK(data.type == TYPE_JPEG);
          encoded_image_base64.insert(0, kJPEGDataUriPrefix);
        }
      }

      data.data.reset(new std::string(encoded_image_base64));
      LOG(INFO) << "NwClipboardGetSyncFunction::RunSync(" << nwapi::nw__clipboard::ToString(data.type) << ")";
      return true;
    }

    ui::Clipboard* clipboard_;
    std::string error_;
  };

  class ClipboardWriter {
  public:
    ClipboardWriter() {
      scw_.reset(new ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste));
    }

    ~ClipboardWriter() {
      scw_.reset();
    }

    bool Write(ClipboardData& data) {
      switch(data.type) {
        case TYPE_TEXT:
        return WriteText(data);
        break;
        case TYPE_HTML:
        return WriteHTML(data);
        break;
        case TYPE_RTF:
        return WriteRTF(data);
        break;
        case TYPE_PNG:
        case TYPE_JPEG:
        return WriteImage(data);
        break;
        case TYPE_NONE:
        NOTREACHED();
        return false;
      }
      NOTREACHED();
      return false;
    }

    std::string error() const {
      return error_;
    }

    void Reset() {
      scw_->Reset();
    }

  private:
    bool WriteText(ClipboardData& data) {
      DCHECK(data.type == TYPE_TEXT);
      scw_->WriteText(base::UTF8ToUTF16(*(data.data)));
      return true;
    }

    bool WriteHTML(ClipboardData& data) {
      DCHECK(data.type == TYPE_HTML);
      scw_->WriteHTML(base::UTF8ToUTF16(*(data.data)), std::string());
      return true;
    }

    bool WriteRTF(ClipboardData& data) {
      DCHECK(data.type == TYPE_RTF);
      scw_->WriteRTF(*(data.data));
      return true;
    }

    bool WriteImage(ClipboardData& data) {
      DCHECK(data.type == TYPE_PNG || data.type == TYPE_JPEG);
      std::string content = *(data.data);

      // strip off data uri header if raw is set
      if (!(data.raw.get() && *(data.raw))) {
        if (data.type == TYPE_PNG && base::StartsWith(content, kPNGDataUriPrefix, base::CompareCase::INSENSITIVE_ASCII)) {
          content = content.substr(strlen(kPNGDataUriPrefix));
        } else if (data.type == TYPE_JPEG && base::StartsWith(content, kJPEGDataUriPrefix, base::CompareCase::INSENSITIVE_ASCII)) {
          content = content.substr(strlen(kJPEGDataUriPrefix));
        } else {
          error_ = base::StringPrintf("Invalid data URI. Only \"%s\" or \"%s\" is accepted.", kPNGDataUriPrefix, kJPEGDataUriPrefix);
          return false;
        }
      }

      std::string decoded_str;
      if (!base::Base64Decode(content, &decoded_str)) {
        error_ = "Bad base64 string";
        return false;
      }

      std::unique_ptr<SkBitmap> bitmap(new SkBitmap());
      if (data.type == TYPE_PNG &&
        !gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(decoded_str.c_str()), decoded_str.size(), bitmap.get())) {
        error_ = "Failed to decode as PNG";
        return false;
      } else if (data.type == TYPE_JPEG) {
        std::unique_ptr<SkBitmap> tmp_bitmap = gfx::JPEGCodec::Decode(reinterpret_cast<const unsigned char*>(decoded_str.c_str()), decoded_str.size());
        if (tmp_bitmap == NULL) {
          error_ = "Failed to decode as JPEG";
          return false;
        }
        bitmap = std::move(tmp_bitmap);
      }

      scw_->WriteImage(*bitmap);

      return true;
    }

    std::string error_;
    std::unique_ptr<ui::ScopedClipboardWriter> scw_;
  };
}

NwClipboardGetListSyncFunction::NwClipboardGetListSyncFunction() {
}

NwClipboardGetListSyncFunction::~NwClipboardGetListSyncFunction() {
}

bool NwClipboardGetListSyncFunction::RunNWSync(base::ListValue* response, std::string* error) {
  std::unique_ptr<GetListSync::Params> params(GetListSync::Params::Create(args()));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  std::unique_ptr<ClipboardReader> reader(new ClipboardReader());

  for(auto& data : params->data) {
    if (!reader->Read(data)) {
      *error = reader->error();
      return false;
    }
    response->Append(data.ToValue());
  }

  return true;
}

NwClipboardSetListSyncFunction::NwClipboardSetListSyncFunction() {
}

NwClipboardSetListSyncFunction::~NwClipboardSetListSyncFunction() {
}

bool NwClipboardSetListSyncFunction::RunNWSync(base::ListValue* response, std::string* error) {
  std::unique_ptr<SetListSync::Params> params(SetListSync::Params::Create(args()));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  std::unique_ptr<ClipboardWriter> writer(new ClipboardWriter());

  for(auto& data : params->data) {
    if (!writer->Write(data)) {
      *error = writer->error();
      writer->Reset();
      return false;
    }
  }

  return true;
}

NwClipboardClearSyncFunction::NwClipboardClearSyncFunction() {

}

NwClipboardClearSyncFunction::~NwClipboardClearSyncFunction() {

}

bool NwClipboardClearSyncFunction::RunNWSync(base::ListValue* response, std::string* error) {
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  clipboard->Clear(ui::ClipboardBuffer::kCopyPaste);
  return true;
}

NwClipboardReadAvailableTypesFunction::NwClipboardReadAvailableTypesFunction() {

}

NwClipboardReadAvailableTypesFunction::~NwClipboardReadAvailableTypesFunction() {

}

bool NwClipboardReadAvailableTypesFunction::RunNWSync(base::ListValue* response, std::string* error) {
  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
  std::vector<std::u16string> types;
  clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste, nullptr, &types);
  for(std::vector<std::u16string>::iterator it = types.begin(); it != types.end(); it++) {
    if (base::EqualsASCII(*it, ui::kMimeTypeText)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_TEXT))));
    } else if (base::EqualsASCII(*it, ui::kMimeTypeHTML)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_HTML))));
    } else if (base::EqualsASCII(*it, ui::kMimeTypeRTF)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_RTF))));
    } else if (base::EqualsASCII(*it, ui::kMimeTypePNG)) {
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_PNG))));
      response->Append(base::WrapUnique(new base::Value(ToString(TYPE_JPEG))));
    }
  }
  return true;
}

} // namespace extensions
<|endoftext|>


<commit_before><commit_msg>Resolves: #i124409# use slot SID_ATTR_METRIC...<commit_after><|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// exception_test.cpp
//
// Identification: test/network/exception_test.cpp
//
// Copyright (c) 2016-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <pqxx/pqxx> /* libpqxx is used to instantiate C++ client */
#include <pqxx/except.hxx>

#include "common/harness.h"
#include "common/logger.h"
#include "gtest/gtest.h"
#include "network/network_manager.h"
#include "network/protocol_handler_factory.h"
#include "network/postgres_protocol_handler.h"
#include "util/string_util.h"

#define NUM_THREADS 1

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Exception Test
//===--------------------------------------------------------------------===//

class ExceptionTests : public PelotonTest {};

static void *LaunchServer(peloton::network::NetworkManager network_manager,
                          int port) {
  try {
    network_manager.SetPort(port);
    network_manager.StartServer();
  } catch (peloton::ConnectionException &exception) {
    LOG_INFO("[LaunchServer] exception in thread");
  }
  return NULL;
}

/*
 * To test with the queries with syntax error that will be caught by parser.
 * The server will catch these errors in Networking layer and directly return ERROR response.
 */
void *ParserExceptionTest(int port) {
  try {
    // forcing the factory to generate psql protocol handler
    pqxx::connection C(StringUtil::Format(
        "host=127.0.0.1 port=%d user=postgres sslmode=disable application_name=psql", port));

    peloton::network::NetworkConnection *conn =
        peloton::network::NetworkManager::GetConnection(
            peloton::network::NetworkManager::recent_connfd);

    network::PostgresProtocolHandler *handler =
        dynamic_cast<network::PostgresProtocolHandler*>(conn->protocol_handler_.get());
    EXPECT_NE(handler, nullptr);

    // If an exception occurs on one transaction, we can not use this transaction anymore
    int exception_count = 0, total = 6;

    // DROP query
    pqxx::work txn1(C);
    try {
      txn1.exec("DROP TABEL IF EXISTS employee;");
      txn1.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Invalid Drop Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // CREATE query
    pqxx::work txn2(C);
    try {
      txn2.exec("CREATE TABEL employee(id ITN, name VARCHAR(100));");
      txn2.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Invalid Create Query: %s", e.base().what());
        exception_count += 1;
      }
    }
    pqxx::work txn3(C);
    txn3.exec("DROP TABLE IF EXISTS foo;");
    txn3.exec("CREATE TABLE foo(id INT);");
    txn3.commit();

    // Select query
    pqxx::work txn4(C);
    try {
      txn4.exec("SELECT name FROM foo id = 1;");
      txn4.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Invalid Select Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // SELECT;
    pqxx::work txn5(C);
    try {
      txn5.exec("SELECT ;");
      txn5.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Invalid Select Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // Prepare query
    pqxx::work txn6(C);
    try {
      txn6.exec("PREPARE func INSERT INTO foo VALUES($1, $2);");
      txn6.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Invalid Prepare Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // Execute query
    pqxx::work txn7(C);
    try {
      txn7.exec("PREPARE func(INT) AS INSERT INTO foo VALUES($1);");
      txn7.exec("EXECUTE fun;");
      txn7.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Invalid Execute Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // Empty query, should be valid
    pqxx::work txn8(C);
    try {
      txn8.exec(";;");
      txn8.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_INFO("Empty Query: %s", e.base().what());
        EXPECT_TRUE(false);
      }
    }

    // Check the number of exceptions
    EXPECT_EQ(exception_count, total);

  } catch (const std::exception &e) {
    LOG_INFO("[ExceptionTest] Exception occurred: %s", e.what());
    EXPECT_TRUE(false);
  }

  LOG_INFO("[ExceptionTest] Client has closed");
  return NULL;
}

/**
 * Use std::thread to initiate peloton server and pqxx client in separate
 * threads
 * Simple query test to guarantee both sides run correctly
 * Callback method to close server after client finishes
 */
TEST_F(ExceptionTests, ParserExceptionTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::network::NetworkManager network_manager;

  int port = 15721;
  std::thread serverThread(LaunchServer, network_manager, port);
  while (!network_manager.GetIsStarted()) {
    sleep(1);
  }

  // server & client running correctly
  ParserExceptionTest(port);

  network_manager.CloseServer();
  serverThread.join();
  LOG_INFO("Peloton is shutting down");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down");
}

}  // namespace test
}  // namespace peloton
<commit_msg>Log_info to log_trace<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// exception_test.cpp
//
// Identification: test/network/exception_test.cpp
//
// Copyright (c) 2016-17, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <pqxx/pqxx> /* libpqxx is used to instantiate C++ client */
#include <pqxx/except.hxx>

#include "common/harness.h"
#include "common/logger.h"
#include "gtest/gtest.h"
#include "network/network_manager.h"
#include "network/protocol_handler_factory.h"
#include "network/postgres_protocol_handler.h"
#include "util/string_util.h"

#define NUM_THREADS 1

namespace peloton {
namespace test {

//===--------------------------------------------------------------------===//
// Exception Test
//===--------------------------------------------------------------------===//

class ExceptionTests : public PelotonTest {};

static void *LaunchServer(peloton::network::NetworkManager network_manager,
                          int port) {
  try {
    network_manager.SetPort(port);
    network_manager.StartServer();
  } catch (peloton::ConnectionException &exception) {
    LOG_INFO("[LaunchServer] exception in thread");
  }
  return NULL;
}

/*
 * To test with the queries with syntax error that will be caught by parser.
 * The server will catch these errors in Networking layer and directly return ERROR response.
 */
void *ParserExceptionTest(int port) {
  try {
    // forcing the factory to generate psql protocol handler
    pqxx::connection C(StringUtil::Format(
        "host=127.0.0.1 port=%d user=postgres sslmode=disable application_name=psql", port));

    peloton::network::NetworkConnection *conn =
        peloton::network::NetworkManager::GetConnection(
            peloton::network::NetworkManager::recent_connfd);

    network::PostgresProtocolHandler *handler =
        dynamic_cast<network::PostgresProtocolHandler*>(conn->protocol_handler_.get());
    EXPECT_NE(handler, nullptr);

    // If an exception occurs on one transaction, we can not use this transaction anymore
    int exception_count = 0, total = 6;

    // DROP query
    pqxx::work txn1(C);
    try {
      txn1.exec("DROP TABEL IF EXISTS employee;");
      txn1.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Invalid Drop Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // CREATE query
    pqxx::work txn2(C);
    try {
      txn2.exec("CREATE TABEL employee(id ITN, name VARCHAR(100));");
      txn2.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Invalid Create Query: %s", e.base().what());
        exception_count += 1;
      }
    }
    pqxx::work txn3(C);
    txn3.exec("DROP TABLE IF EXISTS foo;");
    txn3.exec("CREATE TABLE foo(id INT);");
    txn3.commit();

    // Select query
    pqxx::work txn4(C);
    try {
      txn4.exec("SELECT name FROM foo id = 1;");
      txn4.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Invalid Select Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // SELECT;
    pqxx::work txn5(C);
    try {
      txn5.exec("SELECT ;");
      txn5.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Invalid Select Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // Prepare query
    pqxx::work txn6(C);
    try {
      txn6.exec("PREPARE func INSERT INTO foo VALUES($1, $2);");
      txn6.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Invalid Prepare Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // Execute query
    pqxx::work txn7(C);
    try {
      txn7.exec("PREPARE func(INT) AS INSERT INTO foo VALUES($1);");
      txn7.exec("EXECUTE fun;");
      txn7.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Invalid Execute Query: %s", e.base().what());
        exception_count += 1;
      }
    }

    // Empty query, should be valid
    pqxx::work txn8(C);
    try {
      txn8.exec(";;");
      txn8.commit();
    } catch (const pqxx::pqxx_exception &e) {
      const pqxx::sql_error *s = dynamic_cast<const pqxx::sql_error*>(&e.base());
      if (s) {
        LOG_TRACE("Empty Query: %s", e.base().what());
        EXPECT_TRUE(false);
      }
    }

    // Check the number of exceptions
    EXPECT_EQ(exception_count, total);

  } catch (const std::exception &e) {
    LOG_ERROR("[ExceptionTest] Exception occurred: %s", e.what());
    EXPECT_TRUE(false);
  }

  LOG_INFO("[ExceptionTest] Client has closed");
  return NULL;
}

/**
 * Use std::thread to initiate peloton server and pqxx client in separate
 * threads
 * Simple query test to guarantee both sides run correctly
 * Callback method to close server after client finishes
 */
TEST_F(ExceptionTests, ParserExceptionTest) {
  peloton::PelotonInit::Initialize();
  LOG_INFO("Server initialized");
  peloton::network::NetworkManager network_manager;

  int port = 15721;
  std::thread serverThread(LaunchServer, network_manager, port);
  while (!network_manager.GetIsStarted()) {
    sleep(1);
  }

  // server & client running correctly
  ParserExceptionTest(port);

  network_manager.CloseServer();
  serverThread.join();
  LOG_INFO("Peloton is shutting down");
  peloton::PelotonInit::Shutdown();
  LOG_INFO("Peloton has shut down");
}

}  // namespace test
}  // namespace peloton
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////

#include <cppcoro/shared_lazy_task.hpp>
#include <cppcoro/task.hpp>
#include <cppcoro/single_consumer_event.hpp>

#include "counted.hpp"

#include "doctest/doctest.h"

TEST_SUITE_BEGIN("shared_lazy_task");

TEST_CASE("awaiting default-constructed task throws broken_promise")
{
	auto t = []() -> cppcoro::task<>
	{
		CHECK_THROWS_AS(co_await cppcoro::shared_lazy_task<>{}, const cppcoro::broken_promise&);
	}();

	CHECK(t.is_ready());
}

TEST_CASE("coroutine doesn't start executing until awaited")
{
	bool startedExecuting = false;
	auto f = [&]() -> cppcoro::shared_lazy_task<>
	{
		startedExecuting = true;
		co_return;
	};

	auto t = f();

	CHECK(!t.is_ready());
	CHECK(!startedExecuting);

	auto waiter = [](cppcoro::shared_lazy_task<> t) -> cppcoro::task<>
	{
		co_await t;
	}(t);

	CHECK(waiter.is_ready());
	CHECK(t.is_ready());
	CHECK(startedExecuting);
}

TEST_CASE("result is destroyed when last reference is destroyed")
{
	counted::reset_counts();

	{
		auto t = []() -> cppcoro::shared_lazy_task<counted>
		{
			co_return counted{};
		}();

		CHECK(counted::active_count() == 0);

		[](cppcoro::shared_lazy_task<counted> t) -> cppcoro::task<>
		{
			co_await t;
		}(t);

		CHECK(counted::active_count() == 1);
	}

	CHECK(counted::active_count() == 0);
}

TEST_CASE("multiple awaiters")
{
	cppcoro::single_consumer_event event;
	bool startedExecution = false;
	auto produce = [&]() -> cppcoro::shared_lazy_task<int>
	{
		startedExecution = true;
		co_await event;
		co_return 1;
	};

	auto consume = [](cppcoro::shared_lazy_task<int> t) -> cppcoro::task<>
	{
		int result = co_await t;
		CHECK(result == 1);
	};

	auto sharedTask = produce();

	CHECK(!sharedTask.is_ready());
	CHECK(!startedExecution);

	auto t1 = consume(sharedTask);

	CHECK(!t1.is_ready());
	CHECK(startedExecution);
	CHECK(!sharedTask.is_ready());

	auto t2 = consume(sharedTask);

	CHECK(!t2.is_ready());
	CHECK(!sharedTask.is_ready());

	auto t3 = consume(sharedTask);

	event.set();

	CHECK(sharedTask.is_ready());
	CHECK(t1.is_ready());
	CHECK(t2.is_ready());
	CHECK(t3.is_ready());
}

TEST_CASE("waiting on shared_lazy_task in loop doesn't cause stack-overflow")
{
	// This test checks that awaiting a shared_lazy_task that completes
	// synchronously doesn't recursively resume the awaiter inside the
	// call to start executing the task. If it were to do this then we'd
	// expect that this test would result in failure due to stack-overflow.

	auto completesSynchronously = []() -> cppcoro::shared_lazy_task<int>
	{
		co_return 1;
	};

	auto run = [&]() -> cppcoro::task<>
	{
		int result = 0;
		for (int i = 0; i < 1'000'000; ++i)
		{
			result += co_await completesSynchronously();
		}
		CHECK(result == 1'000'000);
	};

	auto t = run();
	CHECK(t.is_ready());
}

TEST_CASE("make_shared_task")
{
	bool startedExecution = false;

	auto f = [&]() -> cppcoro::lazy_task<std::string>
	{
		startedExecution = false;
		co_return "test";
	};

	auto t = f();

	cppcoro::shared_lazy_task<std::string> sharedT =
		cppcoro::make_shared_task(std::move(t));

	CHECK(!sharedT.is_ready());
	CHECK(!startedExecution);

	auto consume = [](cppcoro::shared_lazy_task<std::string> t) -> cppcoro::task<>
	{
		auto x = co_await std::move(t);
		CHECK(x == "test");
	};

	auto c1 = consume(sharedT);
	auto c2 = consume(sharedT);

	CHECK(c1.is_ready());
	CHECK(c2.is_ready());
}

TEST_CASE("make_shared_task of void"
	* doctest::description{ "Tests that workaround for MSVC 2017.1 bug is operational" })
{
	bool startedExecution = false;

	auto f = [&]() -> cppcoro::lazy_task<>
	{
		startedExecution = true;
		co_return;
	};

	auto t = f();

	cppcoro::shared_lazy_task<> sharedT = cppcoro::make_shared_task(std::move(t));

	CHECK(!sharedT.is_ready());
	CHECK(!startedExecution);

	auto consume = [](cppcoro::shared_lazy_task<> t) -> cppcoro::task<>
	{
		co_await t;
	};

	auto c1 = consume(sharedT);
	CHECK(startedExecution);

	auto c2 = consume(sharedT);

	CHECK(c1.is_ready());
	CHECK(c2.is_ready());
}

TEST_SUITE_END();
<commit_msg>Skip running some shared_lazy_task tests under VS2015 x86 optimised.<commit_after>///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////

#include <cppcoro/shared_lazy_task.hpp>
#include <cppcoro/task.hpp>
#include <cppcoro/single_consumer_event.hpp>

#include "counted.hpp"

#include "doctest/doctest.h"

TEST_SUITE_BEGIN("shared_lazy_task");

TEST_CASE("awaiting default-constructed task throws broken_promise")
{
	auto t = []() -> cppcoro::task<>
	{
		CHECK_THROWS_AS(co_await cppcoro::shared_lazy_task<>{}, const cppcoro::broken_promise&);
	}();

	CHECK(t.is_ready());
}

TEST_CASE("coroutine doesn't start executing until awaited")
{
	bool startedExecuting = false;
	auto f = [&]() -> cppcoro::shared_lazy_task<>
	{
		startedExecuting = true;
		co_return;
	};

	auto t = f();

	CHECK(!t.is_ready());
	CHECK(!startedExecuting);

	auto waiter = [](cppcoro::shared_lazy_task<> t) -> cppcoro::task<>
	{
		co_await t;
	}(t);

	CHECK(waiter.is_ready());
	CHECK(t.is_ready());
	CHECK(startedExecuting);
}

static constexpr bool is_msvc_2015_x86_optimised =
#if defined(_MSC_VER) && _MSC_VER < 1910 && defined(CPPCORO_RELEASE_OPTIMISED)
	true;
#else
	false;
#endif

// Skip running under MSVC 2015 x86 opt due to compiler bug which causes this test
// to crash with an access violation inside shared_lazy_task_promise_base::try_await().
TEST_CASE("result is destroyed when last reference is destroyed"
	* doctest::skip{ is_msvc_2015_x86_optimised })
{
	counted::reset_counts();

	{
		auto t = []() -> cppcoro::shared_lazy_task<counted>
		{
			co_return counted{};
		}();

		CHECK(counted::active_count() == 0);

		[](cppcoro::shared_lazy_task<counted> t) -> cppcoro::task<>
		{
			co_await t;
		}(t);

		CHECK(counted::active_count() == 1);
	}

	CHECK(counted::active_count() == 0);
}

TEST_CASE("multiple awaiters")
{
	cppcoro::single_consumer_event event;
	bool startedExecution = false;
	auto produce = [&]() -> cppcoro::shared_lazy_task<int>
	{
		startedExecution = true;
		co_await event;
		co_return 1;
	};

	auto consume = [](cppcoro::shared_lazy_task<int> t) -> cppcoro::task<>
	{
		int result = co_await t;
		CHECK(result == 1);
	};

	auto sharedTask = produce();

	CHECK(!sharedTask.is_ready());
	CHECK(!startedExecution);

	auto t1 = consume(sharedTask);

	CHECK(!t1.is_ready());
	CHECK(startedExecution);
	CHECK(!sharedTask.is_ready());

	auto t2 = consume(sharedTask);

	CHECK(!t2.is_ready());
	CHECK(!sharedTask.is_ready());

	auto t3 = consume(sharedTask);

	event.set();

	CHECK(sharedTask.is_ready());
	CHECK(t1.is_ready());
	CHECK(t2.is_ready());
	CHECK(t3.is_ready());
}

// Skip running under MSVC 2015 x86 opt due to compiler bug which causes this test
// to crash with an access violation inside shared_lazy_task_promise_base::try_await().
TEST_CASE("waiting on shared_lazy_task in loop doesn't cause stack-overflow"
	* doctest::skip{ is_msvc_2015_x86_optimised })
{
	// This test checks that awaiting a shared_lazy_task that completes
	// synchronously doesn't recursively resume the awaiter inside the
	// call to start executing the task. If it were to do this then we'd
	// expect that this test would result in failure due to stack-overflow.

	auto completesSynchronously = []() -> cppcoro::shared_lazy_task<int>
	{
		co_return 1;
	};

	auto run = [&]() -> cppcoro::task<>
	{
		int result = 0;
		for (int i = 0; i < 1'000'000; ++i)
		{
			result += co_await completesSynchronously();
		}
		CHECK(result == 1'000'000);
	};

	auto t = run();
	CHECK(t.is_ready());
}

TEST_CASE("make_shared_task")
{
	bool startedExecution = false;

	auto f = [&]() -> cppcoro::lazy_task<std::string>
	{
		startedExecution = false;
		co_return "test";
	};

	auto t = f();

	cppcoro::shared_lazy_task<std::string> sharedT =
		cppcoro::make_shared_task(std::move(t));

	CHECK(!sharedT.is_ready());
	CHECK(!startedExecution);

	auto consume = [](cppcoro::shared_lazy_task<std::string> t) -> cppcoro::task<>
	{
		auto x = co_await std::move(t);
		CHECK(x == "test");
	};

	auto c1 = consume(sharedT);
	auto c2 = consume(sharedT);

	CHECK(c1.is_ready());
	CHECK(c2.is_ready());
}

TEST_CASE("make_shared_task of void"
	* doctest::description{ "Tests that workaround for MSVC 2017.1 bug is operational" })
{
	bool startedExecution = false;

	auto f = [&]() -> cppcoro::lazy_task<>
	{
		startedExecution = true;
		co_return;
	};

	auto t = f();

	cppcoro::shared_lazy_task<> sharedT = cppcoro::make_shared_task(std::move(t));

	CHECK(!sharedT.is_ready());
	CHECK(!startedExecution);

	auto consume = [](cppcoro::shared_lazy_task<> t) -> cppcoro::task<>
	{
		co_await t;
	};

	auto c1 = consume(sharedT);
	CHECK(startedExecution);

	auto c2 = consume(sharedT);

	CHECK(c1.is_ready());
	CHECK(c2.is_ready());
}

TEST_SUITE_END();
<|endoftext|>