<commit_before>#include "oddlib/compressiontype3ae.hpp"
#include "oddlib/stream.hpp"
#include "logger.hpp"
#include <vector>
#include <cassert>

static Uint16 ReadUint16(Oddlib::IStream& stream)
{
    Uint16 ret = 0;
    stream.ReadUInt16(ret);
    return ret;
}

static Uint32 ReadUint32(Oddlib::IStream& stream)
{
    Uint32 ret = 0;
    stream.ReadUInt32(ret);
    return ret;
}

template<typename T>
static void ReadNextSource(Oddlib::IStream& stream, int& control_byte, T& dstIndex)
{
    if (control_byte)
    {
        if (control_byte == 0xE)
        {
            control_byte = 0x1Eu;
            dstIndex |= ReadUint16(stream) << 14;
        }
    }
    else
    {
        dstIndex = ReadUint32(stream);
        control_byte = 0x20u;
    }
    control_byte -= 6;
}

namespace Oddlib
{
    std::vector<Uint8> CompressionType3Ae::Decompress(IStream& stream, Uint32 size, Uint32 w, Uint32 h)
    {
        LOG_INFO("Data size is " << size);

        // TODO: Shouldn't need to be * 4
        std::vector< unsigned char > buffer(w*h * 4);

        int dstPos = 0;
        int control_byte = 0;

        int width = ReadUint16(stream);
        int height = ReadUint16(stream);
        if (height > 0)
        {
            int dstIndex = 0;
            do
            {
                int columnNumber = 0;
                while (columnNumber < width)
                {
                    ReadNextSource(stream, control_byte, dstIndex);

                    const unsigned char blackBytes = dstIndex & 0x3F;

                     unsigned int srcByte = (unsigned int)dstIndex >> 6;

                    const int bytesToWrite = blackBytes + columnNumber;
                    if (blackBytes > 0)
                    {
                        const unsigned int doubleBBytes = (unsigned int)blackBytes >> 2;
                        for (auto i = 0u; i < 4 * doubleBBytes; i++)
                        {
                            buffer[dstPos + i] = 0;
                        }

                        for (int i = blackBytes & 3; i; --i)
                        {
                            buffer[(dstPos + 4 * doubleBBytes) + i] = 0;
                        }
                        dstPos += blackBytes;
                    }

                    ReadNextSource(stream, control_byte, srcByte);

                    const unsigned char bytes = srcByte & 0x3F;
                    dstIndex = srcByte >> 6;

                    columnNumber = bytes + bytesToWrite;
                    if (bytes > 0)
                    {
                        int byteCount = bytes;
                        do
                        {
                            ReadNextSource(stream, control_byte, dstIndex);

                            const char dstByte = dstIndex & 0x3F;
                            dstIndex = (unsigned int)dstIndex >> 6;

                            buffer[dstPos] = dstByte;
                            dstPos++;
                            --byteCount;
                        } while (byteCount);
                    }
                }
                if (columnNumber & 3)
                {
                    do
                    {
                        ++dstPos;
                        ++columnNumber;
                    } while (columnNumber & 3);
                }
            } while (height-- != 1);
        }

        return buffer;
    }
}
<commit_msg>Remove the "blacking out" part the of decompression algorithm since our buffers are init'ed to 0's. Its easier to do this then check the "blacking out" part of the algorithm is 100% correct<commit_after>#include "oddlib/compressiontype3ae.hpp"
#include "oddlib/stream.hpp"
#include "logger.hpp"
#include <vector>
#include <cassert>

static Uint16 ReadUint16(Oddlib::IStream& stream)
{
    Uint16 ret = 0;
    stream.ReadUInt16(ret);
    return ret;
}

static Uint32 ReadUint32(Oddlib::IStream& stream)
{
    Uint32 ret = 0;
    stream.ReadUInt32(ret);
    return ret;
}

template<typename T>
static void ReadNextSource(Oddlib::IStream& stream, int& control_byte, T& dstIndex)
{
    if (control_byte)
    {
        if (control_byte == 0xE)
        {
            control_byte = 0x1Eu;
            dstIndex |= ReadUint16(stream) << 14;
        }
    }
    else
    {
        dstIndex = ReadUint32(stream);
        control_byte = 0x20u;
    }
    control_byte -= 6;
}

namespace Oddlib
{
    std::vector<Uint8> CompressionType3Ae::Decompress(IStream& stream, Uint32 size, Uint32 w, Uint32 h)
    {
        LOG_INFO("Data size is " << size);

        // TODO: Shouldn't need to be * 4
        std::vector< unsigned char > buffer(w*h * 4);

        int dstPos = 0;
        int control_byte = 0;

        int width = ReadUint16(stream);
        int height = ReadUint16(stream);
        if (height > 0)
        {
            unsigned int dstIndex = 0;
            do
            {
                int columnNumber = 0;
                while (columnNumber < width)
                {
                    ReadNextSource(stream, control_byte, dstIndex);

                    const unsigned char blackBytes = dstIndex & 0x3F;
                    unsigned int srcByte = dstIndex >> 6;

                    // Here the "black" bytes would be written, since our buffers are inited to zeros we
                    // don't have to worry about getting this bit correct
                    const int bytesToWrite = blackBytes + columnNumber;

                    // Pretend we just blacked out an area
                    dstPos += blackBytes;
                    ReadNextSource(stream, control_byte, srcByte);

                    const unsigned char bytes = srcByte & 0x3F;
                    dstIndex = srcByte >> 6;

                    columnNumber = bytes + bytesToWrite;
                    if (bytes > 0)
                    {
                        int byteCount = bytes;
                        do
                        {
                            ReadNextSource(stream, control_byte, dstIndex);

                            const char dstByte = dstIndex & 0x3F;
                            dstIndex = dstIndex >> 6;

                            buffer[dstPos] = dstByte;
                            dstPos++;
                            --byteCount;
                        } while (byteCount);
                    }
                }
                if (columnNumber & 3)
                {
                    do
                    {
                        ++dstPos;
                        ++columnNumber;
                    } while (columnNumber & 3);
                }
            } while (height-- != 1);
        }

        return buffer;
    }
}
<|endoftext|>


<commit_before>/*
  Copyright (C) 2008-2016 The Communi Project

  You may use this file under the terms of BSD license as follows:

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the copyright holder nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "gnomeplugin.h"
#include "gnomemenu.h"
#include "x11helper.h"
#include "themeinfo.h"
#include <QSystemTrayIcon>
#include <QMainWindow>
#include <QAction>

GnomePlugin::GnomePlugin(QObject* parent) : QObject(parent)
{
    d.mute = 0;
    d.window = 0;
}

void GnomePlugin::windowCreated(QMainWindow* window)
{
    d.window = window;

#ifdef COMMUNI_HAVE_GIO
    GnomeMenu *section1 = new GnomeMenu(window);
    section1->addSimpleItem("showConnect", "Connect...", window, "doConnect");
    section1->addSimpleItem("showSettings", "Settings", window, "showSettings");
    section1->addSimpleItem("showHelp", "Help", window, "showHelp");

    GnomeMenu *section2 = new GnomeMenu(window);
    section2->addToggleItem("toggleMute", "Mute", d.mute->isChecked(), d.mute, "toggle");

    GnomeMenu *section3 = new GnomeMenu(window);
    section3->addSimpleItem("quit", "Quit", window, "close");

    GnomeMenu *builder = new GnomeMenu(window);
    builder->addSection(section1);
    builder->addSection(section2);
    builder->addSection(section3);
    builder->setMenuToWindow(window->winId(), "/org/communi/gnomeintegration");
#endif // COMMUNI_HAVE_GIO
}

void GnomePlugin::themeChanged(const ThemeInfo& theme)
{
    QByteArray gtkTheme = theme.gtkTheme().toUtf8();
    X11Helper::setWindowProperty(d.window->winId(), "_GTK_THEME_VARIANT", gtkTheme);
}

void GnomePlugin::setupTrayIcon(QSystemTrayIcon* tray)
{
    tray->setVisible(false);
}

void GnomePlugin::setupMuteAction(QAction* action)
{
    d.mute = action;
}
<commit_msg>KDE: keep tray icon visible<commit_after>/*
  Copyright (C) 2008-2016 The Communi Project

  You may use this file under the terms of BSD license as follows:

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the copyright holder nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "gnomeplugin.h"
#include "gnomemenu.h"
#include "x11helper.h"
#include "themeinfo.h"
#include <QSystemTrayIcon>
#include <QMainWindow>
#include <QAction>

GnomePlugin::GnomePlugin(QObject* parent) : QObject(parent)
{
    d.mute = 0;
    d.window = 0;
}

void GnomePlugin::windowCreated(QMainWindow* window)
{
    d.window = window;

#ifdef COMMUNI_HAVE_GIO
    GnomeMenu *section1 = new GnomeMenu(window);
    section1->addSimpleItem("showConnect", "Connect...", window, "doConnect");
    section1->addSimpleItem("showSettings", "Settings", window, "showSettings");
    section1->addSimpleItem("showHelp", "Help", window, "showHelp");

    GnomeMenu *section2 = new GnomeMenu(window);
    section2->addToggleItem("toggleMute", "Mute", d.mute->isChecked(), d.mute, "toggle");

    GnomeMenu *section3 = new GnomeMenu(window);
    section3->addSimpleItem("quit", "Quit", window, "close");

    GnomeMenu *builder = new GnomeMenu(window);
    builder->addSection(section1);
    builder->addSection(section2);
    builder->addSection(section3);
    builder->setMenuToWindow(window->winId(), "/org/communi/gnomeintegration");
#endif // COMMUNI_HAVE_GIO
}

void GnomePlugin::themeChanged(const ThemeInfo& theme)
{
    QByteArray gtkTheme = theme.gtkTheme().toUtf8();
    X11Helper::setWindowProperty(d.window->winId(), "_GTK_THEME_VARIANT", gtkTheme);
}

void GnomePlugin::setupTrayIcon(QSystemTrayIcon* tray)
{
    if (qgetenv("XDG_CURRENT_DESKTOP") != "KDE" && qgetenv("KDE_FULL_SESSION").isEmpty())
        tray->setVisible(false);
}

void GnomePlugin::setupMuteAction(QAction* action)
{
    d.mute = action;
}
<|endoftext|>


<commit_before>/************************************************************************************
 * Copyright (C) 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>                *
 *                                                                                *
 * This program is free software; you can redistribute it and/or                    *
 * modify it under the terms of the GNU General Public License                      *
 * as published by the Free Software Foundation; either version 2                   *
 * of the License, or (at your option) any later version.                           *
 *                                                                                *
 * This program is distributed in the hope that it will be useful,                  *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
 * GNU General Public License for more details.                                     *
 *                                                                                *
 * You should have received a copy of the GNU General Public License                *
 * along with this program; if not, write to the Free Software                      *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 ************************************************************************************/

#include <purpose/pluginbase.h>
#include "mpform.h"
#include <QDebug>
#include <QTimer>
#include <QStandardPaths>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <KLocalizedString>
#include <KPluginFactory>
#include <KJob>
#include <KIO/TransferJob>
#include <KIO/StoredTransferJob>

EXPORT_SHARE_VERSION

// Taken from "share" Data Engine
// key associated with plasma-devel@kde.org
// thanks to Alan Schaaf of Imgur (alan@imgur.com)
static const QString apiKey = QStringLiteral("d0757bc2e94a0d4652f28079a0be9379");
static const QUrl imgurUrl(QStringLiteral("https://api.imgur.com/2/upload.json?key=")+apiKey);

class ImgurShareJob : public Purpose::Job
{
    Q_OBJECT
    public:
        ImgurShareJob(QObject* parent)
            : Purpose::Job(parent)
            , m_pendingJobs(0)
        {}

        virtual void start() override
        {
            QJsonArray urls = data().value(QStringLiteral("urls")).toArray();
            qDebug() << "starting..." << data().toVariantMap();
            if (urls.isEmpty()) {
                qWarning() << "no urls to share" << urls << data();
                emitResult();
                return;
            }

            foreach(const QJsonValue &val, urls) {
                QString u = val.toString();
                if (u.startsWith(QLatin1String("data:"))) {
                    QByteArray data = QByteArray::fromBase64(u.mid(4).toLatin1());
                    QFile f(QStringLiteral("/tmp/puta.png"));
                    Q_ASSERT(f.open(QFile::WriteOnly));
                    f.write(data);
                    m_form.addFile(QStringLiteral("image"), QUrl(QStringLiteral("file:///not-in-the-file-system")), data);
                } else {
                    KIO::StoredTransferJob* job = KIO::storedGet(QUrl(u));
                    connect(job, &KJob::finished, this, &ImgurShareJob::fileFetched);
                    m_pendingJobs++;
                }
            }
            if (m_pendingJobs == 0) {
                performUpload();
            }
        }

        void fileFetched(KJob* j)
        {
            KIO::StoredTransferJob* job = qobject_cast<KIO::StoredTransferJob*>(j);
            m_form.addFile(QStringLiteral("image"), job->url(), job->data());
            --m_pendingJobs;
            if (m_pendingJobs == 0)
                performUpload();
        }

        void performUpload()
        {
            m_form.finish();

            KIO::TransferJob *tJob = KIO::http_post(imgurUrl, m_form.formData(), KIO::HideProgressInfo);
            tJob->setMetaData(QMap<QString,QString>{{ QStringLiteral("content-type"), QString::fromLocal8Bit(m_form.contentType()) }});
            connect(tJob, &KIO::TransferJob::data, this, [this](KIO::Job*, const QByteArray& data) { m_resultData += data; });
            connect(tJob, &KJob::result, this, &ImgurShareJob::imagesUploaded);

            m_form.reset(); //we can free some resources already
        }

        void imagesUploaded(KJob* job) {
            QJsonParseError error;
            QJsonObject resultMap = QJsonDocument::fromJson(m_resultData, &error).object();
            if (static_cast<KIO::TransferJob *>(job)->isErrorPage()) {
                setError(3);
                setErrorText(i18n("Error page returned"));
                qDebug() << "Error page :(";
            } else if (job->error()) {
                setError(job->error());
                setErrorText(job->errorText());
            } else if (error.error) {
                setError(1);
                setErrorText(error.errorString());
            } else if ( resultMap.contains(QLatin1String("error")) ) {
                setError(2);
                QJsonObject errorMap = resultMap[QStringLiteral("error")].toObject();
                setErrorText(errorMap[QStringLiteral("message")].toString());
            } else {
                QJsonObject uploadMap = resultMap[QStringLiteral("upload")].toObject();
                QJsonObject linksMap = uploadMap[QStringLiteral("links")].toObject();
                QString url = linksMap[QStringLiteral("original")].toString();
                Q_EMIT infoMessage(this, url, QStringLiteral("%1").arg(url));
            }
            emitResult();
        }

        virtual QUrl configSourceCode() const override
        {
            return QUrl();
        }

    private:
        int m_pendingJobs;
        MPForm m_form;
        QByteArray m_resultData;
};

class Q_DECL_EXPORT ImgurPlugin : public Purpose::PluginBase
{
    Q_OBJECT
    public:
        ImgurPlugin(QObject* p, const QVariantList& ) : Purpose::PluginBase(p) {}

        virtual Purpose::Job* share() const override
        {
            return new ImgurShareJob(nullptr);
        }
};

K_PLUGIN_FACTORY_WITH_JSON(ImgurShare, "imgurplugin.json", registerPlugin<ImgurPlugin>();)

#include "imgurplugin.moc"
<commit_msg>Revert the data: protocol support<commit_after>/************************************************************************************
 * Copyright (C) 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>                *
 *                                                                                *
 * This program is free software; you can redistribute it and/or                    *
 * modify it under the terms of the GNU General Public License                      *
 * as published by the Free Software Foundation; either version 2                   *
 * of the License, or (at your option) any later version.                           *
 *                                                                                *
 * This program is distributed in the hope that it will be useful,                  *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
 * GNU General Public License for more details.                                     *
 *                                                                                *
 * You should have received a copy of the GNU General Public License                *
 * along with this program; if not, write to the Free Software                      *
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 ************************************************************************************/

#include <purpose/pluginbase.h>
#include "mpform.h"
#include <QDebug>
#include <QTimer>
#include <QStandardPaths>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <KLocalizedString>
#include <KPluginFactory>
#include <KJob>
#include <KIO/TransferJob>
#include <KIO/StoredTransferJob>

EXPORT_SHARE_VERSION

// Taken from "share" Data Engine
// key associated with plasma-devel@kde.org
// thanks to Alan Schaaf of Imgur (alan@imgur.com)
static const QString apiKey = QStringLiteral("d0757bc2e94a0d4652f28079a0be9379");
static const QUrl imgurUrl(QStringLiteral("https://api.imgur.com/2/upload.json?key=")+apiKey);

class ImgurShareJob : public Purpose::Job
{
    Q_OBJECT
    public:
        ImgurShareJob(QObject* parent)
            : Purpose::Job(parent)
            , m_pendingJobs(0)
        {}

        virtual void start() override
        {
            QJsonArray urls = data().value(QStringLiteral("urls")).toArray();
            qDebug() << "starting..." << data().toVariantMap();
            if (urls.isEmpty()) {
                qWarning() << "no urls to share" << urls << data();
                emitResult();
                return;
            }

            foreach(const QJsonValue &val, urls) {
                QString u = val.toString();
                KIO::StoredTransferJob* job = KIO::storedGet(QUrl(u));
                connect(job, &KJob::finished, this, &ImgurShareJob::fileFetched);
                m_pendingJobs++;
            }
            Q_ASSERT(m_pendingJobs>0);
        }

        void fileFetched(KJob* j)
        {
            KIO::StoredTransferJob* job = qobject_cast<KIO::StoredTransferJob*>(j);
            m_form.addFile(QStringLiteral("image"), job->url(), job->data());
            --m_pendingJobs;
            if (m_pendingJobs == 0)
                performUpload();
        }

        void performUpload()
        {
            m_form.finish();

            KIO::TransferJob *tJob = KIO::http_post(imgurUrl, m_form.formData(), KIO::HideProgressInfo);
            tJob->setMetaData(QMap<QString,QString>{{ QStringLiteral("content-type"), QString::fromLocal8Bit(m_form.contentType()) }});
            connect(tJob, &KIO::TransferJob::data, this, [this](KIO::Job*, const QByteArray& data) { m_resultData += data; });
            connect(tJob, &KJob::result, this, &ImgurShareJob::imagesUploaded);

            m_form.reset(); //we can free some resources already
        }

        void imagesUploaded(KJob* job) {
            QJsonParseError error;
            QJsonObject resultMap = QJsonDocument::fromJson(m_resultData, &error).object();
            if (static_cast<KIO::TransferJob *>(job)->isErrorPage()) {
                setError(3);
                setErrorText(i18n("Error page returned"));
                qDebug() << "Error page :(";
            } else if (job->error()) {
                setError(job->error());
                setErrorText(job->errorText());
            } else if (error.error) {
                setError(1);
                setErrorText(error.errorString());
            } else if ( resultMap.contains(QLatin1String("error")) ) {
                setError(2);
                QJsonObject errorMap = resultMap[QStringLiteral("error")].toObject();
                setErrorText(errorMap[QStringLiteral("message")].toString());
            } else {
                QJsonObject uploadMap = resultMap[QStringLiteral("upload")].toObject();
                QJsonObject linksMap = uploadMap[QStringLiteral("links")].toObject();
                QString url = linksMap[QStringLiteral("original")].toString();
                Q_EMIT infoMessage(this, url, QStringLiteral("%1").arg(url));
            }
            emitResult();
        }

        virtual QUrl configSourceCode() const override
        {
            return QUrl();
        }

    private:
        int m_pendingJobs;
        MPForm m_form;
        QByteArray m_resultData;
};

class Q_DECL_EXPORT ImgurPlugin : public Purpose::PluginBase
{
    Q_OBJECT
    public:
        ImgurPlugin(QObject* p, const QVariantList& ) : Purpose::PluginBase(p) {}

        virtual Purpose::Job* share() const override
        {
            return new ImgurShareJob(nullptr);
        }
};

K_PLUGIN_FACTORY_WITH_JSON(ImgurShare, "imgurplugin.json", registerPlugin<ImgurPlugin>();)

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


<commit_before><commit_msg>INTEGRATION: CWS changefileheader (1.8.18); FILE MERGED 2008/04/01 16:09:54 thb 1.8.18.3: #i85898# Stripping all external header guards 2008/04/01 13:05:01 thb 1.8.18.2: #i85898# Stripping all external header guards 2008/03/31 16:28:21 rt 1.8.18.1: #i87441# Change license header to LPGL v3.<commit_after><|endoftext|>


<commit_before><commit_msg>Basic archetype<commit_after><|endoftext|>


<commit_before><commit_msg>Marks session as connected upon StartSession success<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Rhys Ulerich
 *
 * 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/.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <iterator>

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include <descendu/map.hpp>

using namespace descendu;

TEST_CASE( "map" ) {

    map m;

    SECTION( "populate" ) {
        // Empty on construction
        REQUIRE( m.cbegin() == m.cend() );

        // Insertion with explicit type
        m.populate(map::key_type(0, 0));
        auto a = m.cbegin();
        std::advance(a, 1);
        REQUIRE( a == m.cend() );

        // Idempotent re-insertion
        m.populate(map::key_type(0, 0));
        auto b = m.cbegin();
        std::advance(b, 1);
        REQUIRE( b == m.cend() );

        // Insertion with nicety provided by hex
        m.populate(map::key_type(1, 0));
        auto c = m.cbegin();
        std::advance(c, 2);
        REQUIRE( c == m.cend() );
    }

    SECTION( "mutable" ) {
        auto& a = m.populate({0, 0});
        a.cannon.increase(1);
        REQUIRE( a.cannon.total() == 1 );

        auto& b = m.lookup({0, 0}).value();
        REQUIRE( b.cannon.total() == 1 );
    }

    SECTION( "not_found" ) {
        REQUIRE( !m.lookup({0, 0}).has_value() );
        REQUIRE( !m.lookup({0, 0}) );
    }

}
<commit_msg>Enforce no clobber of existing<commit_after>/*
 * Copyright (C) 2016 Rhys Ulerich
 *
 * 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/.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <iterator>

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include <descendu/map.hpp>

using namespace descendu;

TEST_CASE( "map" ) {

    map m;

    SECTION( "populate" ) {
        // Empty on construction
        REQUIRE( m.cbegin() == m.cend() );

        // Insertion with explicit type
        m.populate(map::key_type(0, 0));
        auto a = m.cbegin();
        std::advance(a, 1);
        REQUIRE( a == m.cend() );

        // Idempotent re-insertion
        m.populate(map::key_type(0, 0));
        auto b = m.cbegin();
        std::advance(b, 1);
        REQUIRE( b == m.cend() );

        // Insertion with nicety provided by hex
        m.populate(map::key_type(1, 0));
        auto c = m.cbegin();
        std::advance(c, 2);
        REQUIRE( c == m.cend() );
    }

    SECTION( "mutable" ) {
        auto& a = m.populate({0, 0});
        a.cannon.increase(1);
        REQUIRE( a.cannon.total() == 1 );

        auto& b = m.lookup({0, 0}).value();
        REQUIRE( b.cannon.total() == 1 );

        // No clobber of existing entry
        auto& c = m.populate({0, 0});
        REQUIRE( c.cannon.total() == 1 );
    }

    SECTION( "not_found" ) {
        REQUIRE( !m.lookup({0, 0}).has_value() );
        REQUIRE( !m.lookup({0, 0}) );
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "chrome/browser/sync/sync_setup_flow.h"

#include "app/gfx/font.h"
#include "app/gfx/font_util.h"
#include "base/histogram.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/google_service_auth_error.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/pref_names.h"
#include "grit/locale_settings.h"

// XPath expression for finding specific iframes.
static const wchar_t* kLoginIFrameXPath = L"//iframe[@id='login']";
static const wchar_t* kMergeIFrameXPath = L"//iframe[@id='merge']";
static const wchar_t* kDoneIframeXPath = L"//iframe[@id='done']";

// Helper function to read the JSON string from the Value parameter.
static std::string GetJsonResponse(const Value* content) {
  if (!content || !content->IsType(Value::TYPE_LIST)) {
    NOTREACHED();
    return std::string();
  }
  const ListValue* args = static_cast<const ListValue*>(content);
  if (args->GetSize() != 1) {
    NOTREACHED();
    return std::string();
  }

  std::string result;
  Value* value = NULL;
  if (!args->Get(0, &value) || !value->GetAsString(&result)) {
    NOTREACHED();
    return std::string();
  }

  return result;
}

void FlowHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback("SubmitAuth",
      NewCallback(this, &FlowHandler::HandleSubmitAuth));
  dom_ui_->RegisterMessageCallback("SubmitMergeAndSync",
      NewCallback(this, &FlowHandler::HandleSubmitMergeAndSync));
}

static bool GetAuthData(const std::string& json,
    std::string* username, std::string* password, std::string* captcha) {
  scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
  if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
    return false;

  DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
  if (!result->GetString(L"user", username) ||
      !result->GetString(L"pass", password) ||
      !result->GetString(L"captcha", captcha)) {
      return false;
  }
  return true;
}

void FlowHandler::HandleSubmitAuth(const Value* value) {
  std::string json(GetJsonResponse(value));
  std::string username, password, captcha;
  if (json.empty())
    return;

  if (!GetAuthData(json, &username, &password, &captcha)) {
    // The page sent us something that we didn't understand.
    // This probably indicates a programming error.
    NOTREACHED();
    return;
  }

  if (flow_)
    flow_->OnUserSubmittedAuth(username, password, captcha);
}

void FlowHandler::HandleSubmitMergeAndSync(const Value* value) {
  if (flow_)
    flow_->OnUserAcceptedMergeAndSync();
}

// Called by SyncSetupFlow::Advance.
void FlowHandler::ShowGaiaLogin(const DictionaryValue& args) {
  std::string json;
  base::JSONWriter::Write(&args, false, &json);
  std::wstring javascript = std::wstring(L"showGaiaLogin") +
      L"(" + UTF8ToWide(json) + L");";
  ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
}

void FlowHandler::ShowGaiaSuccessAndClose() {
  ExecuteJavascriptInIFrame(kLoginIFrameXPath, L"showGaiaSuccessAndClose();");
}

void FlowHandler::ShowGaiaSuccessAndSettingUp() {
  ExecuteJavascriptInIFrame(kLoginIFrameXPath,
                            L"showGaiaSuccessAndSettingUp();");
}

void FlowHandler::ShowMergeAndSync() {
  if (dom_ui_)  // NULL during testing.
    dom_ui_->CallJavascriptFunction(L"showMergeAndSync");
}

void FlowHandler::ShowSetupDone(const std::wstring& user) {
  StringValue synced_to_string(WideToUTF8(l10n_util::GetStringF(
      IDS_SYNC_NTP_SYNCED_TO, user)));
  std::string json;
  base::JSONWriter::Write(&synced_to_string, false, &json);
  std::wstring javascript = std::wstring(L"setSyncedToUser") +
      L"(" + UTF8ToWide(json) + L");";
  ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);

  if (dom_ui_)
    dom_ui_->CallJavascriptFunction(L"showSetupDone", synced_to_string);
}

void FlowHandler::ShowFirstTimeDone(const std::wstring& user) {
  ExecuteJavascriptInIFrame(kDoneIframeXPath,
                            L"setShowFirstTimeSetupSummary();");
  ShowSetupDone(user);
}

void FlowHandler::ShowMergeAndSyncError() {
  ExecuteJavascriptInIFrame(kMergeIFrameXPath, L"showMergeAndSyncError();");
}

void FlowHandler::ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath,
                                            const std::wstring& js) {
  if (dom_ui_) {
    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
    rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
  }
}

SyncSetupFlow::~SyncSetupFlow() {
  flow_handler_->set_flow(NULL);
}

void SyncSetupFlow::GetDialogSize(gfx::Size* size) const {
  PrefService* prefs = service_->profile()->GetPrefs();
  gfx::Font approximate_web_font = gfx::Font::CreateFont(
      prefs->GetString(prefs::kWebKitSansSerifFontFamily),
      prefs->GetInteger(prefs::kWebKitDefaultFontSize));

  *size = gfx::GetLocalizedContentsSizeForFont(
      IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
      IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
      approximate_web_font);

#if !defined(OS_WIN)
  // NOTE(akalin): This is a hack to work around a problem with font height on
  // windows.  Basically font metrics are incorrectly returned in logical units
  // instead of pixels on Windows.  Logical units are very commonly 96 DPI
  // so our localized char/line counts are too small by a factor of 96/72.
  // So we compensate for this on non-windows platform.
  //
  // TODO(akalin): Remove this hack once we fix the windows font problem (or at
  // least work around it in some other place).
  float scale_hack = 96.f/72.f;
  size->set_width(size->width() * scale_hack);
  size->set_height(size->height() * scale_hack);
#endif
}

// A callback to notify the delegate that the dialog closed.
void SyncSetupFlow::OnDialogClosed(const std::string& json_retval) {
  DCHECK(json_retval.empty());
  container_->set_flow(NULL);  // Sever ties from the wizard.
  if (current_state_ == SyncSetupWizard::DONE ||
      current_state_ == SyncSetupWizard::DONE_FIRST_TIME) {
    service_->SetSyncSetupCompleted();
  }

  // Record the state at which the user cancelled the signon dialog.
  switch (current_state_) {
    case SyncSetupWizard::GAIA_LOGIN:
      ProfileSyncService::SyncEvent(
          ProfileSyncService::CANCEL_FROM_SIGNON_WITHOUT_AUTH);
      break;
    case SyncSetupWizard::GAIA_SUCCESS:
      ProfileSyncService::SyncEvent(
          ProfileSyncService::CANCEL_DURING_SIGNON);
      break;
    case SyncSetupWizard::MERGE_AND_SYNC:
      ProfileSyncService::SyncEvent(
          ProfileSyncService::CANCEL_DURING_SIGNON_AFTER_MERGE);
      break;
    case SyncSetupWizard::DONE_FIRST_TIME:
    case SyncSetupWizard::DONE:
      UMA_HISTOGRAM_MEDIUM_TIMES("Sync.UserPerceivedAuthorizationTime",
                                 base::TimeTicks::Now() - login_start_time_);
      break;
    default:
      break;
  }

  service_->OnUserCancelledDialog();
  delete this;
}

// static
void SyncSetupFlow::GetArgsForGaiaLogin(const ProfileSyncService* service,
                                        DictionaryValue* args) {
  const GoogleServiceAuthError& error = service->GetAuthError();
  if (!service->last_attempted_user_email().empty()) {
    args->SetString(L"user", service->last_attempted_user_email());
    args->SetInteger(L"error", error.state());
  } else {
    std::wstring user(UTF16ToWide(service->GetAuthenticatedUsername()));
    args->SetString(L"user", user);
    args->SetInteger(L"error", user.empty() ? 0 : error.state());
  }

  args->SetString(L"captchaUrl", error.captcha().image_url.spec());
}

void SyncSetupFlow::GetDOMMessageHandlers(
    std::vector<DOMMessageHandler*>* handlers) const {
  handlers->push_back(flow_handler_);
}

bool SyncSetupFlow::ShouldAdvance(SyncSetupWizard::State state) {
  switch (state) {
    case SyncSetupWizard::GAIA_LOGIN:
      return current_state_ == SyncSetupWizard::GAIA_LOGIN;
    case SyncSetupWizard::GAIA_SUCCESS:
      return current_state_ == SyncSetupWizard::GAIA_LOGIN;
    case SyncSetupWizard::MERGE_AND_SYNC:
      return current_state_ == SyncSetupWizard::GAIA_SUCCESS;
    case SyncSetupWizard::FATAL_ERROR:
      return true;  // You can always hit the panic button.
    case SyncSetupWizard::DONE_FIRST_TIME:
    case SyncSetupWizard::DONE:
      return current_state_ == SyncSetupWizard::MERGE_AND_SYNC ||
             current_state_ == SyncSetupWizard::GAIA_SUCCESS;
    default:
      NOTREACHED() << "Unhandled State: " << state;
      return false;
  }
}

void SyncSetupFlow::Advance(SyncSetupWizard::State advance_state) {
  if (!ShouldAdvance(advance_state))
    return;
  switch (advance_state) {
    case SyncSetupWizard::GAIA_LOGIN: {
      DictionaryValue args;
      SyncSetupFlow::GetArgsForGaiaLogin(service_, &args);
      flow_handler_->ShowGaiaLogin(args);
      break;
    }
    case SyncSetupWizard::GAIA_SUCCESS:
      if (end_state_ == SyncSetupWizard::GAIA_SUCCESS)
        flow_handler_->ShowGaiaSuccessAndClose();
      else
        flow_handler_->ShowGaiaSuccessAndSettingUp();
      break;
    case SyncSetupWizard::MERGE_AND_SYNC:
      flow_handler_->ShowMergeAndSync();
      break;
    case SyncSetupWizard::FATAL_ERROR:
      if (current_state_ == SyncSetupWizard::MERGE_AND_SYNC)
        flow_handler_->ShowMergeAndSyncError();
      break;
    case SyncSetupWizard::DONE_FIRST_TIME:
      flow_handler_->ShowFirstTimeDone(
          UTF16ToWide(service_->GetAuthenticatedUsername()));
      break;
    case SyncSetupWizard::DONE:
      flow_handler_->ShowSetupDone(
          UTF16ToWide(service_->GetAuthenticatedUsername()));
      break;
    default:
      NOTREACHED() << "Invalid advance state: " << advance_state;
  }
  current_state_ = advance_state;
}

// static
SyncSetupFlow* SyncSetupFlow::Run(ProfileSyncService* service,
                                  SyncSetupFlowContainer* container,
                                  SyncSetupWizard::State start,
                                  SyncSetupWizard::State end) {
  DictionaryValue args;
  if (start == SyncSetupWizard::GAIA_LOGIN)
    SyncSetupFlow::GetArgsForGaiaLogin(service, &args);
  std::string json_args;
  base::JSONWriter::Write(&args, false, &json_args);

  Browser* b = BrowserList::GetLastActive();
  if (!b)
    return NULL;

  FlowHandler* handler = new FlowHandler();
  SyncSetupFlow* flow = new SyncSetupFlow(start, end, json_args,
      container, handler, service);
  handler->set_flow(flow);
  b->BrowserShowHtmlDialog(flow, NULL);
  return flow;
}
<commit_msg>Change the layout have in sync_setup_flow.cc to only be active on MacOS.<commit_after>// Copyright (c) 2009 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 "chrome/browser/sync/sync_setup_flow.h"

#include "app/gfx/font.h"
#include "app/gfx/font_util.h"
#include "base/histogram.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/google_service_auth_error.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/pref_names.h"
#include "grit/locale_settings.h"

// XPath expression for finding specific iframes.
static const wchar_t* kLoginIFrameXPath = L"//iframe[@id='login']";
static const wchar_t* kMergeIFrameXPath = L"//iframe[@id='merge']";
static const wchar_t* kDoneIframeXPath = L"//iframe[@id='done']";

// Helper function to read the JSON string from the Value parameter.
static std::string GetJsonResponse(const Value* content) {
  if (!content || !content->IsType(Value::TYPE_LIST)) {
    NOTREACHED();
    return std::string();
  }
  const ListValue* args = static_cast<const ListValue*>(content);
  if (args->GetSize() != 1) {
    NOTREACHED();
    return std::string();
  }

  std::string result;
  Value* value = NULL;
  if (!args->Get(0, &value) || !value->GetAsString(&result)) {
    NOTREACHED();
    return std::string();
  }

  return result;
}

void FlowHandler::RegisterMessages() {
  dom_ui_->RegisterMessageCallback("SubmitAuth",
      NewCallback(this, &FlowHandler::HandleSubmitAuth));
  dom_ui_->RegisterMessageCallback("SubmitMergeAndSync",
      NewCallback(this, &FlowHandler::HandleSubmitMergeAndSync));
}

static bool GetAuthData(const std::string& json,
    std::string* username, std::string* password, std::string* captcha) {
  scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
  if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
    return false;

  DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
  if (!result->GetString(L"user", username) ||
      !result->GetString(L"pass", password) ||
      !result->GetString(L"captcha", captcha)) {
      return false;
  }
  return true;
}

void FlowHandler::HandleSubmitAuth(const Value* value) {
  std::string json(GetJsonResponse(value));
  std::string username, password, captcha;
  if (json.empty())
    return;

  if (!GetAuthData(json, &username, &password, &captcha)) {
    // The page sent us something that we didn't understand.
    // This probably indicates a programming error.
    NOTREACHED();
    return;
  }

  if (flow_)
    flow_->OnUserSubmittedAuth(username, password, captcha);
}

void FlowHandler::HandleSubmitMergeAndSync(const Value* value) {
  if (flow_)
    flow_->OnUserAcceptedMergeAndSync();
}

// Called by SyncSetupFlow::Advance.
void FlowHandler::ShowGaiaLogin(const DictionaryValue& args) {
  std::string json;
  base::JSONWriter::Write(&args, false, &json);
  std::wstring javascript = std::wstring(L"showGaiaLogin") +
      L"(" + UTF8ToWide(json) + L");";
  ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
}

void FlowHandler::ShowGaiaSuccessAndClose() {
  ExecuteJavascriptInIFrame(kLoginIFrameXPath, L"showGaiaSuccessAndClose();");
}

void FlowHandler::ShowGaiaSuccessAndSettingUp() {
  ExecuteJavascriptInIFrame(kLoginIFrameXPath,
                            L"showGaiaSuccessAndSettingUp();");
}

void FlowHandler::ShowMergeAndSync() {
  if (dom_ui_)  // NULL during testing.
    dom_ui_->CallJavascriptFunction(L"showMergeAndSync");
}

void FlowHandler::ShowSetupDone(const std::wstring& user) {
  StringValue synced_to_string(WideToUTF8(l10n_util::GetStringF(
      IDS_SYNC_NTP_SYNCED_TO, user)));
  std::string json;
  base::JSONWriter::Write(&synced_to_string, false, &json);
  std::wstring javascript = std::wstring(L"setSyncedToUser") +
      L"(" + UTF8ToWide(json) + L");";
  ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);

  if (dom_ui_)
    dom_ui_->CallJavascriptFunction(L"showSetupDone", synced_to_string);
}

void FlowHandler::ShowFirstTimeDone(const std::wstring& user) {
  ExecuteJavascriptInIFrame(kDoneIframeXPath,
                            L"setShowFirstTimeSetupSummary();");
  ShowSetupDone(user);
}

void FlowHandler::ShowMergeAndSyncError() {
  ExecuteJavascriptInIFrame(kMergeIFrameXPath, L"showMergeAndSyncError();");
}

void FlowHandler::ExecuteJavascriptInIFrame(const std::wstring& iframe_xpath,
                                            const std::wstring& js) {
  if (dom_ui_) {
    RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
    rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
  }
}

SyncSetupFlow::~SyncSetupFlow() {
  flow_handler_->set_flow(NULL);
}

void SyncSetupFlow::GetDialogSize(gfx::Size* size) const {
  PrefService* prefs = service_->profile()->GetPrefs();
  gfx::Font approximate_web_font = gfx::Font::CreateFont(
      prefs->GetString(prefs::kWebKitSansSerifFontFamily),
      prefs->GetInteger(prefs::kWebKitDefaultFontSize));

  *size = gfx::GetLocalizedContentsSizeForFont(
      IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
      IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
      approximate_web_font);

#if defined(OS_MACOSX)
  // NOTE(akalin): This is a hack to work around a problem with font height on
  // windows.  Basically font metrics are incorrectly returned in logical units
  // instead of pixels on Windows.  Logical units are very commonly 96 DPI
  // so our localized char/line counts are too small by a factor of 96/72.
  // So we compensate for this on non-windows platform.
  //
  // TODO(akalin): Remove this hack once we fix the windows font problem (or at
  // least work around it in some other place).
  float scale_hack = 96.f/72.f;
  size->set_width(size->width() * scale_hack);
  size->set_height(size->height() * scale_hack);
#endif
}

// A callback to notify the delegate that the dialog closed.
void SyncSetupFlow::OnDialogClosed(const std::string& json_retval) {
  DCHECK(json_retval.empty());
  container_->set_flow(NULL);  // Sever ties from the wizard.
  if (current_state_ == SyncSetupWizard::DONE ||
      current_state_ == SyncSetupWizard::DONE_FIRST_TIME) {
    service_->SetSyncSetupCompleted();
  }

  // Record the state at which the user cancelled the signon dialog.
  switch (current_state_) {
    case SyncSetupWizard::GAIA_LOGIN:
      ProfileSyncService::SyncEvent(
          ProfileSyncService::CANCEL_FROM_SIGNON_WITHOUT_AUTH);
      break;
    case SyncSetupWizard::GAIA_SUCCESS:
      ProfileSyncService::SyncEvent(
          ProfileSyncService::CANCEL_DURING_SIGNON);
      break;
    case SyncSetupWizard::MERGE_AND_SYNC:
      ProfileSyncService::SyncEvent(
          ProfileSyncService::CANCEL_DURING_SIGNON_AFTER_MERGE);
      break;
    case SyncSetupWizard::DONE_FIRST_TIME:
    case SyncSetupWizard::DONE:
      UMA_HISTOGRAM_MEDIUM_TIMES("Sync.UserPerceivedAuthorizationTime",
                                 base::TimeTicks::Now() - login_start_time_);
      break;
    default:
      break;
  }

  service_->OnUserCancelledDialog();
  delete this;
}

// static
void SyncSetupFlow::GetArgsForGaiaLogin(const ProfileSyncService* service,
                                        DictionaryValue* args) {
  const GoogleServiceAuthError& error = service->GetAuthError();
  if (!service->last_attempted_user_email().empty()) {
    args->SetString(L"user", service->last_attempted_user_email());
    args->SetInteger(L"error", error.state());
  } else {
    std::wstring user(UTF16ToWide(service->GetAuthenticatedUsername()));
    args->SetString(L"user", user);
    args->SetInteger(L"error", user.empty() ? 0 : error.state());
  }

  args->SetString(L"captchaUrl", error.captcha().image_url.spec());
}

void SyncSetupFlow::GetDOMMessageHandlers(
    std::vector<DOMMessageHandler*>* handlers) const {
  handlers->push_back(flow_handler_);
}

bool SyncSetupFlow::ShouldAdvance(SyncSetupWizard::State state) {
  switch (state) {
    case SyncSetupWizard::GAIA_LOGIN:
      return current_state_ == SyncSetupWizard::GAIA_LOGIN;
    case SyncSetupWizard::GAIA_SUCCESS:
      return current_state_ == SyncSetupWizard::GAIA_LOGIN;
    case SyncSetupWizard::MERGE_AND_SYNC:
      return current_state_ == SyncSetupWizard::GAIA_SUCCESS;
    case SyncSetupWizard::FATAL_ERROR:
      return true;  // You can always hit the panic button.
    case SyncSetupWizard::DONE_FIRST_TIME:
    case SyncSetupWizard::DONE:
      return current_state_ == SyncSetupWizard::MERGE_AND_SYNC ||
             current_state_ == SyncSetupWizard::GAIA_SUCCESS;
    default:
      NOTREACHED() << "Unhandled State: " << state;
      return false;
  }
}

void SyncSetupFlow::Advance(SyncSetupWizard::State advance_state) {
  if (!ShouldAdvance(advance_state))
    return;
  switch (advance_state) {
    case SyncSetupWizard::GAIA_LOGIN: {
      DictionaryValue args;
      SyncSetupFlow::GetArgsForGaiaLogin(service_, &args);
      flow_handler_->ShowGaiaLogin(args);
      break;
    }
    case SyncSetupWizard::GAIA_SUCCESS:
      if (end_state_ == SyncSetupWizard::GAIA_SUCCESS)
        flow_handler_->ShowGaiaSuccessAndClose();
      else
        flow_handler_->ShowGaiaSuccessAndSettingUp();
      break;
    case SyncSetupWizard::MERGE_AND_SYNC:
      flow_handler_->ShowMergeAndSync();
      break;
    case SyncSetupWizard::FATAL_ERROR:
      if (current_state_ == SyncSetupWizard::MERGE_AND_SYNC)
        flow_handler_->ShowMergeAndSyncError();
      break;
    case SyncSetupWizard::DONE_FIRST_TIME:
      flow_handler_->ShowFirstTimeDone(
          UTF16ToWide(service_->GetAuthenticatedUsername()));
      break;
    case SyncSetupWizard::DONE:
      flow_handler_->ShowSetupDone(
          UTF16ToWide(service_->GetAuthenticatedUsername()));
      break;
    default:
      NOTREACHED() << "Invalid advance state: " << advance_state;
  }
  current_state_ = advance_state;
}

// static
SyncSetupFlow* SyncSetupFlow::Run(ProfileSyncService* service,
                                  SyncSetupFlowContainer* container,
                                  SyncSetupWizard::State start,
                                  SyncSetupWizard::State end) {
  DictionaryValue args;
  if (start == SyncSetupWizard::GAIA_LOGIN)
    SyncSetupFlow::GetArgsForGaiaLogin(service, &args);
  std::string json_args;
  base::JSONWriter::Write(&args, false, &json_args);

  Browser* b = BrowserList::GetLastActive();
  if (!b)
    return NULL;

  FlowHandler* handler = new FlowHandler();
  SyncSetupFlow* flow = new SyncSetupFlow(start, end, json_args,
      container, handler, service);
  handler->set_flow(flow);
  b->BrowserShowHtmlDialog(flow, NULL);
  return flow;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 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 <string>
#include <windows.h>

#include "base/command_line.h"
#include "base/basictypes.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {
  class ChromeLoggingTest : public testing::Test {
   public:
    // Stores the current value of the log file name environment
    // variable and sets the variable to new_value.
    void SaveEnvironmentVariable(std::wstring new_value) {
      unsigned status = GetEnvironmentVariable(env_vars::kLogFileName,
                                               environment_filename_,
                                               MAX_PATH);
      if (!status) {
        wcscpy_s(environment_filename_, L"");
      }

      SetEnvironmentVariable(env_vars::kLogFileName, new_value.c_str());
    }

    // Restores the value of the log file nave environment variable
    // previously saved by SaveEnvironmentVariable().
    void RestoreEnvironmentVariable() {
      SetEnvironmentVariable(env_vars::kLogFileName, environment_filename_);
    }

   private:
    wchar_t environment_filename_[MAX_PATH];  // Saves real environment value.
  };
};

// Tests the log file name getter without an environment variable.
TEST_F(ChromeLoggingTest, LogFileName) {
  SaveEnvironmentVariable(std::wstring());

  FilePath filename = logging::GetLogFileName();
  ASSERT_NE(FilePath::StringType::npos,
            filename.value().find(FILE_PATH_LITERAL("chrome_debug.log")));

  RestoreEnvironmentVariable();
}

// Tests the log file name getter with an environment variable.
TEST_F(ChromeLoggingTest, EnvironmentLogFileName) {
  SaveEnvironmentVariable(std::wstring(L"test value"));

  FilePath filename = logging::GetLogFileName();
  ASSERT_EQ(FilePath(FILE_PATH_LITERAL("test value")).value(),
            filename.value());

  RestoreEnvironmentVariable();
}

#ifndef NDEBUG  // We don't have assertions in release builds.
// Tests whether we correctly fail on browser assertions during tests.
class AssertionTest : public UITest {
 protected:
 AssertionTest() : UITest()
  {
    // Initial loads will never complete due to assertion.
    wait_for_initial_loads_ = false;

    // We're testing the renderer rather than the browser assertion here,
    // because the browser assertion would flunk the test during SetUp()
    // (since TAU wouldn't be able to find the browser window).
    launch_arguments_.AppendSwitch(switches::kRendererAssertTest);
  }
};

// Launch the app in assertion test mode, then close the app.
TEST_F(AssertionTest, Assertion) {
  if (UITest::in_process_renderer()) {
    // in process mode doesn't do the crashing.
    expected_errors_ = 0;
    expected_crashes_ = 0;
  } else {
    expected_errors_ = 1;
    expected_crashes_ = 1;
  }
}
#endif  // NDEBUG

// Tests whether we correctly fail on browser crashes during UI Tests.
class RendererCrashTest : public UITest {
 protected:
 RendererCrashTest() : UITest()
  {
    // Initial loads will never complete due to crash.
    wait_for_initial_loads_ = false;

    launch_arguments_.AppendSwitch(switches::kRendererCrashTest);
  }
};

// Launch the app in renderer crash test mode, then close the app.
TEST_F(RendererCrashTest, Crash) {
  if (UITest::in_process_renderer()) {
    // in process mode doesn't do the crashing.
    expected_crashes_ = 0;
  } else {
    scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
    ASSERT_TRUE(browser.get());
    ASSERT_TRUE(browser->WaitForTabCountToBecome(1, action_max_timeout_ms()));
    expected_crashes_ = 1;
  }
}

// Tests whether we correctly fail on browser crashes during UI Tests.
class BrowserCrashTest : public UITest {
 protected:
 BrowserCrashTest() : UITest()
  {
    // Initial loads will never complete due to crash.
    wait_for_initial_loads_ = false;

    launch_arguments_.AppendSwitch(switches::kBrowserCrashTest);
  }
};

// Launch the app in browser crash test mode.
// This test is disabled. See bug 6910.
TEST_F(BrowserCrashTest, DISABLED_Crash) {
  // Wait while the process is writing the crash dump.
  PlatformThread::Sleep(5000);
  expected_crashes_ = 1;
}
<commit_msg>Remove the BrowserCrashTest.Crash test from the code because it never worked. I will make bug 3910 about creating such test.<commit_after>// Copyright (c) 2006-2009 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 <string>
#include <windows.h>

#include "base/command_line.h"
#include "base/basictypes.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/env_vars.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/ui/ui_test.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {
  class ChromeLoggingTest : public testing::Test {
   public:
    // Stores the current value of the log file name environment
    // variable and sets the variable to new_value.
    void SaveEnvironmentVariable(std::wstring new_value) {
      unsigned status = GetEnvironmentVariable(env_vars::kLogFileName,
                                               environment_filename_,
                                               MAX_PATH);
      if (!status) {
        wcscpy_s(environment_filename_, L"");
      }

      SetEnvironmentVariable(env_vars::kLogFileName, new_value.c_str());
    }

    // Restores the value of the log file nave environment variable
    // previously saved by SaveEnvironmentVariable().
    void RestoreEnvironmentVariable() {
      SetEnvironmentVariable(env_vars::kLogFileName, environment_filename_);
    }

   private:
    wchar_t environment_filename_[MAX_PATH];  // Saves real environment value.
  };
};

// Tests the log file name getter without an environment variable.
TEST_F(ChromeLoggingTest, LogFileName) {
  SaveEnvironmentVariable(std::wstring());

  FilePath filename = logging::GetLogFileName();
  ASSERT_NE(FilePath::StringType::npos,
            filename.value().find(FILE_PATH_LITERAL("chrome_debug.log")));

  RestoreEnvironmentVariable();
}

// Tests the log file name getter with an environment variable.
TEST_F(ChromeLoggingTest, EnvironmentLogFileName) {
  SaveEnvironmentVariable(std::wstring(L"test value"));

  FilePath filename = logging::GetLogFileName();
  ASSERT_EQ(FilePath(FILE_PATH_LITERAL("test value")).value(),
            filename.value());

  RestoreEnvironmentVariable();
}

#ifndef NDEBUG  // We don't have assertions in release builds.
// Tests whether we correctly fail on browser assertions during tests.
class AssertionTest : public UITest {
 protected:
 AssertionTest() : UITest()
  {
    // Initial loads will never complete due to assertion.
    wait_for_initial_loads_ = false;

    // We're testing the renderer rather than the browser assertion here,
    // because the browser assertion would flunk the test during SetUp()
    // (since TAU wouldn't be able to find the browser window).
    launch_arguments_.AppendSwitch(switches::kRendererAssertTest);
  }
};

// Launch the app in assertion test mode, then close the app.
TEST_F(AssertionTest, Assertion) {
  if (UITest::in_process_renderer()) {
    // in process mode doesn't do the crashing.
    expected_errors_ = 0;
    expected_crashes_ = 0;
  } else {
    expected_errors_ = 1;
    expected_crashes_ = 1;
  }
}
#endif  // NDEBUG

// Tests whether we correctly fail on browser crashes during UI Tests.
class RendererCrashTest : public UITest {
 protected:
 RendererCrashTest() : UITest()
  {
    // Initial loads will never complete due to crash.
    wait_for_initial_loads_ = false;

    launch_arguments_.AppendSwitch(switches::kRendererCrashTest);
  }
};

// Launch the app in renderer crash test mode, then close the app.
TEST_F(RendererCrashTest, Crash) {
  if (UITest::in_process_renderer()) {
    // in process mode doesn't do the crashing.
    expected_crashes_ = 0;
  } else {
    scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
    ASSERT_TRUE(browser.get());
    ASSERT_TRUE(browser->WaitForTabCountToBecome(1, action_max_timeout_ms()));
    expected_crashes_ = 1;
  }
}
<|endoftext|>


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

#include <atlbase.h>

#include "base/command_line.h"
#include "base/process_util.h"
#include "base/test/test_suite.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_paths.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/chrome_frame_ui_test_utils.h"
#include "chrome_frame/test_utils.h"
#include "chrome_frame/utils.h"

// To enable ATL-based code to run in this module
class ChromeFrameUnittestsModule
    : public CAtlExeModuleT<ChromeFrameUnittestsModule> {
 public:
  static HRESULT InitializeCom() {
    return CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  }
};

ChromeFrameUnittestsModule _AtlModule;

const char kNoRegistrationSwitch[] = "no-registration";

void PureCall() {
  __debugbreak();
}

// This class implements the Run method and registers an exception handler to
// ensure that any ChromeFrame processes like IE, Firefox, etc are terminated
// if there is a crash in the chrome frame test suite.
class ChromeFrameTestSuite : public base::TestSuite {
 public:
  ChromeFrameTestSuite(int argc, char** argv)
      : base::TestSuite(argc, argv) {}

  int Run() {
    // Register a stack based exception handler to catch any exceptions which
    // occur in the course of the test.
    int ret = -1;
    __try {
      ret = base::TestSuite::Run();
    }

    _except(EXCEPTION_EXECUTE_HANDLER) {
      ret = -1;
    }
    return ret;
  }
};

int main(int argc, char **argv) {
  base::EnableTerminationOnHeapCorruption();
  base::PlatformThread::SetName("ChromeFrame tests");

  _set_purecall_handler(PureCall);

  ChromeFrameTestSuite test_suite(argc, argv);

  SetConfigBool(kChromeFrameHeadlessMode, true);
  SetConfigBool(kChromeFrameAccessibleMode, true);

  base::ProcessHandle crash_service = chrome_frame_test::StartCrashService();
  int ret = -1;
  // If mini_installer is used to register CF, we use the switch
  // --no-registration to avoid repetitive registration.
  if (CommandLine::ForCurrentProcess()->HasSwitch(kNoRegistrationSwitch)) {
    ret = test_suite.Run();
  } else {
    // Register paths needed by the ScopedChromeFrameRegistrar.
    chrome::RegisterPathProvider();

    // This will register the chrome frame in the build directory. It currently
    // leaves that chrome frame registered once the tests are done. It must be
    // constructed AFTER the TestSuite is created since TestSuites create THE
    // AtExitManager.
    // TODO(robertshield): Make these tests restore the original registration
    // once done.
    ScopedChromeFrameRegistrar registrar;

    // Register IAccessible2 proxy stub DLL, needed for some tests.
    ScopedChromeFrameRegistrar ia2_registrar(
        chrome_frame_test::GetIAccessible2ProxyStubPath().value());

    ret = test_suite.Run();
  }

  if (ret == -1) {
    LOG(ERROR) << "ChromeFrame tests crashed";
    chrome_frame_test::KillProcesses(L"iexplore.exe", 0, false);
    chrome_frame_test::KillProcesses(L"firefox.exe", 0, false);
  }

  DeleteConfigValue(kChromeFrameHeadlessMode);
  DeleteConfigValue(kChromeFrameAccessibleMode);

  if (crash_service)
    base::KillProcess(crash_service, 0, false);
}
<commit_msg>Fix a dumb error in the chrome frame tests code which attempts to terminate any running browser processes on a crash. The exception handler was not registered correctly.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <atlbase.h>

#include "base/command_line.h"
#include "base/process_util.h"
#include "base/test/test_suite.h"
#include "base/threading/platform_thread.h"
#include "chrome/common/chrome_paths.h"
#include "chrome_frame/test/chrome_frame_test_utils.h"
#include "chrome_frame/test/chrome_frame_ui_test_utils.h"
#include "chrome_frame/test_utils.h"
#include "chrome_frame/utils.h"

// To enable ATL-based code to run in this module
class ChromeFrameUnittestsModule
    : public CAtlExeModuleT<ChromeFrameUnittestsModule> {
 public:
  static HRESULT InitializeCom() {
    return CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  }
};

ChromeFrameUnittestsModule _AtlModule;

const char kNoRegistrationSwitch[] = "no-registration";

void PureCall() {
  __debugbreak();
}

// This class implements the Run method and registers an exception handler to
// ensure that any ChromeFrame processes like IE, Firefox, etc are terminated
// if there is a crash in the chrome frame test suite.
class ChromeFrameTestSuite : public base::TestSuite {
 public:
  ChromeFrameTestSuite(int argc, char** argv)
      : base::TestSuite(argc, argv) {}

  int Run() {
    // Register a stack based exception handler to catch any exceptions which
    // occur in the course of the test.
    int ret = -1;
    __try {
      ret = base::TestSuite::Run();
    }

    __except(EXCEPTION_EXECUTE_HANDLER) {
      ret = -1;
    }
    return ret;
  }
};

int main(int argc, char **argv) {
  base::EnableTerminationOnHeapCorruption();
  base::PlatformThread::SetName("ChromeFrame tests");

  _set_purecall_handler(PureCall);

  ChromeFrameTestSuite test_suite(argc, argv);

  SetConfigBool(kChromeFrameHeadlessMode, true);
  SetConfigBool(kChromeFrameAccessibleMode, true);

  base::ProcessHandle crash_service = chrome_frame_test::StartCrashService();
  int ret = -1;
  // If mini_installer is used to register CF, we use the switch
  // --no-registration to avoid repetitive registration.
  if (CommandLine::ForCurrentProcess()->HasSwitch(kNoRegistrationSwitch)) {
    ret = test_suite.Run();
  } else {
    // Register paths needed by the ScopedChromeFrameRegistrar.
    chrome::RegisterPathProvider();

    // This will register the chrome frame in the build directory. It currently
    // leaves that chrome frame registered once the tests are done. It must be
    // constructed AFTER the TestSuite is created since TestSuites create THE
    // AtExitManager.
    // TODO(robertshield): Make these tests restore the original registration
    // once done.
    ScopedChromeFrameRegistrar registrar;

    // Register IAccessible2 proxy stub DLL, needed for some tests.
    ScopedChromeFrameRegistrar ia2_registrar(
        chrome_frame_test::GetIAccessible2ProxyStubPath().value());

    ret = test_suite.Run();
  }

  if (ret == -1) {
    LOG(ERROR) << "ChromeFrame tests crashed";
    chrome_frame_test::KillProcesses(L"iexplore.exe", 0, false);
    chrome_frame_test::KillProcesses(L"firefox.exe", 0, false);
  }

  DeleteConfigValue(kChromeFrameHeadlessMode);
  DeleteConfigValue(kChromeFrameAccessibleMode);

  if (crash_service)
    base::KillProcess(crash_service, 0, false);
}
<|endoftext|>


<commit_before>/*
 *  PathResolver.cpp
 *  openc2e
 *
 *  Created by Bryan Donlan
 *  Copyright (c) 2005 Bryan Donlan. All rights reserved.
 *
 *  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 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.
 *
 */

#include "PathResolver.h"

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <set>
#include <map>
#include <cctype>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;
using namespace boost::filesystem;

static set<string> dircache;
static map<string, string> cache;

static bool checkDirCache(path &dir);
static bool doCacheDir(path &dir);

/* C++ is far too verbose for its own good */
static string toLowerCase(string in) {
	transform(in.begin(), in.end(), in.begin(), (int(*)(int))tolower);
	return in;
}

static path lcpath(path &orig) {
	return path(toLowerCase(orig.string()), native);
}

static path lcleaf(path &orig) {
	path br, leaf;
	br = orig.branch_path();
	leaf = path(toLowerCase(orig.leaf()), native);
	return br / leaf;
}

bool resolveFile(path &p) {
	string s = p.string();
	if (!resolveFile(s))
		return false;
	p = path(s);
	return true;
}

bool resolveFile_(string &srcPath) {
	path orig(srcPath, native);
	if (exists(orig))
		return true;

	orig.normalize();
	path dir = orig.branch_path();
	path leaf = path(orig.leaf(), native);

	if (!checkDirCache(dir))
		return false;

	orig = dir / lcpath(leaf);
	string fn = orig.string();

/*	if (exists(orig)) {
		srcPath = fn;
		return true;
	}*/

	map<string, string>::iterator i = cache.find(fn);
	if (i == cache.end()) {
		assert(!exists(orig));
		return false;
	}
	srcPath = cache[fn];
	return true;
}

bool resolveFile(std::string &path) {
	std::string orig = path;
	bool res = resolveFile_(path);
	std::cerr << orig << " -> ";
	if (!res)
		std::cerr << "(nil)";
	else
		std::cerr << path;
	std::cerr << std::endl;
	return res;
}

/* If dir is cached, do nothing.
 * If dir exists, cache it.
 * If dir does not exist, see if there's one with different capitalization.
 *
 * If we find a dir, return true. Else, false.
 */
bool checkDirCache(path &dir) {
	if (dircache.end() != dircache.find(dir.string()))
		return true;
	if (exists(dir))
		return doCacheDir(dir);
	if (dir.empty())
		return false;
	bool res = resolveFile(dir);
	if (!res)
		return false;
	return checkDirCache(dir);
}

/* Cache a dir. Return true for success.
 */
bool doCacheDir(path &dir) {
	directory_iterator it(dir);
	directory_iterator fsend;
	while (it != fsend) {
		path cur = *it++;
		string key, val;
		key = cur.string();
		val = lcleaf(cur).string();
		cache[val] = key;
	}
	dircache.insert(dir.string());
	return true;
}
/* vim: set noet: */
<commit_msg>make PathResolver work, temporarily<commit_after>/*
 *  PathResolver.cpp
 *  openc2e
 *
 *  Created by Bryan Donlan
 *  Copyright (c) 2005 Bryan Donlan. All rights reserved.
 *
 *  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 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.
 *
 */

#include "PathResolver.h"

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <set>
#include <map>
#include <cctype>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;
using namespace boost::filesystem;

static set<string> dircache;
static map<string, string> cache;

static bool checkDirCache(path &dir);
static bool doCacheDir(path &dir);

/* C++ is far too verbose for its own good */
static string toLowerCase(string in) {
	transform(in.begin(), in.end(), in.begin(), (int(*)(int))tolower);
	return in;
}

static path lcpath(path &orig) {
	return path(toLowerCase(orig.string()), native);
}

static path lcleaf(path &orig) {
	path br, leaf;
	br = orig.branch_path();
	leaf = path(toLowerCase(orig.leaf()), native);
	return br / leaf;
}

bool resolveFile(path &p) {
	string s = p.string();
	if (!resolveFile(s))
		return false;
	p = path(s);
	return true;
}

bool resolveFile_(string &srcPath) {
	path orig(srcPath, native);
	if (exists(orig))
		return true;

	orig.normalize();
	path dir = orig.branch_path();
	path leaf = path(orig.leaf(), native);

	if (!checkDirCache(dir))
		return false;

	orig = dir / lcpath(leaf);
	string fn = orig.string();

	if (exists(orig)) {
		srcPath = fn;
		return true;
	}

	map<string, string>::iterator i = cache.find(fn);
	if (i == cache.end()) {
		assert(!exists(orig));
		return false;
	}
	srcPath = cache[fn];
	return true;
}

bool resolveFile(std::string &path) {
	std::string orig = path;
	bool res = resolveFile_(path);
	/*std::cerr << orig << " -> ";
	if (!res)
		std::cerr << "(nil)";
	else
		std::cerr << path;
	std::cerr << std::endl;*/
	return res;
}

/* If dir is cached, do nothing.
 * If dir exists, cache it.
 * If dir does not exist, see if there's one with different capitalization.
 *
 * If we find a dir, return true. Else, false.
 */
bool checkDirCache(path &dir) {
	if (dircache.end() != dircache.find(dir.string()))
		return true;
	if (exists(dir))
		return doCacheDir(dir);
	if (dir.empty())
		return false;
	bool res = resolveFile(dir);
	if (!res)
		return false;
	return checkDirCache(dir);
}

/* Cache a dir. Return true for success.
 */
bool doCacheDir(path &dir) {
	directory_iterator it(dir);
	directory_iterator fsend;
	while (it != fsend) {
		path cur = *it++;
		string key, val;
		key = cur.string();
		val = lcleaf(cur).string();
		cache[val] = key;
	}
	dircache.insert(dir.string());
	return true;
}
/* vim: set noet: */
<|endoftext|>


<commit_before>#include "test.h"
#include "test-stats.h"

#include "grok/context.h"
#include "input/input-stream.h"
#include "input/readline.h"
#include "lexer/lexer.h"
#include "object/jsbasicobject.h"
#include "object/argument.h"
#include "object/function.h"
#include "parser/parser.h"
#include "vm/codegen.h"
#include "vm/context.h"
#include "vm/instruction-list.h"
#include "vm/printer.h"
#include "vm/vm.h"
#include "common/colors.h"

#include <iostream>
#include <cerrno>
#include <chrono>
#include <algorithm>
#include <boost/filesystem.hpp>

using namespace grok;
using namespace grok::vm;
using namespace grok::parser;
using namespace grok::input;

namespace grok {
namespace test {

template<typename Diff>
void log_progress(Diff d)
{
    std::cout <<
    (double)std::chrono::duration_cast
        <std::chrono::microseconds>(d).count() / (double)1000
              << "ms" << std::flush;
}

std::shared_ptr<grok::obj::Handle>
    AssertEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();
    auto msg = args->GetProperty("msg")->as<grok::obj::JSObject>()->ToString();

    if ((rhs->GetType() == grok::obj::ObjectType::_double
        || rhs->GetType() == grok::obj::ObjectType::_number)
        && (lhs->GetType() == grok::obj::ObjectType::_double
        || lhs->GetType() == grok::obj::ObjectType::_number)
        && (rhs->ToString() == lhs->ToString())
        && (rhs->AsString() == lhs->AsString()))
        return grok::obj::CreateUndefinedObject();

    if (rhs->GetType() != lhs->GetType()) {
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " types were not same [ msg: " + msg + "]");
    }
    if (rhs->ToString() != lhs->ToString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " toString's were not same [ msg: " + msg + "]");

    if (rhs->AsString() != lhs->AsString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " asString's were not same [ msg: " + msg + "]");

    return grok::obj::CreateUndefinedObject();
}

std::shared_ptr<grok::obj::Handle>
    AssertNotEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();

    if (rhs->GetType() == lhs->GetType()) {
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());
    }
    if (rhs->ToString() == lhs->ToString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    if (rhs->AsString() == lhs->AsString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    return grok::obj::CreateUndefinedObject();
}

Test &Test::Prepare(std::string file)
{
    file_ = file;
    expected_result_file_ = file;
    expected_result_file_.resize(file.size() - 3);
    expected_result_file_ += ".txt";

    grok::vm::InitializeVMContext();
    auto v = grok::vm::GetGlobalVMContext()->GetVStore();
    auto func = grok::obj::CreateFunction(AssertEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs", "msg" });
    v->StoreValue("assert_equal", func);

    func = grok::obj::CreateFunction(AssertNotEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs" });
    v->StoreValue("assert_not_equal", func);
    return *this;
}

std::string ReadFile(std::string file_)
{
    std::string v;
    if (FILE *fp = fopen(file_.c_str(), "r"))
    {
        char buf[1024];
        while (size_t len = fread(buf, 1, sizeof(buf), fp))
            v.insert(v.end(), buf, buf + len);
        fclose(fp);
    } else {
        std::cout << "fatal: " << file_ << ": "
            << strerror(errno);
        throw std::runtime_error("");
    }
    return v;
}

bool Test::CheckResult(std::string result)
{
    std::string expected_result = ReadFile(expected_result_file_);

    return expected_result == result;
}

bool Test::StartTest(int32_t flags)
{
    std::string file = ReadFile(file_);

    auto lex = std::make_unique<Lexer>(file);

    GrokParser parser{ std::move(lex) };
    if (!parser.ParseExpression())
        return !(flags & f_syntax_errors); // test failed

    auto ast = parser.ParsedAST();

    std::shared_ptr<InstructionList> IR;
    try {
        CodeGenerator codegen;
        codegen.Generate(ast.get());

        IR = codegen.GetIR();
        if (!IR || IR->size() == 0)
            return true;

    } catch (std::exception &e) {
        if (f_print_reason & flags)
            std::cout << e.what() << std::endl;
        return !(flags & f_ir_errors);
    }

    try {
        auto vm = grok::vm::CreateVM(grok::vm::GetGlobalVMContext());
        vm->SetCounters(IR->begin(), IR->end());

        vm->Run();

        Value result = vm->GetResult();
        auto obj = result.O->as<grok::obj::JSObject>();

        std::string res = obj->AsString();

        grok::GetContext()->RunIO();
        return true;
    } catch (std::exception &e) {
        if (flags & f_print_reason)
            std::cout << e.what() << std::endl;
        return !(flags & f_vm_errors);
    }
}

}
}

int main(int argc, char *argv[])
{
    grok::InitializeContext();
    int test_id = -1;

    if (argc >= 2) {
        if (std::string(argv[1]) == "-h" ||
            std::string(argv[1]) == "--help") {
            std::cerr << "Usage: " << argv[0] << " <test_number>" << std::endl;
            return 1;
        } else {
            try {
                test_id = std::stoi(argv[1]);
            } catch (std::exception &e) {
                std::cerr << "bad number" << std::endl;
                return 1;
            }
        }
    }
    grok::GetContext()->SetDebugExecution();
    using namespace boost::filesystem;
    using namespace grok::test;
    using namespace std;

    path p("../test/testing");

    try {
        if (!exists(p)) {
            std::cerr << "There is no test directory! Did you delete it?"
             << std::endl;
        }

        if (!is_directory(p)) {
            std::cerr << "It is odd. 'test' was always a directory containing"
                " many test files but it turns out that 'test' is not a "
                "directory at all." << std::endl;
        }

        // we are good
        std::vector<std::string> files;
        size_t count = 0;
    	directory_iterator e;
        for (directory_iterator it(p); it != e; ++it) {
            std::cout << "\rCounting test files: " << count++;
            std::cout << std::flush;
            files.push_back(it->path().string());
        }
        std::cout << std::endl;

        std::sort(files.begin(), files.end());
        TestStats stats;
        size_t i = 0;

        // run the tests

        if (test_id < 0) {
            for (auto file : files) {
                auto s = std::chrono::high_resolution_clock::now();

                std::cout << "Testing '" << file + '\'' << std::endl;
                Test test{ grok::GetContext() };

                if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                        | f_vm_errors | f_print_reason)) {
                    std::cout << "Test[" << ++i << "] <"
                        << file << ">: passed.";
                    stats.AddPassed();
                } else {
                    std::cout << "Test[" << ++i << "] <"
                        << file << ">: failed.";
                    stats.AddFailed();
                }

                auto e = std::chrono::high_resolution_clock::now();
                std::cout << "[ time: ";
                log_progress(e - s);
                std::cout << " ]" << std::endl;
            }
        } else {
            auto s = std::chrono::high_resolution_clock::now();
            if (test_id > files.size()) {
                std::cerr << "test not written yet!" << std::endl;
                return 1;
            }
            auto file = files[test_id];
            std::cout << "Testing '" << file + '\'' << std::endl;
            Test test{ grok::GetContext() };

            if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                    | f_vm_errors | f_print_reason)) {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: passed.";
                stats.AddPassed();
            } else {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: failed.";
                stats.AddFailed();
            }

            auto e = std::chrono::high_resolution_clock::now();
            std::cout << "[ time: ";
            log_progress(e - s);
            std::cout << " ]" << std::endl;
        }

        std::cout << stats << std::endl;
        return 0;
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
    return -1;
}

<commit_msg>Show colored output<commit_after>#include "test.h"
#include "test-stats.h"

#include "grok/context.h"
#include "input/input-stream.h"
#include "input/readline.h"
#include "lexer/lexer.h"
#include "object/jsbasicobject.h"
#include "object/argument.h"
#include "object/function.h"
#include "parser/parser.h"
#include "vm/codegen.h"
#include "vm/context.h"
#include "vm/instruction-list.h"
#include "vm/printer.h"
#include "vm/vm.h"
#include "common/colors.h"

#include <iostream>
#include <cerrno>
#include <chrono>
#include <algorithm>
#include <boost/filesystem.hpp>

using namespace grok;
using namespace grok::vm;
using namespace grok::parser;
using namespace grok::input;

namespace grok {
namespace test {

template<typename Diff>
void log_progress(Diff d)
{
    std::cout <<
    (double)std::chrono::duration_cast
        <std::chrono::microseconds>(d).count() / (double)1000
              << "ms" << std::flush;
}

std::shared_ptr<grok::obj::Handle>
    AssertEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();
    auto msg = args->GetProperty("msg")->as<grok::obj::JSObject>()->ToString();

    if ((rhs->GetType() == grok::obj::ObjectType::_double
        || rhs->GetType() == grok::obj::ObjectType::_number)
        && (lhs->GetType() == grok::obj::ObjectType::_double
        || lhs->GetType() == grok::obj::ObjectType::_number)
        && (rhs->ToString() == lhs->ToString())
        && (rhs->AsString() == lhs->AsString()))
        return grok::obj::CreateUndefinedObject();

    if (rhs->GetType() != lhs->GetType()) {
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " types were not same [ msg: " + msg + "]");
    }
    if (rhs->ToString() != lhs->ToString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " toString's were not same [ msg: " + msg + "]");

    if (rhs->AsString() != lhs->AsString())
        throw std::runtime_error(std::string("AssertEqual failed: ")
            + rhs->ToString() + " is not equal to " + lhs->ToString()
            + " asString's were not same [ msg: " + msg + "]");

    return grok::obj::CreateUndefinedObject();
}

std::shared_ptr<grok::obj::Handle>
    AssertNotEqual(std::shared_ptr<grok::obj::Argument> args)
{
    auto rhs = args->GetProperty("rhs")->as<grok::obj::JSObject>();
    auto lhs = args->GetProperty("lhs")->as<grok::obj::JSObject>();

    if (rhs->GetType() == lhs->GetType()) {
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());
    }
    if (rhs->ToString() == lhs->ToString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    if (rhs->AsString() == lhs->AsString())
        throw std::runtime_error(std::string("AssertNotEqual failed: ")
            + rhs->ToString() + " is equal to " + lhs->ToString());

    return grok::obj::CreateUndefinedObject();
}

Test &Test::Prepare(std::string file)
{
    file_ = file;
    expected_result_file_ = file;
    expected_result_file_.resize(file.size() - 3);
    expected_result_file_ += ".txt";

    grok::vm::InitializeVMContext();
    auto v = grok::vm::GetGlobalVMContext()->GetVStore();
    auto func = grok::obj::CreateFunction(AssertEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs", "msg" });
    v->StoreValue("assert_equal", func);

    func = grok::obj::CreateFunction(AssertNotEqual);
    func->as<grok::obj::Function>()->SetParams({ "lhs", "rhs" });
    v->StoreValue("assert_not_equal", func);
    return *this;
}

std::string ReadFile(std::string file_)
{
    std::string v;
    if (FILE *fp = fopen(file_.c_str(), "r"))
    {
        char buf[1024];
        while (size_t len = fread(buf, 1, sizeof(buf), fp))
            v.insert(v.end(), buf, buf + len);
        fclose(fp);
    } else {
        std::cout << "fatal: " << file_ << ": "
            << strerror(errno);
        throw std::runtime_error("");
    }
    return v;
}

bool Test::CheckResult(std::string result)
{
    std::string expected_result = ReadFile(expected_result_file_);

    return expected_result == result;
}

bool Test::StartTest(int32_t flags)
{
    std::string file = ReadFile(file_);

    auto lex = std::make_unique<Lexer>(file);

    GrokParser parser{ std::move(lex) };
    if (!parser.ParseExpression())
        return !(flags & f_syntax_errors); // test failed

    auto ast = parser.ParsedAST();

    std::shared_ptr<InstructionList> IR;
    try {
        CodeGenerator codegen;
        codegen.Generate(ast.get());

        IR = codegen.GetIR();
        if (!IR || IR->size() == 0)
            return true;

    } catch (std::exception &e) {
        if (f_print_reason & flags)
            std::cout << e.what() << std::endl;
        return !(flags & f_ir_errors);
    }

    try {
        auto vm = grok::vm::CreateVM(grok::vm::GetGlobalVMContext());
        vm->SetCounters(IR->begin(), IR->end());

        vm->Run();

        Value result = vm->GetResult();
        auto obj = result.O->as<grok::obj::JSObject>();

        std::string res = obj->AsString();

        grok::GetContext()->RunIO();
        return true;
    } catch (std::exception &e) {
        if (flags & f_print_reason)
            std::cout << e.what() << std::endl;
        return !(flags & f_vm_errors);
    }
}

}
}

int main(int argc, char *argv[])
{
    grok::InitializeContext();
    int test_id = -1;

    if (argc >= 2) {
        if (std::string(argv[1]) == "-h" ||
            std::string(argv[1]) == "--help") {
            std::cerr << "Usage: " << argv[0] << " <test_number>" << std::endl;
            return 1;
        } else {
            try {
                test_id = std::stoi(argv[1]);
            } catch (std::exception &e) {
                std::cerr << "bad number" << std::endl;
                return 1;
            }
        }
    }
    grok::GetContext()->SetDebugExecution();
    using namespace boost::filesystem;
    using namespace grok::test;
    using namespace std;

    path p("../test/testing");

    try {
        if (!exists(p)) {
            std::cerr << "There is no test directory! Did you delete it?"
             << std::endl;
        }

        if (!is_directory(p)) {
            std::cerr << "It is odd. 'test' was always a directory containing"
                " many test files but it turns out that 'test' is not a "
                "directory at all." << std::endl;
        }

        // we are good
        std::vector<std::string> files;
        size_t count = 0;
    	directory_iterator e;
        for (directory_iterator it(p); it != e; ++it) {
            std::cout << "\rCounting test files: " << count++;
            std::cout << std::flush;
            files.push_back(it->path().string());
        }
        std::cout << std::endl;

        std::sort(files.begin(), files.end());
        TestStats stats;
        size_t i = 0;

        // run the tests

        if (test_id < 0) {
            for (auto file : files) {
                auto s = std::chrono::high_resolution_clock::now();

                std::cout << "Testing '" << file + '\'' << std::endl;
                Test test{ grok::GetContext() };

                if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                        | f_vm_errors | f_print_reason)) {
                    std::cout << Color::Color(Color::fgreen, Color::dim)
                            << "Test[" << ++i << "] <" << file
                            << ">: passed." << Color::Reset();
                    stats.AddPassed();
                } else {
                    std::cout << Color::Color(Color::fgreen, Color::bold)
                        << "Test[" << ++i << "] <"
                        << file << ">: failed." << Color::Reset();
                    stats.AddFailed();
                }

                auto e = std::chrono::high_resolution_clock::now();
                std::cout << "[ time: ";
                log_progress(e - s);
                std::cout << " ]" << std::endl;
            }
        } else {
            auto s = std::chrono::high_resolution_clock::now();
            if (test_id > files.size()) {
                std::cerr << "test not written yet!" << std::endl;
                return 1;
            }
            auto file = files[test_id];
            std::cout << "Testing '" << file + '\'' << std::endl;
            Test test{ grok::GetContext() };

            if (test.Prepare(file).StartTest(f_syntax_errors | f_ir_errors
                    | f_vm_errors | f_print_reason)) {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: passed.";
                stats.AddPassed();
            } else {
                std::cout << "Test[" << ++i << "] <"
                    << file << ">: failed.";
                stats.AddFailed();
            }

            auto e = std::chrono::high_resolution_clock::now();
            std::cout << "[ time: ";
            log_progress(e - s);
            std::cout << " ]" << std::endl;
        }

        std::cout << stats << std::endl;
        return 0;
    } catch (std::exception &e) {
        std::cerr << e.what() << std::endl;
    }
    return -1;
}

<|endoftext|>