<commit_before>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Shantanu Tushar <jhahoneyk@gmail.com>
 * Copyright (C) 2010 Laszlo Papp <djszapi@archlinux.us>
 *
 * This 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
 */

#include "commentitemsmodel.h"

#include "player/lib/atticamanager.h"

#include "core/gluonobject.h"
#include "core/gdlhandler.h"
#include "core/gluon_global.h"

#include "engine/gameproject.h"

#include <attica/comment.h>
#include <attica/listjob.h>

#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QDir>

using namespace GluonCore;
using namespace GluonPlayer;

CommentItemsModel::CommentItemsModel( QString gameId, QObject* parent )
    : QAbstractListModel( parent )
    , m_isOnline( false )
    , m_gameId( gameId )
    , m_rootNode( new GluonObject( "Comment" ) )
{
    m_columnNames << tr("Author") << tr("Title") << tr("Body") << tr("DateTime") << tr("Rating");

    loadData();     // Load comments stored locally
    updateData();   // Fetch latest comments from the web service
}

void CommentItemsModel::updateData()
{
    if( AtticaManager::instance()->isProviderValid() )
    {
        providersUpdated();
    }
    else
    {
        connect( AtticaManager::instance(), SIGNAL( gotProvider() ), SLOT( providersUpdated() ) );
    }
}

void CommentItemsModel::providersUpdated()
{
    if( AtticaManager::instance()->isProviderValid() )
    {
        Attica::ListJob<Attica::Comment> *job =
            AtticaManager::instance()->provider().requestComments( Attica::Comment::ContentComment,
                    m_gameId, "0", 0, 100 );
        connect( job, SIGNAL( finished( Attica::BaseJob* ) ), SLOT( processFetchedComments( Attica::BaseJob* ) ) );
        job->start();
    }
    else
    {
        qDebug() << "No providers found.";
    }
}

void CommentItemsModel::processFetchedComments( Attica::BaseJob* job )
{
    qDebug() << "Comments Successfully Fetched from the server!";

    Attica::ListJob<Attica::Comment> *commentsJob = static_cast<Attica::ListJob<Attica::Comment> *>( job );
    if( commentsJob->metadata().error() == Attica::Metadata::NoError )
    {
        //No error, try to remove exising comments (if any)
        //and add new comments

        for( int i = 0; i < commentsJob->itemList().count(); ++i )
        {
            Attica::Comment p( commentsJob->itemList().at( i ) );
            addComment( p, m_rootNode );
        }

        m_isOnline = true;
        reset();    //Reset the model to notify views to reload comments
    }
    else
    {
        qDebug() << "Could not fetch information";
    }
}

void CommentItemsModel::addCommentFinished( Attica::BaseJob* job )
{
    Attica::ListJob<Attica::Comment> *commentsJob = static_cast<Attica::ListJob<Attica::Comment>*>( job );
    if( commentsJob->metadata().error() == Attica::Metadata::NoError )
    {
        updateData();
    }
    else
    {
        emit addCommentFailed();
    }
}

GluonObject* CommentItemsModel::addComment( Attica::Comment comment, GluonObject* parent )
{
    GluonObject* newComment = new GluonObject( comment.id(), parent );
    newComment->setProperty( "Author", comment.user() );
    newComment->setProperty( "Title", comment.subject() );
    newComment->setProperty( "Body", comment.text() );
    newComment->setProperty( "DateTime", comment.date().toString() );
    newComment->setProperty( "Rating", comment.score() );

    foreach( const Attica::Comment& child, comment.children() )
    {
        addComment( child, newComment );
    }

    return newComment;
}

void CommentItemsModel::treeTraversal(GluonCore::GluonObject* obj)
{
    if( !obj )
        return;

    foreach( QObject * child, obj->children() )
    {
        GluonObject* gobj = qobject_cast<GluonObject*>( child );
        if( gobj )
       {
            gobj->dumpObjectTree();
            m_nodes.append(gobj);
            treeTraversal(gobj);
       }
    }
}

bool dateTimeLessThan(GluonCore::GluonObject* go1, GluonCore::GluonObject* go2)
{
    return go1->property( "DateTime" ).toString() < go2->property( "DateTime" ).toString();
}

void CommentItemsModel::loadData()
{
    // TODO: ~/.gluon/games/$gamebundle/* will be used later
    QDir gluonDir = QDir::home();
    gluonDir.mkpath( GluonEngine::projectSuffix + "/games/" );
    gluonDir.cd( GluonEngine::projectSuffix + "/games/" );

    if( QFile::exists(gluonDir.absoluteFilePath( "comments.gdl" )) )
        m_rootNode = GluonCore::GDLHandler::instance()->parseGDL( gluonDir.absoluteFilePath( "comments.gdl" ) ).at( 0 );
    else
        qDebug() << "File does not exist: " << gluonDir.absoluteFilePath( "comments.gdl" );

    treeTraversal(m_rootNode);
    qSort(m_nodes.begin(), m_nodes.end(), dateTimeLessThan);
}

void CommentItemsModel::saveData()
{
    qDebug() << "Saving data!";
    QDir gluonDir = QDir::home();
    gluonDir.mkpath( GluonEngine::projectSuffix + "/games/" );
    gluonDir.cd( GluonEngine::projectSuffix + "/games/" );
    QString filename = gluonDir.absoluteFilePath( "comments.gdl" );

    QFile dataFile( filename );
    if( !dataFile.open( QIODevice::WriteOnly ) )
        qDebug() << "Cannot open the comments file!";

    QTextStream dataWriter( &dataFile );
    dataWriter << GluonCore::GDLHandler::instance()->serializeGDL( QList<const GluonCore::GluonObject*>() << m_rootNode );
    dataFile.close();
    qDebug() << "Saved";
}

CommentItemsModel::~CommentItemsModel()
{
    saveData();     //Save data before exiting
}

QVariant CommentItemsModel::data( const QModelIndex& index, int role ) const
{
    if( role == Qt::DisplayRole || role == Qt::EditRole )
    {
        GluonObject* node;
        node = static_cast<GluonObject*>( index.internalPointer() );

        return node->property( m_columnNames.at(index.column()).toUtf8() );
    }
    else if ( role >= Qt::UserRole )
    {
        return m_nodes.at(index.row())->property( m_columnNames.at(role - Qt::UserRole).toUtf8() );
    }
    return QVariant();
}

int CommentItemsModel::rowCount( const QModelIndex& parent ) const
{
    return m_nodes.count();
}

QVariant CommentItemsModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
    if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
        return m_columnNames.at( section );

    return QVariant();
}

Qt::ItemFlags CommentItemsModel::flags( const QModelIndex& index ) const
{
    if( !index.isValid() )
        return Qt::ItemIsEnabled;

    return QAbstractItemModel::flags( index );
}

bool CommentItemsModel::setData( const QModelIndex& index, const QVariant& value, int role )
{
    if( index.isValid() && role == Qt::EditRole )
    {
        GluonObject* node;
        node = static_cast<GluonObject*>( index.internalPointer() );

        node->setProperty( m_columnNames.at(index.column()).toUtf8(), value );
        emit dataChanged( index, index );
        return true;
    }

    return false;
}

bool CommentItemsModel::insertRows( int row, int count, const QModelIndex& parent )
{
    if( count != 1 )  // Do not support more than one row at a time
    {
        qDebug() << "Can insert only one comment at a time";
        return false;
    }
    if( row != rowCount( parent ) )
    {
        qDebug() << "Can only add a comment to the end of existing comments";
        return false;
    }

    beginInsertRows( parent, row, row );
    GluonObject* parentNode;
    parentNode = static_cast<GluonObject*>( parent.internalPointer() );

    GluonObject* newNode = new GluonObject( "Comment", parentNode );
    parentNode->addChild( newNode );
    endInsertRows();

    return true;
}

bool CommentItemsModel::isOnline()
{
    return m_isOnline;
}

void CommentItemsModel::uploadComment( const QModelIndex& parentIndex, const QString& subject, const QString& message )
{
    GluonObject* parentNode = static_cast<GluonObject*>( parentIndex.internalPointer() );
    Attica::PostJob* job =
        AtticaManager::instance()->provider().addNewComment( Attica::Comment::ContentComment,
                "128637", "0", parentNode->name(), subject,
                message );
    connect( job, SIGNAL( finished( Attica::BaseJob* ) ), SLOT( addCommentFinished( Attica::BaseJob* ) ) );
    job->start();
}

#include "commentitemsmodel.moc"
<commit_msg>Fix a compilation warning.<commit_after>/******************************************************************************
 * This file is part of the Gluon Development Platform
 * Copyright (C) 2010 Shantanu Tushar <jhahoneyk@gmail.com>
 * Copyright (C) 2010 Laszlo Papp <djszapi@archlinux.us>
 *
 * This 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
 */

#include "commentitemsmodel.h"

#include "player/lib/atticamanager.h"

#include "core/gluonobject.h"
#include "core/gdlhandler.h"
#include "core/gluon_global.h"

#include "engine/gameproject.h"

#include <attica/comment.h>
#include <attica/listjob.h>

#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QDir>

using namespace GluonCore;
using namespace GluonPlayer;

CommentItemsModel::CommentItemsModel( QString gameId, QObject* parent )
    : QAbstractListModel( parent )
    , m_rootNode( new GluonObject( "Comment" ) )
    , m_isOnline( false )
    , m_gameId( gameId )
{
    m_columnNames << tr("Author") << tr("Title") << tr("Body") << tr("DateTime") << tr("Rating");

    loadData();     // Load comments stored locally
    updateData();   // Fetch latest comments from the web service
}

void CommentItemsModel::updateData()
{
    if( AtticaManager::instance()->isProviderValid() )
    {
        providersUpdated();
    }
    else
    {
        connect( AtticaManager::instance(), SIGNAL( gotProvider() ), SLOT( providersUpdated() ) );
    }
}

void CommentItemsModel::providersUpdated()
{
    if( AtticaManager::instance()->isProviderValid() )
    {
        Attica::ListJob<Attica::Comment> *job =
            AtticaManager::instance()->provider().requestComments( Attica::Comment::ContentComment,
                    m_gameId, "0", 0, 100 );
        connect( job, SIGNAL( finished( Attica::BaseJob* ) ), SLOT( processFetchedComments( Attica::BaseJob* ) ) );
        job->start();
    }
    else
    {
        qDebug() << "No providers found.";
    }
}

void CommentItemsModel::processFetchedComments( Attica::BaseJob* job )
{
    qDebug() << "Comments Successfully Fetched from the server!";

    Attica::ListJob<Attica::Comment> *commentsJob = static_cast<Attica::ListJob<Attica::Comment> *>( job );
    if( commentsJob->metadata().error() == Attica::Metadata::NoError )
    {
        //No error, try to remove exising comments (if any)
        //and add new comments

        for( int i = 0; i < commentsJob->itemList().count(); ++i )
        {
            Attica::Comment p( commentsJob->itemList().at( i ) );
            addComment( p, m_rootNode );
        }

        m_isOnline = true;
        reset();    //Reset the model to notify views to reload comments
    }
    else
    {
        qDebug() << "Could not fetch information";
    }
}

void CommentItemsModel::addCommentFinished( Attica::BaseJob* job )
{
    Attica::ListJob<Attica::Comment> *commentsJob = static_cast<Attica::ListJob<Attica::Comment>*>( job );
    if( commentsJob->metadata().error() == Attica::Metadata::NoError )
    {
        updateData();
    }
    else
    {
        emit addCommentFailed();
    }
}

GluonObject* CommentItemsModel::addComment( Attica::Comment comment, GluonObject* parent )
{
    GluonObject* newComment = new GluonObject( comment.id(), parent );
    newComment->setProperty( "Author", comment.user() );
    newComment->setProperty( "Title", comment.subject() );
    newComment->setProperty( "Body", comment.text() );
    newComment->setProperty( "DateTime", comment.date().toString() );
    newComment->setProperty( "Rating", comment.score() );

    foreach( const Attica::Comment& child, comment.children() )
    {
        addComment( child, newComment );
    }

    return newComment;
}

void CommentItemsModel::treeTraversal(GluonCore::GluonObject* obj)
{
    if( !obj )
        return;

    foreach( QObject * child, obj->children() )
    {
        GluonObject* gobj = qobject_cast<GluonObject*>( child );
        if( gobj )
       {
            gobj->dumpObjectTree();
            m_nodes.append(gobj);
            treeTraversal(gobj);
       }
    }
}

bool dateTimeLessThan(GluonCore::GluonObject* go1, GluonCore::GluonObject* go2)
{
    return go1->property( "DateTime" ).toString() < go2->property( "DateTime" ).toString();
}

void CommentItemsModel::loadData()
{
    // TODO: ~/.gluon/games/$gamebundle/* will be used later
    QDir gluonDir = QDir::home();
    gluonDir.mkpath( GluonEngine::projectSuffix + "/games/" );
    gluonDir.cd( GluonEngine::projectSuffix + "/games/" );

    if( QFile::exists(gluonDir.absoluteFilePath( "comments.gdl" )) )
        m_rootNode = GluonCore::GDLHandler::instance()->parseGDL( gluonDir.absoluteFilePath( "comments.gdl" ) ).at( 0 );
    else
        qDebug() << "File does not exist: " << gluonDir.absoluteFilePath( "comments.gdl" );

    treeTraversal(m_rootNode);
    qSort(m_nodes.begin(), m_nodes.end(), dateTimeLessThan);
}

void CommentItemsModel::saveData()
{
    qDebug() << "Saving data!";
    QDir gluonDir = QDir::home();
    gluonDir.mkpath( GluonEngine::projectSuffix + "/games/" );
    gluonDir.cd( GluonEngine::projectSuffix + "/games/" );
    QString filename = gluonDir.absoluteFilePath( "comments.gdl" );

    QFile dataFile( filename );
    if( !dataFile.open( QIODevice::WriteOnly ) )
        qDebug() << "Cannot open the comments file!";

    QTextStream dataWriter( &dataFile );
    dataWriter << GluonCore::GDLHandler::instance()->serializeGDL( QList<const GluonCore::GluonObject*>() << m_rootNode );
    dataFile.close();
    qDebug() << "Saved";
}

CommentItemsModel::~CommentItemsModel()
{
    saveData();     //Save data before exiting
}

QVariant CommentItemsModel::data( const QModelIndex& index, int role ) const
{
    if( role == Qt::DisplayRole || role == Qt::EditRole )
    {
        GluonObject* node;
        node = static_cast<GluonObject*>( index.internalPointer() );

        return node->property( m_columnNames.at(index.column()).toUtf8() );
    }
    else if ( role >= Qt::UserRole )
    {
        return m_nodes.at(index.row())->property( m_columnNames.at(role - Qt::UserRole).toUtf8() );
    }
    return QVariant();
}

int CommentItemsModel::rowCount( const QModelIndex& parent ) const
{
    return m_nodes.count();
}

QVariant CommentItemsModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
    if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
        return m_columnNames.at( section );

    return QVariant();
}

Qt::ItemFlags CommentItemsModel::flags( const QModelIndex& index ) const
{
    if( !index.isValid() )
        return Qt::ItemIsEnabled;

    return QAbstractItemModel::flags( index );
}

bool CommentItemsModel::setData( const QModelIndex& index, const QVariant& value, int role )
{
    if( index.isValid() && role == Qt::EditRole )
    {
        GluonObject* node;
        node = static_cast<GluonObject*>( index.internalPointer() );

        node->setProperty( m_columnNames.at(index.column()).toUtf8(), value );
        emit dataChanged( index, index );
        return true;
    }

    return false;
}

bool CommentItemsModel::insertRows( int row, int count, const QModelIndex& parent )
{
    if( count != 1 )  // Do not support more than one row at a time
    {
        qDebug() << "Can insert only one comment at a time";
        return false;
    }
    if( row != rowCount( parent ) )
    {
        qDebug() << "Can only add a comment to the end of existing comments";
        return false;
    }

    beginInsertRows( parent, row, row );
    GluonObject* parentNode;
    parentNode = static_cast<GluonObject*>( parent.internalPointer() );

    GluonObject* newNode = new GluonObject( "Comment", parentNode );
    parentNode->addChild( newNode );
    endInsertRows();

    return true;
}

bool CommentItemsModel::isOnline()
{
    return m_isOnline;
}

void CommentItemsModel::uploadComment( const QModelIndex& parentIndex, const QString& subject, const QString& message )
{
    GluonObject* parentNode = static_cast<GluonObject*>( parentIndex.internalPointer() );
    Attica::PostJob* job =
        AtticaManager::instance()->provider().addNewComment( Attica::Comment::ContentComment,
                "128637", "0", parentNode->name(), subject,
                message );
    connect( job, SIGNAL( finished( Attica::BaseJob* ) ), SLOT( addCommentFinished( Attica::BaseJob* ) ) );
    job->start();
}

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


<commit_before>// Copyright 2017, Dawid Kurek, <dawikur@gmail.com>

#include "lel/operation/unary.hpp"

#include "gtest/gtest.h"

TEST(unary_test, logical_not_can_be_used_in_constexpr) {
  std::logical_not<> logical_not;

  static_assert(logical_not(false), "");
}

TEST(unary_test, indirection_can_be_used_in_constexpr) {
  LeL::Operation::__Indirection indirection;

  int const val = 5;

  static_assert(indirection(&val) == 5, "");
}
<commit_msg>Remove problemanic on VS test<commit_after>// Copyright 2017, Dawid Kurek, <dawikur@gmail.com>

#include "lel/operation/unary.hpp"

#include "gtest/gtest.h"

TEST(unary_test, logical_not_can_be_used_in_constexpr) {
  std::logical_not<> logical_not;

  static_assert(logical_not(false), "");
}
<|endoftext|>


<commit_before>#include "qversitdefs_p.h"
#include "ut_qversit.h"
#include "qversitreader.h"
#include "qversitreader_p.h"
#include "qversitcontactimporter.h"
#include "qcontact.h"
#include "qcontactmanager.h"

#include <QtTest/QtTest>
#include <QDebug>
#include <QDir>
#include <QList>

QTM_BEGIN_NAMESPACE
class MyQVersitResourceHandler : public QVersitResourceHandler
{
public:
    MyQVersitResourceHandler() : mIndex(0)
    {
    }

    bool saveResource(const QByteArray& contents, const QVersitProperty& property,
                      QString* location)
    {
        Q_UNUSED(property);
        *location = QString::number(mIndex++);
        mObjects.insert(*location, contents);
        return true;
    }

    bool loadResource(const QString &location, QByteArray *contents, QString *mimeType)
    {
        Q_UNUSED(location)
        Q_UNUSED(contents)
        Q_UNUSED(mimeType)
        return false;
    }

    int mIndex;
    QMap<QString, QByteArray> mObjects;
};
QTM_END_NAMESPACE

QTM_USE_NAMESPACE

#ifndef TESTDATA_DIR
#define TESTDATA_DIR "./"
#endif

Q_DECLARE_METATYPE(QList<QContact>);

void UT_QVersit::testImportFiles()
{
    QFETCH(QString, filename);
    QFETCH(QByteArray, charset);
    QFETCH(QList<QContact>, expectedContacts);

    QVersitReader reader;
    QFile file(filename);
    QVERIFY2(file.open(QIODevice::ReadOnly), filename.toAscii());
    reader.setDevice(&file);
    if (charset != "") {
        reader.setDefaultCodec(QTextCodec::codecForName(charset));
    }
    QVERIFY(reader.startReading());
    QVERIFY(reader.waitForFinished());
    QList<QVersitDocument> documents = reader.results();
    QCOMPARE(reader.error(), QVersitReader::NoError);
    QVersitContactImporter importer;
    MyQVersitResourceHandler resourceHandler;
    importer.setResourceHandler(&resourceHandler);
    QList<QContact> contacts = importer.importContacts(documents);

    if (expectedContacts.size() > 0) {
        QCOMPARE(contacts.size(), expectedContacts.size());
        QListIterator<QContact> i(expectedContacts);
        foreach (QContact parsed, contacts) {
            QContact expected = i.next();
            QList<QContactDetail> expectedDetails = expected.details();
            foreach(QContactDetail expectedDetail, expectedDetails) {
                QString name = expectedDetail.definitionName();
                QContactDetail parsedDetail = parsed.detail(name);
                if (parsedDetail != expectedDetail) {
                    qDebug() << "Detail: " << name.toAscii();
                    qDebug() << "Actual:" << parsedDetail.values();
                    qDebug() << "Expected:" << expectedDetail.values();
                    QCOMPARE(parsedDetail, expectedDetail);
                }
            }
        }
    }
}

#define QTEST_NEW_ROW(filename,charset,contact) \
        QTest::newRow(filename) \
        << QString::fromAscii(TESTDATA_DIR "testdata/") + QString::fromAscii(filename) \
        << QByteArray(charset) \
        << (contact);

void UT_QVersit::testImportFiles_data()
{
    QTest::addColumn<QString>("filename");
    QTest::addColumn<QByteArray>("charset");
    QTest::addColumn<QList<QContact> >("expectedContacts");

    QTEST_NEW_ROW("AAB4/MultipleAll.vcf", "UTF-16BE", QList<QContact>());
    QTEST_NEW_ROW("AAB4/MultipleAscii.vcf", "", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleCompany.vcf", "", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleExtensive.vcf", "", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleNonAscii.vcf", "UTF-16BE", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleNonAsciiWithPhoto.vcf", "UTF-16BE", QList<QContact>());
    QTEST_NEW_ROW("AAB5/SingleNonAscii.vcf", "UTF-8", QList<QContact>());

    {
        QList<QContact> list;
        QContact contact;
        QContactName name;
        name.setCustomLabel(QLatin1String("Firstname Lastname"));
        name.setFirst(QLatin1String("Firstname"));
        name.setLast(QLatin1String("Lastname"));
        name.setMiddle(QString());
        name.setPrefix(QLatin1String("Title"));
        name.setSuffix(QLatin1String("Suffix"));
        contact.saveDetail(&name);
        QContactOrganization org;
        org.setName(QLatin1String("Company Name"));
        org.setDepartment(QStringList(QLatin1String("Department Name")));
        org.setTitle(QLatin1String("Job title"));
        contact.saveDetail(&org);
        list.append(contact);
        QContactNote note;
        note.setNote(QLatin1String("This is a note field.  Pretty boring."));
        contact.saveDetail(&note);
        QContactUrl homeUrl;
        homeUrl.setUrl(QLatin1String("http://mywebpage.com"));
        homeUrl.setContexts(QContactDetail::ContextHome);
        contact.saveDetail(&homeUrl);
        QContactUrl workUrl;
        workUrl.setUrl(QLatin1String("http://workwebpage"));
        workUrl.setContexts(QContactDetail::ContextWork);
        contact.saveDetail(&workUrl);
        QTEST_NEW_ROW("Entourage11/basic.vcf", "UTF-16BE", list);
    }

    QTEST_NEW_ROW("Entourage11/image.vcf", "UTF-16BE", QList<QContact>());

    QTEST_NEW_ROW("Entourage11/nonascii.vcf", "UTF-16BE", QList<QContact>());

    {
        QList<QContact> list;
        QContact contact;
        QContactName name;
        name.setCustomLabel(QLatin1String("first last"));
        name.setFirst(QLatin1String("first"));
        name.setLast(QLatin1String("last"));
        name.setMiddle(QString());
        name.setPrefix(QString());
        name.setSuffix(QString());
        contact.saveDetail(&name);
        QContactOrganization org;
        org.setName(QLatin1String("Nokia"));
        org.setDepartment(QStringList(QLatin1String("Qt DF")));
        contact.saveDetail(&org);
        list.append(contact);
        QTEST_NEW_ROW("Entourage12/basic.vcf", "", list);
    }

    QTEST_NEW_ROW("Entourage12/kevin.vcf", "UTF-8", QList<QContact>());
    QTEST_NEW_ROW("Entourage12/nonascii.vcf", "UTF-8", QList<QContact>());
    QTEST_NEW_ROW("gmail.vcf", "UTF-8", QList<QContact>());
}

QTEST_MAIN(UT_QVersit)
<commit_msg>Removed more usages of deprecated API<commit_after>#include "qversitdefs_p.h"
#include "ut_qversit.h"
#include "qversitreader.h"
#include "qversitreader_p.h"
#include "qversitcontactimporter.h"
#include "qcontact.h"
#include "qcontactmanager.h"

#include <QtTest/QtTest>
#include <QDebug>
#include <QDir>
#include <QList>

QTM_BEGIN_NAMESPACE
class MyQVersitResourceHandler : public QVersitResourceHandler
{
public:
    MyQVersitResourceHandler() : mIndex(0)
    {
    }

    bool saveResource(const QByteArray& contents, const QVersitProperty& property,
                      QString* location)
    {
        Q_UNUSED(property);
        *location = QString::number(mIndex++);
        mObjects.insert(*location, contents);
        return true;
    }

    bool loadResource(const QString &location, QByteArray *contents, QString *mimeType)
    {
        Q_UNUSED(location)
        Q_UNUSED(contents)
        Q_UNUSED(mimeType)
        return false;
    }

    int mIndex;
    QMap<QString, QByteArray> mObjects;
};
QTM_END_NAMESPACE

QTM_USE_NAMESPACE

#ifndef TESTDATA_DIR
#define TESTDATA_DIR "./"
#endif

Q_DECLARE_METATYPE(QList<QContact>);

void UT_QVersit::testImportFiles()
{
    QFETCH(QString, filename);
    QFETCH(QByteArray, charset);
    QFETCH(QList<QContact>, expectedContacts);

    QVersitReader reader;
    QFile file(filename);
    QVERIFY2(file.open(QIODevice::ReadOnly), filename.toAscii());
    reader.setDevice(&file);
    if (charset != "") {
        reader.setDefaultCodec(QTextCodec::codecForName(charset));
    }
    QVERIFY(reader.startReading());
    QVERIFY(reader.waitForFinished());
    QList<QVersitDocument> documents = reader.results();
    QCOMPARE(reader.error(), QVersitReader::NoError);
    QVersitContactImporter importer;
    MyQVersitResourceHandler resourceHandler;
    importer.setResourceHandler(&resourceHandler);
    QList<QContact> contacts = importer.importContacts(documents);

    if (expectedContacts.size() > 0) {
        QCOMPARE(contacts.size(), expectedContacts.size());
        QListIterator<QContact> i(expectedContacts);
        foreach (QContact parsed, contacts) {
            QContact expected = i.next();
            QList<QContactDetail> expectedDetails = expected.details();
            foreach(QContactDetail expectedDetail, expectedDetails) {
                QString name = expectedDetail.definitionName();
                QContactDetail parsedDetail = parsed.detail(name);
                if (parsedDetail != expectedDetail) {
                    qDebug() << "Detail: " << name.toAscii();
                    qDebug() << "Actual:" << parsedDetail.values();
                    qDebug() << "Expected:" << expectedDetail.values();
                    QCOMPARE(parsedDetail, expectedDetail);
                }
            }
        }
    }
}

#define QTEST_NEW_ROW(filename,charset,contact) \
        QTest::newRow(filename) \
        << QString::fromAscii(TESTDATA_DIR "testdata/") + QString::fromAscii(filename) \
        << QByteArray(charset) \
        << (contact);

void UT_QVersit::testImportFiles_data()
{
    QTest::addColumn<QString>("filename");
    QTest::addColumn<QByteArray>("charset");
    QTest::addColumn<QList<QContact> >("expectedContacts");

    QTEST_NEW_ROW("AAB4/MultipleAll.vcf", "UTF-16BE", QList<QContact>());
    QTEST_NEW_ROW("AAB4/MultipleAscii.vcf", "", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleCompany.vcf", "", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleExtensive.vcf", "", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleNonAscii.vcf", "UTF-16BE", QList<QContact>());
    QTEST_NEW_ROW("AAB4/SingleNonAsciiWithPhoto.vcf", "UTF-16BE", QList<QContact>());
    QTEST_NEW_ROW("AAB5/SingleNonAscii.vcf", "UTF-8", QList<QContact>());

    {
        QList<QContact> list;
        QContact contact;
        QContactName name;
        name.setCustomLabel(QLatin1String("Firstname Lastname"));
        name.setFirstName(QLatin1String("Firstname"));
        name.setLastName(QLatin1String("Lastname"));
        name.setMiddleName(QString());
        name.setPrefix(QLatin1String("Title"));
        name.setSuffix(QLatin1String("Suffix"));
        contact.saveDetail(&name);
        QContactOrganization org;
        org.setName(QLatin1String("Company Name"));
        org.setDepartment(QStringList(QLatin1String("Department Name")));
        org.setTitle(QLatin1String("Job title"));
        contact.saveDetail(&org);
        list.append(contact);
        QContactNote note;
        note.setNote(QLatin1String("This is a note field.  Pretty boring."));
        contact.saveDetail(&note);
        QContactUrl homeUrl;
        homeUrl.setUrl(QLatin1String("http://mywebpage.com"));
        homeUrl.setContexts(QContactDetail::ContextHome);
        contact.saveDetail(&homeUrl);
        QContactUrl workUrl;
        workUrl.setUrl(QLatin1String("http://workwebpage"));
        workUrl.setContexts(QContactDetail::ContextWork);
        contact.saveDetail(&workUrl);
        QTEST_NEW_ROW("Entourage11/basic.vcf", "UTF-16BE", list);
    }

    QTEST_NEW_ROW("Entourage11/image.vcf", "UTF-16BE", QList<QContact>());

    QTEST_NEW_ROW("Entourage11/nonascii.vcf", "UTF-16BE", QList<QContact>());

    {
        QList<QContact> list;
        QContact contact;
        QContactName name;
        name.setCustomLabel(QLatin1String("first last"));
        name.setFirstName(QLatin1String("first"));
        name.setLastName(QLatin1String("last"));
        name.setMiddleName(QString());
        name.setPrefix(QString());
        name.setSuffix(QString());
        contact.saveDetail(&name);
        QContactOrganization org;
        org.setName(QLatin1String("Nokia"));
        org.setDepartment(QStringList(QLatin1String("Qt DF")));
        contact.saveDetail(&org);
        list.append(contact);
        QTEST_NEW_ROW("Entourage12/basic.vcf", "", list);
    }

    QTEST_NEW_ROW("Entourage12/kevin.vcf", "UTF-8", QList<QContact>());
    QTEST_NEW_ROW("Entourage12/nonascii.vcf", "UTF-8", QList<QContact>());
    QTEST_NEW_ROW("gmail.vcf", "UTF-8", QList<QContact>());
}

QTEST_MAIN(UT_QVersit)
<|endoftext|>


<commit_before>#include "libfbjs/node.hpp"
#include "libfbjs/parser.hpp"

#include <iostream>
#include <string.h>
#include <map>

using namespace fbjs;
using namespace std;

typedef map<string, int> symbol_t;

#define for_nodes(p, i) \
  for (node_list_t::iterator i  = (p)->childNodes().begin(); \
                             i != (p)->childNodes().end(); \
                           ++i)

string get_static_member_symbol(Node *node);

void find_symbols(Node *node, symbol_t &installs, symbol_t &uses) {
  if (node == NULL) {
    return;
  }

  if (typeid(*node) == typeid(NodeStaticMemberExpression)) {
    string symbol = get_static_member_symbol(node);
    if (symbol[0] == 'J' && symbol[1] == 'X' && symbol[2] == '.') {
      uses[symbol] = node->lineno();
    }
  }

  if (typeid(*node) == typeid(NodeFunctionCall)) {
    Node *call = *node->childNodes().begin();
    if (static_cast<NodeStaticMemberExpression *>(call)) {
      if (get_static_member_symbol(call) == "JX.install") {
        NodeArgList *args = static_cast<NodeArgList*>(*(++node->childNodes().begin()));
        NodeStringLiteral* lit = static_cast<NodeStringLiteral*>(*args->childNodes().begin());
        installs[lit->unquoted_value()] = node->lineno();
      }
    }
  }

  for_nodes(node, ii) {
    find_symbols(*ii, installs, uses);
  }
}

string get_static_member_symbol(Node *node) {
  string symbol = "";
  if (node == NULL) {
    return symbol;
  }

  for_nodes(node, ii) {
    if (!(*ii)) {
      break;
    }
    if (typeid(**ii) == typeid(NodeIdentifier)) {
      NodeIdentifier *n = static_cast<NodeIdentifier *>(*ii);
      if (symbol.length()) {
        symbol += ".";
      }
      symbol += n->name();
    } else if (typeid(**ii) == typeid(NodeStaticMemberExpression)) {
      symbol += get_static_member_symbol(*ii);
    }
  }

  return symbol;
}

int main(int argc, char* argv[]) {
  try {
    NodeProgram root(stdin); // parses

    symbol_t installs;
    symbol_t uses;

    find_symbols(&root, installs, uses);

    for (symbol_t::iterator ii = installs.begin(); ii != installs.end(); ++ii) {
      cout << "+" << ii->first << ":" << ii->second << endl;
    }
    for (symbol_t::iterator ii = uses.begin(); ii != uses.end(); ++ii) {
      cout << "?" << ii->first << ":" << ii->second << endl;
    }

  } catch (ParseException ex) {
    printf("Parse Error: %s\n", ex.what());
    return 1;
  }
}
<commit_msg>[javelinsymbols] -- Add support to javelinsymbols for JX.behavior()<commit_after>#include "libfbjs/node.hpp"
#include "libfbjs/parser.hpp"

#include <iostream>
#include <string.h>
#include <map>

using namespace fbjs;
using namespace std;

typedef map<string, int> symbol_t;

#define for_nodes(p, i) \
  for (node_list_t::iterator i  = (p)->childNodes().begin(); \
                             i != (p)->childNodes().end(); \
                           ++i)

string get_static_member_symbol(Node *node);

void find_symbols(Node *node, symbol_t &installs, symbol_t &behaviors,
                  symbol_t &uses) {
  if (node == NULL) {
    return;
  }

  if (typeid(*node) == typeid(NodeStaticMemberExpression)) {
    string symbol = get_static_member_symbol(node);
    if (symbol[0] == 'J' && symbol[1] == 'X' && symbol[2] == '.') {
      uses[symbol] = node->lineno();
    }
  }

  if (typeid(*node) == typeid(NodeFunctionCall)) {
    Node *call = *node->childNodes().begin();
    if (static_cast<NodeStaticMemberExpression *>(call)) {
      string symbol = get_static_member_symbol(call);
      if (symbol == "JX.install" || symbol == "JX.behavior") {
        NodeArgList *args =
          static_cast<NodeArgList*>(*(++node->childNodes().begin()));
        NodeStringLiteral* lit =
          static_cast<NodeStringLiteral*>(*args->childNodes().begin());
        if (symbol == "JX.install") {
          installs[lit->unquoted_value()] = node->lineno();
        } else {
          behaviors[lit->unquoted_value()] = node->lineno();
        }
      }
    }
  }

  for_nodes(node, ii) {
    find_symbols(*ii, installs, behaviors, uses);
  }
}

string get_static_member_symbol(Node *node) {
  string symbol = "";
  if (node == NULL) {
    return symbol;
  }

  for_nodes(node, ii) {
    if (!(*ii)) {
      break;
    }
    if (typeid(**ii) == typeid(NodeIdentifier)) {
      NodeIdentifier *n = static_cast<NodeIdentifier *>(*ii);
      if (symbol.length()) {
        symbol += ".";
      }
      symbol += n->name();
    } else if (typeid(**ii) == typeid(NodeStaticMemberExpression)) {
      symbol += get_static_member_symbol(*ii);
    }
  }

  return symbol;
}

int main(int argc, char* argv[]) {
  try {
    NodeProgram root(stdin); // parses

    symbol_t installs;
    symbol_t behaviors;
    symbol_t uses;

    find_symbols(&root, installs, behaviors, uses);

    for (symbol_t::iterator ii = installs.begin(); ii != installs.end(); ++ii) {
      cout << "+" << ii->first << ":" << ii->second << endl;
    }
    for (symbol_t::iterator ii = behaviors.begin(); ii != behaviors.end(); ++ii) {
      cout << "*" << ii->first << ":" << ii->second << endl;
    }
    for (symbol_t::iterator ii = uses.begin(); ii != uses.end(); ++ii) {
      cout << "?" << ii->first << ":" << ii->second << endl;
    }

  } catch (ParseException ex) {
    printf("Parse Error: %s\n", ex.what());
    return 1;
  }
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/framework/dataset.h"

#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/platform/test.h"

namespace tensorflow {

REGISTER_DATASET_OP_NAME("DummyDatasetOp");

TEST(DatasetTest, RegisterDatasetOp) {
  EXPECT_TRUE(data::DatasetOpRegistry::IsRegistered("DummyDatasetOp"));
  EXPECT_FALSE(data::DatasetOpRegistry::IsRegistered("InvalidDatasetOp"));
}

enum DataTypeTest { _int32, _int64, _float, _double, _string };

struct DatasetTestParam {
  const DataTypeTest type;
  const std::vector<Tensor> tensor;
  const int64 expected_bytes;
};

class DatasetTestTotalBytes
    : public ::testing::TestWithParam<DatasetTestParam> {};

TEST_P(DatasetTestTotalBytes, TestTotalBytes) {
  const DatasetTestParam& test_case = GetParam();
  if (test_case.type == _string) {
    // TotalBytes() is approximate and gives an upper bound for strings
    EXPECT_LE(data::GetTotalBytes(test_case.tensor), test_case.expected_bytes);
  } else {
    EXPECT_EQ(data::GetTotalBytes(test_case.tensor), test_case.expected_bytes);
  }
}

std::vector<Tensor> tensor_int32s{test::AsTensor<int32>({1, 2, 3, 4, 5}),
                                  test::AsTensor<int32>({1, 2, 3, 4})};

std::vector<Tensor> tensor_int64s{test::AsTensor<int64>({1, 2, 3, 4, 5}),
                                  test::AsTensor<int64>({10, 12})};

std::vector<Tensor> tensor_floats{test::AsTensor<float>({1.0, 2.0, 3.0, 4.0})};

std::vector<Tensor> tensor_doubles{
    test::AsTensor<double>({100.0}), test::AsTensor<double>({200.0}),
    test::AsTensor<double>({400.0}), test::AsTensor<double>({800.0})};

const string str = "test string";  // NOLINT
std::vector<Tensor> tensor_strs{test::AsTensor<tstring>({str})};

const DatasetTestParam test_cases[] = {
    {_int32, tensor_int32s, 4 /*bytes*/ * 9 /*elements*/},
    {_int64, tensor_int64s, 8 /*bytes*/ * 7 /*elements*/},
    {_float, tensor_floats, 4 /*bytes*/ * 4 /*elements*/},
    {_double, tensor_doubles, 8 /*bytes*/ * 4 /*elements*/},
    {_string, tensor_strs,
     static_cast<int64>(sizeof(str) + str.size()) /*bytes*/},
};

INSTANTIATE_TEST_SUITE_P(DatasetTestTotalBytes, DatasetTestTotalBytes,
                         ::testing::ValuesIn(test_cases));

}  // namespace tensorflow
<commit_msg>Fix mismatch in expected_bytes of tstring tensor.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/framework/dataset.h"

#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/platform/test.h"

namespace tensorflow {

REGISTER_DATASET_OP_NAME("DummyDatasetOp");

TEST(DatasetTest, RegisterDatasetOp) {
  EXPECT_TRUE(data::DatasetOpRegistry::IsRegistered("DummyDatasetOp"));
  EXPECT_FALSE(data::DatasetOpRegistry::IsRegistered("InvalidDatasetOp"));
}

enum DataTypeTest { _int32, _int64, _float, _double, _string };

struct DatasetTestParam {
  const DataTypeTest type;
  const std::vector<Tensor> tensor;
  const int64 expected_bytes;
};

class DatasetTestTotalBytes
    : public ::testing::TestWithParam<DatasetTestParam> {};

TEST_P(DatasetTestTotalBytes, TestTotalBytes) {
  const DatasetTestParam& test_case = GetParam();
  if (test_case.type == _string) {
    // TotalBytes() is approximate and gives an upper bound for strings
    EXPECT_LE(data::GetTotalBytes(test_case.tensor), test_case.expected_bytes);
  } else {
    EXPECT_EQ(data::GetTotalBytes(test_case.tensor), test_case.expected_bytes);
  }
}

std::vector<Tensor> tensor_int32s{test::AsTensor<int32>({1, 2, 3, 4, 5}),
                                  test::AsTensor<int32>({1, 2, 3, 4})};

std::vector<Tensor> tensor_int64s{test::AsTensor<int64>({1, 2, 3, 4, 5}),
                                  test::AsTensor<int64>({10, 12})};

std::vector<Tensor> tensor_floats{test::AsTensor<float>({1.0, 2.0, 3.0, 4.0})};

std::vector<Tensor> tensor_doubles{
    test::AsTensor<double>({100.0}), test::AsTensor<double>({200.0}),
    test::AsTensor<double>({400.0}), test::AsTensor<double>({800.0})};

const tstring str = "test string";  // NOLINT
std::vector<Tensor> tensor_strs{test::AsTensor<tstring>({str})};

const DatasetTestParam test_cases[] = {
    {_int32, tensor_int32s, 4 /*bytes*/ * 9 /*elements*/},
    {_int64, tensor_int64s, 8 /*bytes*/ * 7 /*elements*/},
    {_float, tensor_floats, 4 /*bytes*/ * 4 /*elements*/},
    {_double, tensor_doubles, 8 /*bytes*/ * 4 /*elements*/},
    {_string, tensor_strs,
     static_cast<int64>(sizeof(str) + str.size()) /*bytes*/},
};

INSTANTIATE_TEST_SUITE_P(DatasetTestTotalBytes, DatasetTestTotalBytes,
                         ::testing::ValuesIn(test_cases));

}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/framework/dataset.h"

#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/platform/test.h"

namespace tensorflow {

REGISTER_DATASET_OP_NAME("DummyDatasetOp");

TEST(DatasetTest, RegisterDatasetOp) {
  EXPECT_TRUE(data::DatasetOpRegistry::IsRegistered("DummyDatasetOp"));
  EXPECT_FALSE(data::DatasetOpRegistry::IsRegistered("InvalidDatasetOp"));
}

enum DataTypeTest {
  _tf_int_32,
  _tf_int_64,
  _tf_float_,
  _tf_double_,
  _tf_string_
};

struct DatasetTestParam {
  const DataTypeTest type;
  const std::vector<Tensor> tensor;
  const int64 expected_bytes;
};

class DatasetTestTotalBytes
    : public ::testing::TestWithParam<DatasetTestParam> {};

TEST_P(DatasetTestTotalBytes, TestTotalBytes) {
  const DatasetTestParam& test_case = GetParam();
  if (test_case.type == _tf_string_) {
    // TotalBytes() is approximate and gives an upper bound for strings
    EXPECT_LE(data::GetTotalBytes(test_case.tensor), test_case.expected_bytes);
  } else {
    EXPECT_EQ(data::GetTotalBytes(test_case.tensor), test_case.expected_bytes);
  }
}

std::vector<Tensor> tensor_tf_int_32s{test::AsTensor<int32>({1, 2, 3, 4, 5}),
                                      test::AsTensor<int32>({1, 2, 3, 4})};

std::vector<Tensor> tensor_tf_int_64s{test::AsTensor<int64>({1, 2, 3, 4, 5}),
                                      test::AsTensor<int64>({10, 12})};

std::vector<Tensor> tensor_tf_float_s{
    test::AsTensor<float>({1.0, 2.0, 3.0, 4.0})};

std::vector<Tensor> tensor_tf_double_s{
    test::AsTensor<double>({100.0}), test::AsTensor<double>({200.0}),
    test::AsTensor<double>({400.0}), test::AsTensor<double>({800.0})};

const tstring str = "test string";  // NOLINT
std::vector<Tensor> tensor_strs{test::AsTensor<tstring>({str})};

const DatasetTestParam test_cases[] = {
    {_tf_int_32, tensor_tf_int_32s, 4 /*bytes*/ * 9 /*elements*/},
    {_tf_int_64, tensor_tf_int_64s, 8 /*bytes*/ * 7 /*elements*/},
    {_tf_float_, tensor_tf_float_s, 4 /*bytes*/ * 4 /*elements*/},
    {_tf_double_, tensor_tf_double_s, 8 /*bytes*/ * 4 /*elements*/},
    {_tf_string_, tensor_strs,
     static_cast<int64>(sizeof(str) + str.size()) /*bytes*/},
};

INSTANTIATE_TEST_SUITE_P(DatasetTestTotalBytes, DatasetTestTotalBytes,
                         ::testing::ValuesIn(test_cases));

}  // namespace tensorflow
<commit_msg>Avoid creating tensors as global variables in dataset_test<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/framework/dataset.h"

#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/platform/test.h"

namespace tensorflow {

REGISTER_DATASET_OP_NAME("DummyDatasetOp");

TEST(DatasetTest, RegisterDatasetOp) {
  EXPECT_TRUE(data::DatasetOpRegistry::IsRegistered("DummyDatasetOp"));
  EXPECT_FALSE(data::DatasetOpRegistry::IsRegistered("InvalidDatasetOp"));
}

enum DataTypeTest {
  _tf_int_32,
  _tf_int_64,
  _tf_float_,
  _tf_double_,
  _tf_string_
};

struct DatasetTestParam {
  const DataTypeTest type;
  // This has to be a function pointer, to make sure the tensors we use as
  // parameters of the test case do not become globals. Ordering of static
  // initializers and globals can cause errors in the test.
  std::function<std::vector<Tensor>()> tensor_factory;
  const int64 expected_bytes;
};

class DatasetTestTotalBytes
    : public ::testing::TestWithParam<DatasetTestParam> {};

TEST_P(DatasetTestTotalBytes, TestTotalBytes) {
  const DatasetTestParam& test_case = GetParam();
  if (test_case.type == _tf_string_) {
    // TotalBytes() is approximate and gives an upper bound for strings
    EXPECT_LE(data::GetTotalBytes(test_case.tensor_factory()),
              test_case.expected_bytes);
  } else {
    EXPECT_EQ(data::GetTotalBytes(test_case.tensor_factory()),
              test_case.expected_bytes);
  }
}

std::vector<Tensor> tensor_tf_int_32s() {
  return {test::AsTensor<int32>({1, 2, 3, 4, 5}),
          test::AsTensor<int32>({1, 2, 3, 4})};
}

std::vector<Tensor> tensor_tf_int_64s() {
  return {test::AsTensor<int64>({1, 2, 3, 4, 5}),
          test::AsTensor<int64>({10, 12})};
}

std::vector<Tensor> tensor_tf_float_s() {
  return {test::AsTensor<float>({1.0, 2.0, 3.0, 4.0})};
}

std::vector<Tensor> tensor_tf_double_s() {
  return {test::AsTensor<double>({100.0}), test::AsTensor<double>({200.0}),
          test::AsTensor<double>({400.0}), test::AsTensor<double>({800.0})};
}

const tstring str = "test string";  // NOLINT
std::vector<Tensor> tensor_strs() { return {test::AsTensor<tstring>({str})}; }

INSTANTIATE_TEST_SUITE_P(
    DatasetTestTotalBytes, DatasetTestTotalBytes,
    ::testing::ValuesIn(std::vector<DatasetTestParam>{
        {_tf_int_32, tensor_tf_int_32s, 4 /*bytes*/ * 9 /*elements*/},
        {_tf_int_64, tensor_tf_int_64s, 8 /*bytes*/ * 7 /*elements*/},
        {_tf_float_, tensor_tf_float_s, 4 /*bytes*/ * 4 /*elements*/},
        {_tf_double_, tensor_tf_double_s, 8 /*bytes*/ * 4 /*elements*/},
        {_tf_string_, tensor_strs,
         static_cast<int64>(sizeof(str) + str.size()) /*bytes*/}}));

}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2019 Google LLC. All Rights Reserved.

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 "tensorflow/lite/experimental/ruy/trace.h"

#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <vector>

#include "tensorflow/lite/experimental/ruy/block_map.h"
#include "tensorflow/lite/experimental/ruy/check_macros.h"
#include "tensorflow/lite/experimental/ruy/common.h"
#include "tensorflow/lite/experimental/ruy/time.h"

namespace ruy {

#ifdef RUY_TRACE

struct BlockTraceEntry {
  std::uint32_t thread_id = 0;
  TimePoint time_reserved;
  TimePoint time_computed_coords;
  TimePoint time_packed_lhs;
  TimePoint time_packed_rhs;
  TimePoint time_finished;
};

struct ThreadTraceEntry {
  TimePoint time_start;
  TimePoint time_loop_start;
  TimePoint time_end;
};

struct Trace {
  enum class LifeStage {
    kInitial,
    kRecordingRootFields,
    kRecordingBlockAndThreadFields,
    kComplete
  };
  void StartRecordingBlockAndThreadFields(const BlockMap& block_map_,
                                          int thread_count_) {
    RUY_DCHECK(life_stage == LifeStage::kRecordingRootFields);
    block_map = block_map_;
    thread_count = thread_count_;
    int num_blocks = NumBlocks(block_map);
    if (num_blocks > block_entries.size()) {
      block_entries.resize(NumBlocks(block_map));
    }
    if (thread_count > thread_entries.size()) {
      thread_entries.resize(thread_count);
    }
    life_stage = LifeStage::kRecordingBlockAndThreadFields;
  }
  BlockMap block_map;
  int thread_count = 0;
  std::vector<BlockTraceEntry> block_entries;
  std::vector<ThreadTraceEntry> thread_entries;
  TimePoint time_start;
  TimePoint time_execute;
  TimePoint time_end;
  LifeStage life_stage = LifeStage::kInitial;
};

struct ProcessedTrace {
  enum class Event : std::uint8_t {
    kNone,
    kThreadStart,
    kThreadLoopStart,
    kThreadEnd,
    kBlockReserved,
    kBlockComputedCoords,
    kBlockPackedLhs,
    kBlockPackedRhs,
    kBlockFinished
  };
  struct Entry {
    Event event = Event::kNone;
    std::uint32_t thread_id = 0;
    std::uint32_t block_id = 0;
    TimePoint time;
  };

  BlockMap block_map;
  int thread_count = 0;
  TimePoint time_start;
  TimePoint time_execute;
  TimePoint time_end;
  std::vector<Entry> entries;
  void Add(Event event, std::uint32_t thread_id, std::uint32_t block_id,
           TimePoint time) {
    // If the time point is still in its default-constructed state,
    // that means we didn't record it.
    if (!time.time_since_epoch().count()) {
      return;
    }
    Entry entry;
    entry.event = event;
    entry.thread_id = thread_id;
    entry.block_id = block_id;
    entry.time = time;
    entries.push_back(entry);
  }
  void Process(const Trace& trace) {
    thread_count = trace.thread_count;
    block_map = trace.block_map;
    time_start = trace.time_start;
    time_execute = trace.time_execute;
    time_end = trace.time_end;
    entries.clear();
    for (int i = 0; i < trace.thread_count; i++) {
      const auto& entry = trace.thread_entries[i];
      Add(Event::kThreadStart, i, 0, entry.time_start);
      Add(Event::kThreadLoopStart, i, 0, entry.time_loop_start);
      Add(Event::kThreadEnd, i, 0, entry.time_end);
    }
    std::uint32_t num_blocks = NumBlocks(block_map);
    for (int i = 0; i < num_blocks; i++) {
      const auto& entry = trace.block_entries[i];
      Add(Event::kBlockReserved, entry.thread_id, i, entry.time_reserved);
      Add(Event::kBlockComputedCoords, entry.thread_id, i,
          entry.time_computed_coords);
      Add(Event::kBlockPackedLhs, entry.thread_id, i, entry.time_packed_lhs);
      Add(Event::kBlockPackedRhs, entry.thread_id, i, entry.time_packed_rhs);
      Add(Event::kBlockFinished, entry.thread_id, i, entry.time_finished);
    }
    std::sort(entries.begin(), entries.end(),
              [](const Entry& a, const Entry& b) -> bool {
                return a.time < b.time ||
                       (a.time == b.time &&
                        static_cast<int>(a.event) < static_cast<int>(b.event));
              });
  }
  void Dump() {
    const char* trace_filename = getenv("RUY_TRACE_FILE");
    FILE* trace_file = trace_filename ? fopen(trace_filename, "w") : stderr;
    if (!trace_file) {
      fprintf(stderr, "Failed to open %s for write, errno=%d\n", trace_filename,
              errno);
      RUY_CHECK(false);
    }
    fprintf(trace_file, "thread_count:%d\n", thread_count);
    fprintf(trace_file, "num_blocks:%d\n", NumBlocks(block_map));
    fprintf(trace_file, "rows:%d\n", block_map.rows);
    fprintf(trace_file, "cols:%d\n", block_map.cols);
    fprintf(trace_file, "Execute: %.9f\n",
            ToSeconds(time_execute - time_start));
    for (const Entry& entry : entries) {
      double time = ToSeconds(entry.time - time_start);
      switch (entry.event) {
        case Event::kThreadStart:
          fprintf(trace_file, "ThreadStart: %.9f, %d\n", time, entry.thread_id);
          break;
        case Event::kThreadLoopStart:
          fprintf(trace_file, "ThreadLoopStart: %.9f, %d\n", time,
                  entry.thread_id);
          break;
        case Event::kThreadEnd:
          fprintf(trace_file, "ThreadEnd: %.9f, %d\n", time, entry.thread_id);
          break;
        case Event::kBlockReserved: {
          std::uint16_t block_r, block_c;
          int start_r, start_c, end_r, end_c;
          GetBlockByIndex(block_map, entry.block_id, &block_r, &block_c);
          GetBlockMatrixCoords(block_map, block_r, block_c, &start_r, &start_c,
                               &end_r, &end_c);
          fprintf(trace_file, "BlockReserved: %.9f, %d, %d, %d, %d, %d, %d\n",
                  time, entry.thread_id, entry.block_id, start_r, start_c,
                  end_r, end_c);
          break;
        }
        case Event::kBlockComputedCoords:
          fprintf(trace_file, "BlockComputedCoords: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        case Event::kBlockPackedLhs:
          fprintf(trace_file, "BlockPackedLhs: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        case Event::kBlockPackedRhs:
          fprintf(trace_file, "BlockPackedRhs: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        case Event::kBlockFinished:
          fprintf(trace_file, "BlockFinished: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        default:
          RUY_CHECK(false);
      }
    }
    fprintf(trace_file, "End: %.9f\n", ToSeconds(time_end - time_start));
    if (trace_filename) {
      fclose(trace_file);
    }
  }
};

void DumpTrace(const Trace& trace) {
  ProcessedTrace processed_trace;
  processed_trace.Process(trace);
  processed_trace.Dump();
}

Trace* NewTraceOrNull(TracingContext* tracing, int rows, int depth, int cols) {
  if (!tracing->initialized) {
    tracing->initialized = true;
    tracing->enabled = getenv("RUY_TRACE");
    if (!tracing->enabled) {
      return nullptr;
    }
    if (getenv("RUY_TRACE_FILTER_ROWS")) {
      tracing->filter_shape_rows = std::stoi(getenv("RUY_TRACE_FILTER_ROWS"));
    }
    if (getenv("RUY_TRACE_FILTER_DEPTH")) {
      tracing->filter_shape_depth = std::stoi(getenv("RUY_TRACE_FILTER_DEPTH"));
    }
    if (getenv("RUY_TRACE_FILTER_COLS")) {
      tracing->filter_shape_cols = std::stoi(getenv("RUY_TRACE_FILTER_COLS"));
    }
  }
  if (!tracing->enabled) {
    return nullptr;
  }
  if (tracing->filter_shape_rows && rows != tracing->filter_shape_rows) {
    return nullptr;
  }
  if (tracing->filter_shape_depth && depth != tracing->filter_shape_depth) {
    return nullptr;
  }
  if (tracing->filter_shape_cols && cols != tracing->filter_shape_cols) {
    return nullptr;
  }
  // Delete any existing trace.
  delete tracing->trace;
  // Create a new one.
  tracing->trace = new Trace;
  return tracing->trace;
}

TracingContext::~TracingContext() {
  if (trace) {
    DumpTrace(*trace);
  }
  delete trace;
}

void TraceRecordThreadStart(std::uint32_t thread_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    relaxed_atomic_store(&trace->block_entries[thread_id].thread_id, thread_id);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[thread_id].time_reserved, now);
    relaxed_atomic_store(&trace->thread_entries[thread_id].time_start, now);
  }
}

void TraceRecordThreadLoopStart(std::uint32_t thread_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->thread_entries[thread_id].time_loop_start,
                         now);
  }
}

void TraceRecordBlockReserved(std::uint32_t thread_id, std::uint32_t block_id,
                              Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    // This is typically called on the next block id just obtained by atomic
    // increment; this may be out of range.
    if (block_id < trace->block_entries.size()) {
      relaxed_atomic_store(&trace->block_entries[block_id].thread_id,
                           thread_id);
      TimePoint now = Clock::now();
      relaxed_atomic_store(&trace->block_entries[block_id].time_reserved, now);
    }
  }
}

void TraceRecordBlockCoordsComputed(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_computed_coords,
                         now);
  }
}

void TraceRecordBlockPackedLhs(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_packed_lhs, now);
  }
}

void TraceRecordBlockPackedRhs(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_packed_rhs, now);
  }
}

void TraceRecordBlockFinished(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_finished, now);
  }
}

void TraceRecordThreadEnd(std::uint32_t thread_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->thread_entries[thread_id].time_end, now);
  }
}

void TraceRecordStart(Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage == Trace::LifeStage::kInitial ||
               trace->life_stage == Trace::LifeStage::kComplete);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->time_start, now);
    trace->life_stage = Trace::LifeStage::kRecordingRootFields;
  }
}

void TraceRecordExecute(Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage == Trace::LifeStage::kRecordingRootFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->time_execute, now);
  }
}

void TraceRecordEnd(Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->time_end, now);
    trace->life_stage = Trace::LifeStage::kComplete;
  }
}

void TraceStartRecordingBlockAndThreadFields(const BlockMap& block_map,
                                             int thread_count, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage == Trace::LifeStage::kRecordingRootFields);
    trace->StartRecordingBlockAndThreadFields(block_map, thread_count);
    trace->life_stage = Trace::LifeStage::kRecordingBlockAndThreadFields;
  }
}

#endif

}  // namespace ruy
<commit_msg>Missing headers / fix compilation with ruy tracing.<commit_after>/* Copyright 2019 Google LLC. All Rights Reserved.

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 "tensorflow/lite/experimental/ruy/trace.h"

#include <algorithm>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>

#include "tensorflow/lite/experimental/ruy/block_map.h"
#include "tensorflow/lite/experimental/ruy/check_macros.h"
#include "tensorflow/lite/experimental/ruy/common.h"
#include "tensorflow/lite/experimental/ruy/time.h"

namespace ruy {

#ifdef RUY_TRACE

struct BlockTraceEntry {
  std::uint32_t thread_id = 0;
  TimePoint time_reserved;
  TimePoint time_computed_coords;
  TimePoint time_packed_lhs;
  TimePoint time_packed_rhs;
  TimePoint time_finished;
};

struct ThreadTraceEntry {
  TimePoint time_start;
  TimePoint time_loop_start;
  TimePoint time_end;
};

struct Trace {
  enum class LifeStage {
    kInitial,
    kRecordingRootFields,
    kRecordingBlockAndThreadFields,
    kComplete
  };
  void StartRecordingBlockAndThreadFields(const BlockMap& block_map_,
                                          int thread_count_) {
    RUY_DCHECK(life_stage == LifeStage::kRecordingRootFields);
    block_map = block_map_;
    thread_count = thread_count_;
    int num_blocks = NumBlocks(block_map);
    if (num_blocks > block_entries.size()) {
      block_entries.resize(NumBlocks(block_map));
    }
    if (thread_count > thread_entries.size()) {
      thread_entries.resize(thread_count);
    }
    life_stage = LifeStage::kRecordingBlockAndThreadFields;
  }
  BlockMap block_map;
  int thread_count = 0;
  std::vector<BlockTraceEntry> block_entries;
  std::vector<ThreadTraceEntry> thread_entries;
  TimePoint time_start;
  TimePoint time_execute;
  TimePoint time_end;
  LifeStage life_stage = LifeStage::kInitial;
};

struct ProcessedTrace {
  enum class Event : std::uint8_t {
    kNone,
    kThreadStart,
    kThreadLoopStart,
    kThreadEnd,
    kBlockReserved,
    kBlockComputedCoords,
    kBlockPackedLhs,
    kBlockPackedRhs,
    kBlockFinished
  };
  struct Entry {
    Event event = Event::kNone;
    std::uint32_t thread_id = 0;
    std::uint32_t block_id = 0;
    TimePoint time;
  };

  BlockMap block_map;
  int thread_count = 0;
  TimePoint time_start;
  TimePoint time_execute;
  TimePoint time_end;
  std::vector<Entry> entries;
  void Add(Event event, std::uint32_t thread_id, std::uint32_t block_id,
           TimePoint time) {
    // If the time point is still in its default-constructed state,
    // that means we didn't record it.
    if (!time.time_since_epoch().count()) {
      return;
    }
    Entry entry;
    entry.event = event;
    entry.thread_id = thread_id;
    entry.block_id = block_id;
    entry.time = time;
    entries.push_back(entry);
  }
  void Process(const Trace& trace) {
    thread_count = trace.thread_count;
    block_map = trace.block_map;
    time_start = trace.time_start;
    time_execute = trace.time_execute;
    time_end = trace.time_end;
    entries.clear();
    for (int i = 0; i < trace.thread_count; i++) {
      const auto& entry = trace.thread_entries[i];
      Add(Event::kThreadStart, i, 0, entry.time_start);
      Add(Event::kThreadLoopStart, i, 0, entry.time_loop_start);
      Add(Event::kThreadEnd, i, 0, entry.time_end);
    }
    std::uint32_t num_blocks = NumBlocks(block_map);
    for (int i = 0; i < num_blocks; i++) {
      const auto& entry = trace.block_entries[i];
      Add(Event::kBlockReserved, entry.thread_id, i, entry.time_reserved);
      Add(Event::kBlockComputedCoords, entry.thread_id, i,
          entry.time_computed_coords);
      Add(Event::kBlockPackedLhs, entry.thread_id, i, entry.time_packed_lhs);
      Add(Event::kBlockPackedRhs, entry.thread_id, i, entry.time_packed_rhs);
      Add(Event::kBlockFinished, entry.thread_id, i, entry.time_finished);
    }
    std::sort(entries.begin(), entries.end(),
              [](const Entry& a, const Entry& b) -> bool {
                return a.time < b.time ||
                       (a.time == b.time &&
                        static_cast<int>(a.event) < static_cast<int>(b.event));
              });
  }
  void Dump() {
    const char* trace_filename = getenv("RUY_TRACE_FILE");
    FILE* trace_file = trace_filename ? fopen(trace_filename, "w") : stderr;
    if (!trace_file) {
      fprintf(stderr, "Failed to open %s for write, errno=%d\n", trace_filename,
              errno);
      RUY_CHECK(false);
    }
    fprintf(trace_file, "thread_count:%d\n", thread_count);
    fprintf(trace_file, "num_blocks:%d\n", NumBlocks(block_map));
    fprintf(trace_file, "rows:%d\n", block_map.rows);
    fprintf(trace_file, "cols:%d\n", block_map.cols);
    fprintf(trace_file, "Execute: %.9f\n",
            ToSeconds(time_execute - time_start));
    for (const Entry& entry : entries) {
      double time = ToSeconds(entry.time - time_start);
      switch (entry.event) {
        case Event::kThreadStart:
          fprintf(trace_file, "ThreadStart: %.9f, %d\n", time, entry.thread_id);
          break;
        case Event::kThreadLoopStart:
          fprintf(trace_file, "ThreadLoopStart: %.9f, %d\n", time,
                  entry.thread_id);
          break;
        case Event::kThreadEnd:
          fprintf(trace_file, "ThreadEnd: %.9f, %d\n", time, entry.thread_id);
          break;
        case Event::kBlockReserved: {
          std::uint16_t block_r, block_c;
          int start_r, start_c, end_r, end_c;
          GetBlockByIndex(block_map, entry.block_id, &block_r, &block_c);
          GetBlockMatrixCoords(block_map, block_r, block_c, &start_r, &start_c,
                               &end_r, &end_c);
          fprintf(trace_file, "BlockReserved: %.9f, %d, %d, %d, %d, %d, %d\n",
                  time, entry.thread_id, entry.block_id, start_r, start_c,
                  end_r, end_c);
          break;
        }
        case Event::kBlockComputedCoords:
          fprintf(trace_file, "BlockComputedCoords: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        case Event::kBlockPackedLhs:
          fprintf(trace_file, "BlockPackedLhs: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        case Event::kBlockPackedRhs:
          fprintf(trace_file, "BlockPackedRhs: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        case Event::kBlockFinished:
          fprintf(trace_file, "BlockFinished: %.9f, %d, %d\n", time,
                  entry.thread_id, entry.block_id);
          break;
        default:
          RUY_CHECK(false);
      }
    }
    fprintf(trace_file, "End: %.9f\n", ToSeconds(time_end - time_start));
    if (trace_filename) {
      fclose(trace_file);
    }
  }
};

void DumpTrace(const Trace& trace) {
  ProcessedTrace processed_trace;
  processed_trace.Process(trace);
  processed_trace.Dump();
}

Trace* NewTraceOrNull(TracingContext* tracing, int rows, int depth, int cols) {
  if (!tracing->initialized) {
    tracing->initialized = true;
    tracing->enabled = getenv("RUY_TRACE");
    if (!tracing->enabled) {
      return nullptr;
    }
    if (getenv("RUY_TRACE_FILTER_ROWS")) {
      tracing->filter_shape_rows = std::stoi(getenv("RUY_TRACE_FILTER_ROWS"));
    }
    if (getenv("RUY_TRACE_FILTER_DEPTH")) {
      tracing->filter_shape_depth = std::stoi(getenv("RUY_TRACE_FILTER_DEPTH"));
    }
    if (getenv("RUY_TRACE_FILTER_COLS")) {
      tracing->filter_shape_cols = std::stoi(getenv("RUY_TRACE_FILTER_COLS"));
    }
  }
  if (!tracing->enabled) {
    return nullptr;
  }
  if (tracing->filter_shape_rows && rows != tracing->filter_shape_rows) {
    return nullptr;
  }
  if (tracing->filter_shape_depth && depth != tracing->filter_shape_depth) {
    return nullptr;
  }
  if (tracing->filter_shape_cols && cols != tracing->filter_shape_cols) {
    return nullptr;
  }
  // Delete any existing trace.
  delete tracing->trace;
  // Create a new one.
  tracing->trace = new Trace;
  return tracing->trace;
}

TracingContext::~TracingContext() {
  if (trace) {
    DumpTrace(*trace);
  }
  delete trace;
}

void TraceRecordThreadStart(std::uint32_t thread_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    relaxed_atomic_store(&trace->block_entries[thread_id].thread_id, thread_id);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[thread_id].time_reserved, now);
    relaxed_atomic_store(&trace->thread_entries[thread_id].time_start, now);
  }
}

void TraceRecordThreadLoopStart(std::uint32_t thread_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->thread_entries[thread_id].time_loop_start,
                         now);
  }
}

void TraceRecordBlockReserved(std::uint32_t thread_id, std::uint32_t block_id,
                              Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    // This is typically called on the next block id just obtained by atomic
    // increment; this may be out of range.
    if (block_id < trace->block_entries.size()) {
      relaxed_atomic_store(&trace->block_entries[block_id].thread_id,
                           thread_id);
      TimePoint now = Clock::now();
      relaxed_atomic_store(&trace->block_entries[block_id].time_reserved, now);
    }
  }
}

void TraceRecordBlockCoordsComputed(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_computed_coords,
                         now);
  }
}

void TraceRecordBlockPackedLhs(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_packed_lhs, now);
  }
}

void TraceRecordBlockPackedRhs(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_packed_rhs, now);
  }
}

void TraceRecordBlockFinished(std::uint32_t block_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->block_entries[block_id].time_finished, now);
  }
}

void TraceRecordThreadEnd(std::uint32_t thread_id, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->thread_entries[thread_id].time_end, now);
  }
}

void TraceRecordStart(Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage == Trace::LifeStage::kInitial ||
               trace->life_stage == Trace::LifeStage::kComplete);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->time_start, now);
    trace->life_stage = Trace::LifeStage::kRecordingRootFields;
  }
}

void TraceRecordExecute(Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage == Trace::LifeStage::kRecordingRootFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->time_execute, now);
  }
}

void TraceRecordEnd(Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage ==
               Trace::LifeStage::kRecordingBlockAndThreadFields);
    TimePoint now = Clock::now();
    relaxed_atomic_store(&trace->time_end, now);
    trace->life_stage = Trace::LifeStage::kComplete;
  }
}

void TraceStartRecordingBlockAndThreadFields(const BlockMap& block_map,
                                             int thread_count, Trace* trace) {
  if (trace) {
    RUY_DCHECK(trace->life_stage == Trace::LifeStage::kRecordingRootFields);
    trace->StartRecordingBlockAndThreadFields(block_map, thread_count);
    trace->life_stage = Trace::LifeStage::kRecordingBlockAndThreadFields;
  }
}

#endif

}  // namespace ruy
<|endoftext|>


<commit_before>/**
 * \file
 * \brief mutexTestTryLockWhenLocked() implementation
 *
 * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "mutexTestTryLockWhenLocked.hpp"

#include "waitForNextTick.hpp"

#include "distortos/DynamicThread.hpp"
#include "distortos/Mutex.hpp"

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {256};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

bool mutexTestTryLockWhenLocked(Mutex& mutex, const uint8_t priority)
{
	bool sharedRet {};
	auto tryLockThreadObject = makeDynamicThread({testThreadStackSize, priority},
			[&mutex, &sharedRet]()
			{
				const auto start = TickClock::now();
				const auto ret = mutex.tryLock();
				sharedRet = ret == EBUSY && start == TickClock::now();
			});
	waitForNextTick();
	tryLockThreadObject.start();
	tryLockThreadObject.join();

	return sharedRet;
}

}	// namespace test

}	// namespace distortos
<commit_msg>test: include <cerrno> in mutexTestTryLockWhenLocked.cpp<commit_after>/**
 * \file
 * \brief mutexTestTryLockWhenLocked() implementation
 *
 * \author Copyright (C) 2014-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "mutexTestTryLockWhenLocked.hpp"

#include "waitForNextTick.hpp"

#include "distortos/DynamicThread.hpp"
#include "distortos/Mutex.hpp"

#include <cerrno>

namespace distortos
{

namespace test
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {256};

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

bool mutexTestTryLockWhenLocked(Mutex& mutex, const uint8_t priority)
{
	bool sharedRet {};
	auto tryLockThreadObject = makeDynamicThread({testThreadStackSize, priority},
			[&mutex, &sharedRet]()
			{
				const auto start = TickClock::now();
				const auto ret = mutex.tryLock();
				sharedRet = ret == EBUSY && start == TickClock::now();
			});
	waitForNextTick();
	tryLockThreadObject.start();
	tryLockThreadObject.join();

	return sharedRet;
}

}	// namespace test

}	// namespace distortos
<|endoftext|>


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

#include "base/strings/stringprintf.h"
#include "chrome/browser/apps/app_browsertest_util.h"
#include "components/guest_view/browser/guest_view_manager.h"
#include "components/guest_view/browser/guest_view_manager_factory.h"
#include "components/guest_view/browser/test_guest_view_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/guest_view/app_view/app_view_guest.h"
#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"

using guest_view::GuestViewManager;
using guest_view::TestGuestViewManagerFactory;

namespace {

class RenderProcessHostObserverForExit
    : public content::RenderProcessHostObserver {
 public:
  explicit RenderProcessHostObserverForExit(
      content::RenderProcessHost* observed_host)
      : render_process_host_exited_(false), observed_host_(observed_host) {
    observed_host->AddObserver(this);
  }

  void WaitUntilRenderProcessHostKilled() {
    if (render_process_host_exited_)
      return;
    message_loop_runner_ = new content::MessageLoopRunner;
    message_loop_runner_->Run();
  }

  base::TerminationStatus termination_status() const { return status_; }

 private:
  void RenderProcessExited(content::RenderProcessHost* host,
                           base::TerminationStatus status,
                           int exit_code) override {
    DCHECK(observed_host_ == host);
    render_process_host_exited_ = true;
    status_ = status;
    observed_host_->RemoveObserver(this);
    if (message_loop_runner_.get()) {
      message_loop_runner_->Quit();
    }
  }

  bool render_process_host_exited_;
  content::RenderProcessHost* observed_host_;
  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
  base::TerminationStatus status_;

  DISALLOW_COPY_AND_ASSIGN(RenderProcessHostObserverForExit);
};

}  // namespace

class AppViewTest : public extensions::PlatformAppBrowserTest {
 public:
  AppViewTest() {
    GuestViewManager::set_factory_for_testing(&factory_);
  }

  enum TestServer {
    NEEDS_TEST_SERVER,
    NO_TEST_SERVER
  };

  void TestHelper(const std::string& test_name,
                  const std::string& app_location,
                  const std::string& app_to_embed,
                  TestServer test_server) {
    // For serving guest pages.
    if (test_server == NEEDS_TEST_SERVER) {
      if (!StartEmbeddedTestServer()) {
        LOG(ERROR) << "FAILED TO START TEST SERVER.";
        return;
      }
    }

    LoadAndLaunchPlatformApp(app_location.c_str(), "Launched");

    // Flush any pending events to make sure we start with a clean slate.
    content::RunAllPendingInMessageLoop();

    content::WebContents* embedder_web_contents =
        GetFirstAppWindowWebContents();
    if (!embedder_web_contents) {
      LOG(ERROR) << "UNABLE TO FIND EMBEDDER WEB CONTENTS.";
      return;
    }

    ExtensionTestMessageListener done_listener("TEST_PASSED", false);
    done_listener.set_failure_message("TEST_FAILED");
    if (!content::ExecuteScript(
            embedder_web_contents,
            base::StringPrintf("runTest('%s', '%s')", test_name.c_str(),
                               app_to_embed.c_str()))) {
      LOG(ERROR) << "UNABLE TO START TEST.";
      return;
    }
    ASSERT_TRUE(done_listener.WaitUntilSatisfied());
  }

  guest_view::TestGuestViewManager* test_guest_view_manager() const {
    return test_guest_view_manager_;
  }

 private:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line);
  }

  void SetUpOnMainThread() override {
    extensions::PlatformAppBrowserTest::SetUpOnMainThread();
    test_guest_view_manager_ = static_cast<guest_view::TestGuestViewManager*>(
        guest_view::GuestViewManager::CreateWithDelegate(
            browser()->profile(),
            scoped_ptr<guest_view::GuestViewManagerDelegate>(
                new extensions::ExtensionsGuestViewManagerDelegate(
                    browser()->profile()))));
  }

  TestGuestViewManagerFactory factory_;
  guest_view::TestGuestViewManager* test_guest_view_manager_;

  DISALLOW_COPY_AND_ASSIGN(AppViewTest);
};

// Tests that <appview> is able to navigate to another installed app.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewWithUndefinedDataShouldSucceed) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewWithUndefinedDataShouldSucceed",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> correctly processes parameters passed on connect.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewRefusedDataShouldFail) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewRefusedDataShouldFail",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> correctly processes parameters passed on connect.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewGoodDataShouldSucceed) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewGoodDataShouldSucceed",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> correctly handles multiple successive connects.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewMultipleConnects) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewMultipleConnects",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> does not embed self (the app which owns appview).
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewEmbedSelfShouldFail) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewEmbedSelfShouldFail",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

IN_PROC_BROWSER_TEST_F(AppViewTest, KillGuestWithInvalidInstanceID) {
  const extensions::Extension* mock_bad_app =
      LoadAndLaunchPlatformApp("app_view/bad_app", "AppViewTest.LAUNCHED");

  content::RenderProcessHost* bad_app_render_process_host =
      extensions::AppWindowRegistry::Get(browser()->profile())
          ->GetCurrentAppWindowForApp(mock_bad_app->id())
          ->web_contents()
          ->GetRenderProcessHost();

  // Monitor |mock_bad_app|'s RenderProcessHost for its exiting.
  RenderProcessHostObserverForExit exit_observer(bad_app_render_process_host);

  // Choosing a |guest_instance_id| which does not exist.
  int invalid_guest_instance_id =
      test_guest_view_manager()->GetNextInstanceID();
  // Call the desired function to verify that the |mock_bad_app| gets killed if
  // the provided |guest_instance_id| is not mapped to any "GuestView"'s.
  extensions::AppViewGuest::CompletePendingRequest(
      browser()->profile(), GURL("about:blank"), invalid_guest_instance_id,
      mock_bad_app->id(), bad_app_render_process_host);
  exit_observer.WaitUntilRenderProcessHostKilled();
}

IN_PROC_BROWSER_TEST_F(AppViewTest, KillGuestCommunicatingWithWrongAppView) {
  const extensions::Extension* host_app =
      LoadAndLaunchPlatformApp("app_view/host_app", "AppViewTest.LAUNCHED");
  const extensions::Extension* mock_guest_extension =
      InstallPlatformApp("app_view/guest_app");
  const extensions::Extension* mock_bad_app =
      LoadAndLaunchPlatformApp("app_view/bad_app", "AppViewTest.LAUNCHED");

  EXPECT_TRUE(content::ExecuteScript(
      extensions::AppWindowRegistry::Get(browser()->profile())
          ->GetCurrentAppWindowForApp(host_app->id())
          ->web_contents(),
      base::StringPrintf("onAppCommand('%s', '%s');", "EMBED",
                         mock_guest_extension->id().c_str())));
  ExtensionTestMessageListener on_embed_requested_listener(
      "AppViewTest.EmbedRequested", true);
  EXPECT_TRUE(on_embed_requested_listener.WaitUntilSatisfied());
  // Now assume the bad application is somehow sending a message to complete a
  // pending request to attach to <appview>. It should be killed.
  content::RenderProcessHost* bad_app_render_process_host =
      extensions::ProcessManager::Get(browser()->profile())
          ->GetBackgroundHostForExtension(mock_bad_app->id())
          ->render_process_host();
  RenderProcessHostObserverForExit bad_app_obs(bad_app_render_process_host);
  // Make the false request.
  int guest_instance_id =
      extensions::AppViewGuest::GetAllRegisteredInstanceIdsForTesting()[0];
  extensions::AppViewGuest::CompletePendingRequest(
      browser()->profile(), GURL("about:blank"), guest_instance_id,
      mock_bad_app->id(), bad_app_render_process_host);

  on_embed_requested_listener.Reply("continue");
  // Make sure the bad application has been terminated.
  bad_app_obs.WaitUntilRenderProcessHostKilled();
}
<commit_msg>[MemSheriff] Exclude test that fails under msan<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/strings/stringprintf.h"
#include "chrome/browser/apps/app_browsertest_util.h"
#include "components/guest_view/browser/guest_view_manager.h"
#include "components/guest_view/browser/guest_view_manager_factory.h"
#include "components/guest_view/browser/test_guest_view_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/guest_view/app_view/app_view_guest.h"
#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"

using guest_view::GuestViewManager;
using guest_view::TestGuestViewManagerFactory;

namespace {

class RenderProcessHostObserverForExit
    : public content::RenderProcessHostObserver {
 public:
  explicit RenderProcessHostObserverForExit(
      content::RenderProcessHost* observed_host)
      : render_process_host_exited_(false), observed_host_(observed_host) {
    observed_host->AddObserver(this);
  }

  void WaitUntilRenderProcessHostKilled() {
    if (render_process_host_exited_)
      return;
    message_loop_runner_ = new content::MessageLoopRunner;
    message_loop_runner_->Run();
  }

  base::TerminationStatus termination_status() const { return status_; }

 private:
  void RenderProcessExited(content::RenderProcessHost* host,
                           base::TerminationStatus status,
                           int exit_code) override {
    DCHECK(observed_host_ == host);
    render_process_host_exited_ = true;
    status_ = status;
    observed_host_->RemoveObserver(this);
    if (message_loop_runner_.get()) {
      message_loop_runner_->Quit();
    }
  }

  bool render_process_host_exited_;
  content::RenderProcessHost* observed_host_;
  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
  base::TerminationStatus status_;

  DISALLOW_COPY_AND_ASSIGN(RenderProcessHostObserverForExit);
};

}  // namespace

class AppViewTest : public extensions::PlatformAppBrowserTest {
 public:
  AppViewTest() {
    GuestViewManager::set_factory_for_testing(&factory_);
  }

  enum TestServer {
    NEEDS_TEST_SERVER,
    NO_TEST_SERVER
  };

  void TestHelper(const std::string& test_name,
                  const std::string& app_location,
                  const std::string& app_to_embed,
                  TestServer test_server) {
    // For serving guest pages.
    if (test_server == NEEDS_TEST_SERVER) {
      if (!StartEmbeddedTestServer()) {
        LOG(ERROR) << "FAILED TO START TEST SERVER.";
        return;
      }
    }

    LoadAndLaunchPlatformApp(app_location.c_str(), "Launched");

    // Flush any pending events to make sure we start with a clean slate.
    content::RunAllPendingInMessageLoop();

    content::WebContents* embedder_web_contents =
        GetFirstAppWindowWebContents();
    if (!embedder_web_contents) {
      LOG(ERROR) << "UNABLE TO FIND EMBEDDER WEB CONTENTS.";
      return;
    }

    ExtensionTestMessageListener done_listener("TEST_PASSED", false);
    done_listener.set_failure_message("TEST_FAILED");
    if (!content::ExecuteScript(
            embedder_web_contents,
            base::StringPrintf("runTest('%s', '%s')", test_name.c_str(),
                               app_to_embed.c_str()))) {
      LOG(ERROR) << "UNABLE TO START TEST.";
      return;
    }
    ASSERT_TRUE(done_listener.WaitUntilSatisfied());
  }

  guest_view::TestGuestViewManager* test_guest_view_manager() const {
    return test_guest_view_manager_;
  }

 private:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line);
  }

  void SetUpOnMainThread() override {
    extensions::PlatformAppBrowserTest::SetUpOnMainThread();
    test_guest_view_manager_ = static_cast<guest_view::TestGuestViewManager*>(
        guest_view::GuestViewManager::CreateWithDelegate(
            browser()->profile(),
            scoped_ptr<guest_view::GuestViewManagerDelegate>(
                new extensions::ExtensionsGuestViewManagerDelegate(
                    browser()->profile()))));
  }

  TestGuestViewManagerFactory factory_;
  guest_view::TestGuestViewManager* test_guest_view_manager_;

  DISALLOW_COPY_AND_ASSIGN(AppViewTest);
};

// Tests that <appview> is able to navigate to another installed app.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewWithUndefinedDataShouldSucceed) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewWithUndefinedDataShouldSucceed",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> correctly processes parameters passed on connect.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewRefusedDataShouldFail) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewRefusedDataShouldFail",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> correctly processes parameters passed on connect.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewGoodDataShouldSucceed) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewGoodDataShouldSucceed",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> correctly handles multiple successive connects.
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewMultipleConnects) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewMultipleConnects",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

// Tests that <appview> does not embed self (the app which owns appview).
IN_PROC_BROWSER_TEST_F(AppViewTest, TestAppViewEmbedSelfShouldFail) {
  const extensions::Extension* skeleton_app =
      InstallPlatformApp("app_view/shim/skeleton");
  TestHelper("testAppViewEmbedSelfShouldFail",
             "app_view/shim",
             skeleton_app->id(),
             NO_TEST_SERVER);
}

IN_PROC_BROWSER_TEST_F(AppViewTest, KillGuestWithInvalidInstanceID) {
  const extensions::Extension* mock_bad_app =
      LoadAndLaunchPlatformApp("app_view/bad_app", "AppViewTest.LAUNCHED");

  content::RenderProcessHost* bad_app_render_process_host =
      extensions::AppWindowRegistry::Get(browser()->profile())
          ->GetCurrentAppWindowForApp(mock_bad_app->id())
          ->web_contents()
          ->GetRenderProcessHost();

  // Monitor |mock_bad_app|'s RenderProcessHost for its exiting.
  RenderProcessHostObserverForExit exit_observer(bad_app_render_process_host);

  // Choosing a |guest_instance_id| which does not exist.
  int invalid_guest_instance_id =
      test_guest_view_manager()->GetNextInstanceID();
  // Call the desired function to verify that the |mock_bad_app| gets killed if
  // the provided |guest_instance_id| is not mapped to any "GuestView"'s.
  extensions::AppViewGuest::CompletePendingRequest(
      browser()->profile(), GURL("about:blank"), invalid_guest_instance_id,
      mock_bad_app->id(), bad_app_render_process_host);
  exit_observer.WaitUntilRenderProcessHostKilled();
}

// Failing on msan bot: crbug.com/507940
#if defined(MEMORY_SANITIZER)
#define MAYBE_KillGuestCommunicatingWithWrongAppViewPaste \
        DISABLED_KillGuestCommunicatingWithWrongAppViewPaste
#else
#define MAYBE_KillGuestCommunicatingWithWrongAppView \
        KillGuestCommunicatingWithWrongAppView
#endif

IN_PROC_BROWSER_TEST_F(AppViewTest,
                       MAYBE_KillGuestCommunicatingWithWrongAppView) {
  const extensions::Extension* host_app =
      LoadAndLaunchPlatformApp("app_view/host_app", "AppViewTest.LAUNCHED");
  const extensions::Extension* mock_guest_extension =
      InstallPlatformApp("app_view/guest_app");
  const extensions::Extension* mock_bad_app =
      LoadAndLaunchPlatformApp("app_view/bad_app", "AppViewTest.LAUNCHED");

  EXPECT_TRUE(content::ExecuteScript(
      extensions::AppWindowRegistry::Get(browser()->profile())
          ->GetCurrentAppWindowForApp(host_app->id())
          ->web_contents(),
      base::StringPrintf("onAppCommand('%s', '%s');", "EMBED",
                         mock_guest_extension->id().c_str())));
  ExtensionTestMessageListener on_embed_requested_listener(
      "AppViewTest.EmbedRequested", true);
  EXPECT_TRUE(on_embed_requested_listener.WaitUntilSatisfied());
  // Now assume the bad application is somehow sending a message to complete a
  // pending request to attach to <appview>. It should be killed.
  content::RenderProcessHost* bad_app_render_process_host =
      extensions::ProcessManager::Get(browser()->profile())
          ->GetBackgroundHostForExtension(mock_bad_app->id())
          ->render_process_host();
  RenderProcessHostObserverForExit bad_app_obs(bad_app_render_process_host);
  // Make the false request.
  int guest_instance_id =
      extensions::AppViewGuest::GetAllRegisteredInstanceIdsForTesting()[0];
  extensions::AppViewGuest::CompletePendingRequest(
      browser()->profile(), GURL("about:blank"), guest_instance_id,
      mock_bad_app->id(), bad_app_render_process_host);

  on_embed_requested_listener.Reply("continue");
  // Make sure the bad application has been terminated.
  bad_app_obs.WaitUntilRenderProcessHostKilled();
}
<|endoftext|>