<commit_before>
#include <QDebug>
#include <QMetaEnum>
#include <QProcessEnvironment>
#include <QCoreApplication>
#include <QUrl>

#include "libsshqtprocess.h"
#include "libsshqtclient.h"
#include "libsshqtdebug.h"

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// LibsshQtProcess
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

LibsshQtProcess::LibsshQtProcess(LibsshQtClient *parent) :
    LibsshQtChannel(false, parent, parent),
    state_(StateClosed),
    exit_code_(-1),
    stderr_(new LibsshQtProcessStderr(this))
{
    debug_prefix_ = LibsshQt::debugPrefix(this);

    LIBSSHQT_DEBUG("Constructor");

    timer_.setSingleShot(true);
    timer_.setInterval(0);

    connect(&timer_, SIGNAL(timeout()),        this, SLOT(processState()));
    connect(parent,  SIGNAL(error()),          this, SLOT(handleClientError()));
    connect(parent,  SIGNAL(doProcessState()), this, SLOT(processState()));
    connect(parent,  SIGNAL(doCleanup()),      this, SLOT(closeChannel()));

    setStdoutBehaviour(OutputToQDebug, "Remote stdout:");
    setStderrBehaviour(OutputToQDebug, "Remote stderr:");
}

LibsshQtProcess::~LibsshQtProcess()
{
    LIBSSHQT_DEBUG("Destructor");
    closeChannel();
}

const char *LibsshQtProcess::enumToString(const State value)
{
    return staticMetaObject.enumerator(
                staticMetaObject.indexOfEnumerator("State"))
                    .valueToKey(value);
}

const char *LibsshQtProcess::enumToString(const OutputBehaviour value)
{
    return staticMetaObject.enumerator(
                staticMetaObject.indexOfEnumerator("OutputBehaviour"))
                    .valueToKey(value);
}

void LibsshQtProcess::setCommand(QString command)
{
    command_ = command;
    LIBSSHQT_DEBUG("Setting command to" << command);
}

QString LibsshQtProcess::command() const
{
    return command_;
}

int LibsshQtProcess::exitCode() const
{
    return exit_code_;
}

void LibsshQtProcess::setStdoutBehaviour(OutputBehaviour behaviour,
                                         QString         prefix)
{
    LIBSSHQT_DEBUG("Setting stdout behaviour to" << behaviour);

    stdout_behaviour_     = behaviour;
    stdout_output_prefix_ = prefix;

    if ( behaviour == OutputManual ) {
        disconnect(this, SIGNAL(readyRead()),
                   this, SLOT(handleStdoutOutput()));

    } else {
        connect(this, SIGNAL(readyRead()),
                this, SLOT(handleStdoutOutput()),
                Qt::UniqueConnection);
        handleStdoutOutput();
    }
}

void LibsshQtProcess::setStderrBehaviour(OutputBehaviour behaviour,
                                         QString         prefix)
{
    LIBSSHQT_DEBUG("Setting stderr behaviour to" << behaviour);

    stderr_behaviour_     = behaviour;
    stderr_output_prefix_ = prefix;

    if ( behaviour == OutputManual ) {
        disconnect(stderr_, SIGNAL(readyRead()),
                   this, SLOT(handleStderrOutput()));

    } else {
        connect(stderr_, SIGNAL(readyRead()),
                this, SLOT(handleStderrOutput()),
                Qt::UniqueConnection);
        handleStderrOutput();
    }
}

LibsshQtProcessStderr *LibsshQtProcess::stderr()
{
    return stderr_;
}

LibsshQtProcess::State LibsshQtProcess::state() const
{
    return state_;
}

/*!
    Same as openChannel()
*/
bool LibsshQtProcess::open(OpenMode ignored)
{
    Q_UNUSED( ignored );
    openChannel();
    return true;
}

/*!
    If the process has been successfully opened this function calls sendEof()
    otherwise closeChannel() is called.

    In either case you should wait for closed signal before deletin the
    LibsshQtProcess.
*/
void LibsshQtProcess::close()
{
    if ( state_ == StateOpen ) {
        sendEof();
    } else {
        closeChannel();
    }
}

/*!
    Open SSH channel and start the process.
*/
void LibsshQtProcess::openChannel()
{
    if ( state_ == StateClosed ) {
        setState(StateWaitClient);
        timer_.start();
    }
}

/*!
    This function closes the SSH channel immediadly and prepares the object for
    reuse, any possible data in buffers is discarded.
*/
void LibsshQtProcess::closeChannel()
{
    if ( state_ != StateClosed &&
         state_ != StateClosing ){

        // Prevent recursion
        setState(StateClosing);

        emit readChannelFinished();
        handleStdoutOutput();
        handleStderrOutput();

        if ( channel_ ) {
            if ( ssh_channel_is_open(channel_) != 0 ) {
                ssh_channel_close(channel_);
            }

            ssh_channel_free(channel_);
            channel_ = 0;
        }

        QIODevice::close();
        reinterpret_cast< QIODevice* >( stderr_ )->close();

        read_buffer_.clear();
        write_buffer_.clear();
        stderr_->read_buffer_.clear();
        stderr_->write_buffer_.clear();

        setState(StateClosed);
    }
}

void LibsshQtProcess::setState(State state)
{
    if ( state_ == state ) {
        LIBSSHQT_DEBUG("State is already" << state);
        return;
    }

    LIBSSHQT_DEBUG("Changing state to" << state);
    state_ = state;

    switch (  state_ ) {
    case StateClosed:       emit closed();          break;
    case StateClosing:                              break;
    case StateWaitClient:                           break;
    case StateOpening:                              break;
    case StateExec:                                 break;
    case StateOpen:         emit opened();          break;
    case StateError:        emit error();           break;
    case StateClientError:  emit error();           break;
    }
}

void LibsshQtProcess::queueCheckIo()
{
    timer_.start();
}

void LibsshQtProcess::processState()
{
    switch ( state_ ) {

    case StateClosed:
    case StateClosing:
    case StateError:
    case StateClientError:
        return;

    case StateWaitClient:
    {
        if ( client_->state() == LibsshQtClient::StateOpened ) {
            setState(StateOpening);
            timer_.start();
        }
        return;
    } break;

    case StateOpening:
    {
        if ( ! channel_ ) {
            ssh_channel channel = ssh_channel_new(client_->sshSession());

            if ( channel ) {
                channel_ = channel;
                stderr_->channel_ = channel;

            } else {
                LIBSSHQT_FATAL("Could not create SSH channel");
            }
        }

        int rc = ssh_channel_open_session(channel_);

        switch ( rc ) {
        case SSH_AGAIN:
            client_->enableWritableNotifier();
            return;

        case SSH_ERROR:
            LIBSSHQT_DEBUG("Channel open error:" << errorCodeAndMessage());
            setState(StateError);
            return;

        case SSH_OK:
            setState(StateExec);
            timer_.start();
            return;

        default:
            LIBSSHQT_CRITICAL("Unknown result code" << rc <<
                              "received from ssh_channel_open_session()");
            return;
        }
    } break;

    case StateExec:
    {
        int rc = ssh_channel_request_exec(channel_, qPrintable(command_));

        switch ( rc ) {
        case SSH_AGAIN:
            client_->enableWritableNotifier();
            return;

        case SSH_ERROR:
            LIBSSHQT_DEBUG("Channel exec error:" << errorCodeAndMessage());
            setState(StateError);
            return;

        case SSH_OK:
            // Set Unbuffered to disable QIODevice buffers.
            if ( ! QIODevice::open( ReadWrite | Unbuffered )) {
                LIBSSHQT_FATAL("QIODevice::open() failed");
            }

            stderr_->open();
            setState(StateOpen);
            timer_.start();
            return;

        default:
            LIBSSHQT_CRITICAL("Unknown result code" << rc <<
                              "received from ssh_channel_request_exec()");
            return;
        }
    } break;

    case StateOpen:
    {
        checkIo();
        stderr_->checkIo();

        if ( state_ == StateOpen &&
             ssh_channel_poll(channel_, false) == SSH_EOF &&
             ssh_channel_poll(channel_, true)  == SSH_EOF ) {

            exit_code_ = ssh_channel_get_exit_status(channel_);

            LIBSSHQT_DEBUG("Process channel EOF");
            LIBSSHQT_DEBUG("Command exit code:"     << exit_code_);
            LIBSSHQT_DEBUG("Data in read buffer:"   << read_buffer_.size());
            LIBSSHQT_DEBUG("Data in write buffer:"  << write_buffer_.size());
            LIBSSHQT_DEBUG("Data in stderr buffer:" <<
                           stderr_->read_buffer_.size());

            closeChannel();
            emit finished(exit_code_);
            return;
        }

        return;
    } break;

    } // End switch

    Q_ASSERT_X(false, __func__, "Case was not handled properly");
}

void LibsshQtProcess::handleClientError()
{
    setState(LibsshQtProcess::StateClientError);
}

void LibsshQtProcess::handleStdoutOutput()
{
    if ( stdout_behaviour_ == OutputManual) return;

    while ( canReadLine()) {
        QString line = QString(readLine());
        handleOutput(stdout_behaviour_, stdout_output_prefix_, line);
    }
}

void LibsshQtProcess::handleStderrOutput()
{
    if ( stderr_behaviour_ == OutputManual) return;

    Q_ASSERT(stderr_);
    while ( stderr_->canReadLine()) {
        QString line = QString(stderr()->readLine());
        handleOutput(stderr_behaviour_, stderr_output_prefix_, line);
    }
}

void LibsshQtProcess::handleOutput(OutputBehaviour &behaviour,
                                   QString             &prefix,
                                   QString             &line)
{
    switch ( behaviour ) {
    case OutputManual:
    case OutputToDevNull:
        // Do nothing
        return;

    case OutputToQDebug:
        if ( line.endsWith('\n')) {
            line.remove(line.length() - 1, 1);
        }

        if ( prefix.isEmpty()) {
            qDebug() << qPrintable(line);
        } else {
            qDebug() << qPrintable(prefix)
                     << qPrintable(line);
        }
        return;
    }
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// LibsshQtProcessStderr
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

LibsshQtProcessStderr::LibsshQtProcessStderr(LibsshQtProcess *parent) :
    LibsshQtChannel(true, parent->client(), parent)
{
    debug_prefix_ = LibsshQt::debugPrefix(this);
}

void LibsshQtProcessStderr::close()
{
    reinterpret_cast<LibsshQtProcess *>(parent())->close();
}

bool LibsshQtProcessStderr::open(OpenMode ignored)
{
    Q_UNUSED( ignored );

    // Set Unbuffered to disable QIODevice buffers.
     if ( ! QIODevice::open( ReadWrite | Unbuffered )) {
        LIBSSHQT_FATAL("QIODevice::open() failed");
    }
    return true;
}

void LibsshQtProcessStderr::queueCheckIo()
{
    reinterpret_cast<LibsshQtProcess *>(parent())->queueCheckIo();
}

<commit_msg>Emit readyRead signal after EOF if there is data in readbuffer<commit_after>
#include <QDebug>
#include <QMetaEnum>
#include <QProcessEnvironment>
#include <QCoreApplication>
#include <QUrl>

#include "libsshqtprocess.h"
#include "libsshqtclient.h"
#include "libsshqtdebug.h"

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// LibsshQtProcess
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

LibsshQtProcess::LibsshQtProcess(LibsshQtClient *parent) :
    LibsshQtChannel(false, parent, parent),
    state_(StateClosed),
    exit_code_(-1),
    stderr_(new LibsshQtProcessStderr(this))
{
    debug_prefix_ = LibsshQt::debugPrefix(this);

    LIBSSHQT_DEBUG("Constructor");

    timer_.setSingleShot(true);
    timer_.setInterval(0);

    connect(&timer_, SIGNAL(timeout()),        this, SLOT(processState()));
    connect(parent,  SIGNAL(error()),          this, SLOT(handleClientError()));
    connect(parent,  SIGNAL(doProcessState()), this, SLOT(processState()));
    connect(parent,  SIGNAL(doCleanup()),      this, SLOT(closeChannel()));

    setStdoutBehaviour(OutputToQDebug, "Remote stdout:");
    setStderrBehaviour(OutputToQDebug, "Remote stderr:");
}

LibsshQtProcess::~LibsshQtProcess()
{
    LIBSSHQT_DEBUG("Destructor");
    closeChannel();
}

const char *LibsshQtProcess::enumToString(const State value)
{
    return staticMetaObject.enumerator(
                staticMetaObject.indexOfEnumerator("State"))
                    .valueToKey(value);
}

const char *LibsshQtProcess::enumToString(const OutputBehaviour value)
{
    return staticMetaObject.enumerator(
                staticMetaObject.indexOfEnumerator("OutputBehaviour"))
                    .valueToKey(value);
}

void LibsshQtProcess::setCommand(QString command)
{
    command_ = command;
    LIBSSHQT_DEBUG("Setting command to" << command);
}

QString LibsshQtProcess::command() const
{
    return command_;
}

int LibsshQtProcess::exitCode() const
{
    return exit_code_;
}

void LibsshQtProcess::setStdoutBehaviour(OutputBehaviour behaviour,
                                         QString         prefix)
{
    LIBSSHQT_DEBUG("Setting stdout behaviour to" << behaviour);

    stdout_behaviour_     = behaviour;
    stdout_output_prefix_ = prefix;

    if ( behaviour == OutputManual ) {
        disconnect(this, SIGNAL(readyRead()),
                   this, SLOT(handleStdoutOutput()));

    } else {
        connect(this, SIGNAL(readyRead()),
                this, SLOT(handleStdoutOutput()),
                Qt::UniqueConnection);
        handleStdoutOutput();
    }
}

void LibsshQtProcess::setStderrBehaviour(OutputBehaviour behaviour,
                                         QString         prefix)
{
    LIBSSHQT_DEBUG("Setting stderr behaviour to" << behaviour);

    stderr_behaviour_     = behaviour;
    stderr_output_prefix_ = prefix;

    if ( behaviour == OutputManual ) {
        disconnect(stderr_, SIGNAL(readyRead()),
                   this, SLOT(handleStderrOutput()));

    } else {
        connect(stderr_, SIGNAL(readyRead()),
                this, SLOT(handleStderrOutput()),
                Qt::UniqueConnection);
        handleStderrOutput();
    }
}

LibsshQtProcessStderr *LibsshQtProcess::stderr()
{
    return stderr_;
}

LibsshQtProcess::State LibsshQtProcess::state() const
{
    return state_;
}

/*!
    Same as openChannel()
*/
bool LibsshQtProcess::open(OpenMode ignored)
{
    Q_UNUSED( ignored );
    openChannel();
    return true;
}

/*!
    If the process has been successfully opened this function calls sendEof()
    otherwise closeChannel() is called.

    In either case you should wait for closed signal before deletin the
    LibsshQtProcess.
*/
void LibsshQtProcess::close()
{
    if ( state_ == StateOpen ) {
        sendEof();
    } else {
        closeChannel();
    }
}

/*!
    Open SSH channel and start the process.
*/
void LibsshQtProcess::openChannel()
{
    if ( state_ == StateClosed ) {
        setState(StateWaitClient);
        timer_.start();
    }
}

/*!
    This function closes the SSH channel immediadly and prepares the object for
    reuse, any possible data in buffers is discarded.
*/
void LibsshQtProcess::closeChannel()
{
    if ( state_ != StateClosed &&
         state_ != StateClosing ){

        // Prevent recursion
        setState(StateClosing);

        emit readChannelFinished();
        handleStdoutOutput();
        handleStderrOutput();

        if ( channel_ ) {
            if ( ssh_channel_is_open(channel_) != 0 ) {
                ssh_channel_close(channel_);
            }

            ssh_channel_free(channel_);
            channel_ = 0;
        }

        QIODevice::close();
        reinterpret_cast< QIODevice* >( stderr_ )->close();

        read_buffer_.clear();
        write_buffer_.clear();
        stderr_->read_buffer_.clear();
        stderr_->write_buffer_.clear();

        setState(StateClosed);
    }
}

void LibsshQtProcess::setState(State state)
{
    if ( state_ == state ) {
        LIBSSHQT_DEBUG("State is already" << state);
        return;
    }

    LIBSSHQT_DEBUG("Changing state to" << state);
    state_ = state;

    switch (  state_ ) {
    case StateClosed:       emit closed();          break;
    case StateClosing:                              break;
    case StateWaitClient:                           break;
    case StateOpening:                              break;
    case StateExec:                                 break;
    case StateOpen:         emit opened();          break;
    case StateError:        emit error();           break;
    case StateClientError:  emit error();           break;
    }
}

void LibsshQtProcess::queueCheckIo()
{
    timer_.start();
}

void LibsshQtProcess::processState()
{
    switch ( state_ ) {

    case StateClosed:
    case StateClosing:
    case StateError:
    case StateClientError:
        return;

    case StateWaitClient:
    {
        if ( client_->state() == LibsshQtClient::StateOpened ) {
            setState(StateOpening);
            timer_.start();
        }
        return;
    } break;

    case StateOpening:
    {
        if ( ! channel_ ) {
            ssh_channel channel = ssh_channel_new(client_->sshSession());

            if ( channel ) {
                channel_ = channel;
                stderr_->channel_ = channel;

            } else {
                LIBSSHQT_FATAL("Could not create SSH channel");
            }
        }

        int rc = ssh_channel_open_session(channel_);

        switch ( rc ) {
        case SSH_AGAIN:
            client_->enableWritableNotifier();
            return;

        case SSH_ERROR:
            LIBSSHQT_DEBUG("Channel open error:" << errorCodeAndMessage());
            setState(StateError);
            return;

        case SSH_OK:
            setState(StateExec);
            timer_.start();
            return;

        default:
            LIBSSHQT_CRITICAL("Unknown result code" << rc <<
                              "received from ssh_channel_open_session()");
            return;
        }
    } break;

    case StateExec:
    {
        int rc = ssh_channel_request_exec(channel_, qPrintable(command_));

        switch ( rc ) {
        case SSH_AGAIN:
            client_->enableWritableNotifier();
            return;

        case SSH_ERROR:
            LIBSSHQT_DEBUG("Channel exec error:" << errorCodeAndMessage());
            setState(StateError);
            return;

        case SSH_OK:
            // Set Unbuffered to disable QIODevice buffers.
            if ( ! QIODevice::open( ReadWrite | Unbuffered )) {
                LIBSSHQT_FATAL("QIODevice::open() failed");
            }

            stderr_->open();
            setState(StateOpen);
            timer_.start();
            return;

        default:
            LIBSSHQT_CRITICAL("Unknown result code" << rc <<
                              "received from ssh_channel_request_exec()");
            return;
        }
    } break;

    case StateOpen:
    {
        checkIo();
        stderr_->checkIo();

        if ( state_ == StateOpen &&
             ssh_channel_poll(channel_, false) == SSH_EOF &&
             ssh_channel_poll(channel_, true)  == SSH_EOF ) {

            // EOF state affects atEnd() and canReadLine() behavior,
            // so emit readyRead signal so that users can do something about it.
            if ( ! read_buffer_.isEmpty()) {
                emit readyRead();
            }
            if ( ! stderr_->read_buffer_.isEmpty()) {
                emit stderr_->readyRead();
            }

            exit_code_ = ssh_channel_get_exit_status(channel_);

            LIBSSHQT_DEBUG("Process channel EOF");
            LIBSSHQT_DEBUG("Command exit code:"     << exit_code_);
            LIBSSHQT_DEBUG("Data in read buffer:"   << read_buffer_.size());
            LIBSSHQT_DEBUG("Data in write buffer:"  << write_buffer_.size());
            LIBSSHQT_DEBUG("Data in stderr buffer:" <<
                           stderr_->read_buffer_.size());

            closeChannel();
            emit finished(exit_code_);
            return;
        }

        return;
    } break;

    } // End switch

    Q_ASSERT_X(false, __func__, "Case was not handled properly");
}

void LibsshQtProcess::handleClientError()
{
    setState(LibsshQtProcess::StateClientError);
}

void LibsshQtProcess::handleStdoutOutput()
{
    if ( stdout_behaviour_ == OutputManual) return;

    while ( canReadLine()) {
        QString line = QString(readLine());
        handleOutput(stdout_behaviour_, stdout_output_prefix_, line);
    }
}

void LibsshQtProcess::handleStderrOutput()
{
    if ( stderr_behaviour_ == OutputManual) return;

    Q_ASSERT(stderr_);
    while ( stderr_->canReadLine()) {
        QString line = QString(stderr()->readLine());
        handleOutput(stderr_behaviour_, stderr_output_prefix_, line);
    }
}

void LibsshQtProcess::handleOutput(OutputBehaviour &behaviour,
                                   QString             &prefix,
                                   QString             &line)
{
    switch ( behaviour ) {
    case OutputManual:
    case OutputToDevNull:
        // Do nothing
        return;

    case OutputToQDebug:
        if ( line.endsWith('\n')) {
            line.remove(line.length() - 1, 1);
        }

        if ( prefix.isEmpty()) {
            qDebug() << qPrintable(line);
        } else {
            qDebug() << qPrintable(prefix)
                     << qPrintable(line);
        }
        return;
    }
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// LibsshQtProcessStderr
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

LibsshQtProcessStderr::LibsshQtProcessStderr(LibsshQtProcess *parent) :
    LibsshQtChannel(true, parent->client(), parent)
{
    debug_prefix_ = LibsshQt::debugPrefix(this);
}

void LibsshQtProcessStderr::close()
{
    reinterpret_cast<LibsshQtProcess *>(parent())->close();
}

bool LibsshQtProcessStderr::open(OpenMode ignored)
{
    Q_UNUSED( ignored );

    // Set Unbuffered to disable QIODevice buffers.
     if ( ! QIODevice::open( ReadWrite | Unbuffered )) {
        LIBSSHQT_FATAL("QIODevice::open() failed");
    }
    return true;
}

void LibsshQtProcessStderr::queueCheckIo()
{
    reinterpret_cast<LibsshQtProcess *>(parent())->queueCheckIo();
}

<|endoftext|>


<commit_before>#include "globals.hh"
#include "util.hh"
#include "archive.hh"
#include "args.hh"

#include <algorithm>
#include <map>
#include <thread>
#include <dlfcn.h>

namespace nix {

/* The default location of the daemon socket, relative to nixStateDir.
   The socket is in a directory to allow you to control access to the
   Nix daemon by setting the mode/ownership of the directory
   appropriately.  (This wouldn't work on the socket itself since it
   must be deleted and recreated on startup.) */
#define DEFAULT_SOCKET_PATH "/daemon-socket/socket"

/* chroot-like behavior from Apple's sandbox */
#if __APPLE__
    #define DEFAULT_ALLOWED_IMPURE_PREFIXES "/System/Library /usr/lib /dev /bin/sh"
#else
    #define DEFAULT_ALLOWED_IMPURE_PREFIXES ""
#endif

Settings settings;

Settings::Settings()
    : Config({})
    , nixPrefix(NIX_PREFIX)
    , nixStore(canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR))))
    , nixDataDir(canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR)))
    , nixLogDir(canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR)))
    , nixStateDir(canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR)))
    , nixConfDir(canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR)))
    , nixLibexecDir(canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR)))
    , nixBinDir(canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR)))
    , nixManDir(canonPath(NIX_MAN_DIR))
    , nixDaemonSocketFile(canonPath(nixStateDir + DEFAULT_SOCKET_PATH))
{
    buildUsersGroup = getuid() == 0 ? "nixbld" : "";
    lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1";

    caFile = getEnv("NIX_SSL_CERT_FILE", getEnv("SSL_CERT_FILE", ""));
    if (caFile == "") {
        for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
            if (pathExists(fn)) {
                caFile = fn;
                break;
            }
    }

    /* Backwards compatibility. */
    auto s = getEnv("NIX_REMOTE_SYSTEMS");
    if (s != "") {
        Strings ss;
        for (auto & p : tokenizeString<Strings>(s, ":"))
            ss.push_back("@" + p);
        builders = concatStringsSep(" ", ss);
    }

#if defined(__linux__) && defined(SANDBOX_SHELL)
    sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
#endif

    allowedImpureHostPrefixes = tokenizeString<StringSet>(DEFAULT_ALLOWED_IMPURE_PREFIXES);
}

void Settings::loadConfFile()
{
    applyConfigFile(nixConfDir + "/nix.conf");

    /* We only want to send overrides to the daemon, i.e. stuff from
       ~/.nix/nix.conf or the command line. */
    resetOverriden();

    applyConfigFile(getConfigDir() + "/nix/nix.conf");
}

void Settings::set(const string & name, const string & value)
{
    Config::set(name, value);
}

unsigned int Settings::getDefaultCores()
{
    return std::max(1U, std::thread::hardware_concurrency());
}

const string nixVersion = PACKAGE_VERSION;

template<> void BaseSetting<SandboxMode>::set(const std::string & str)
{
    if (str == "true") value = smEnabled;
    else if (str == "relaxed") value = smRelaxed;
    else if (str == "false") value = smDisabled;
    else throw UsageError("option '%s' has invalid value '%s'", name, str);
}

template<> std::string BaseSetting<SandboxMode>::to_string()
{
    if (value == smEnabled) return "true";
    else if (value == smRelaxed) return "relaxed";
    else if (value == smDisabled) return "false";
    else abort();
}

template<> void BaseSetting<SandboxMode>::toJSON(JSONPlaceholder & out)
{
    AbstractSetting::toJSON(out);
}

template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::string & category)
{
    args.mkFlag()
        .longName(name)
        .description("Enable sandboxing.")
        .handler([=](std::vector<std::string> ss) { override(smEnabled); })
        .category(category);
    args.mkFlag()
        .longName("no-" + name)
        .description("Disable sandboxing.")
        .handler([=](std::vector<std::string> ss) { override(smDisabled); })
        .category(category);
    args.mkFlag()
        .longName("relaxed-" + name)
        .description("Enable sandboxing, but allow builds to disable it.")
        .handler([=](std::vector<std::string> ss) { override(smRelaxed); })
        .category(category);
}

void MaxBuildJobsSetting::set(const std::string & str)
{
    if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency());
    else if (!string2Int(str, value))
        throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
}

void initPlugins()
{
    for (const auto & pluginFile : settings.pluginFiles.get()) {
        Paths pluginFiles;
        try {
            auto ents = readDirectory(pluginFile);
            for (const auto & ent : ents)
                pluginFiles.emplace_back(pluginFile + "/" + ent.name);
        } catch (SysError & e) {
            if (e.errNo != ENOTDIR)
                throw;
            pluginFiles.emplace_back(pluginFile);
        }
        for (const auto & file : pluginFiles) {
            /* handle is purposefully leaked as there may be state in the
               DSO needed by the action of the plugin. */
            void *handle =
                dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
            if (!handle)
                throw Error("could not dynamically open plugin file '%s%': %s%", file, dlerror());
        }
    }
    /* We handle settings registrations here, since plugins can add settings */
    if (RegisterSetting::settingRegistrations) {
        for (auto & registration : *RegisterSetting::settingRegistrations)
            settings.addSetting(registration);
        delete RegisterSetting::settingRegistrations;
    }
    settings.handleUnknownSettings();
}

RegisterSetting::SettingRegistrations * RegisterSetting::settingRegistrations;

RegisterSetting::RegisterSetting(AbstractSetting * s)
{
    if (!settingRegistrations)
        settingRegistrations = new SettingRegistrations;
    settingRegistrations->emplace_back(s);
}

}
<commit_msg>initPlugins: Fix dlopen error message.<commit_after>#include "globals.hh"
#include "util.hh"
#include "archive.hh"
#include "args.hh"

#include <algorithm>
#include <map>
#include <thread>
#include <dlfcn.h>

namespace nix {

/* The default location of the daemon socket, relative to nixStateDir.
   The socket is in a directory to allow you to control access to the
   Nix daemon by setting the mode/ownership of the directory
   appropriately.  (This wouldn't work on the socket itself since it
   must be deleted and recreated on startup.) */
#define DEFAULT_SOCKET_PATH "/daemon-socket/socket"

/* chroot-like behavior from Apple's sandbox */
#if __APPLE__
    #define DEFAULT_ALLOWED_IMPURE_PREFIXES "/System/Library /usr/lib /dev /bin/sh"
#else
    #define DEFAULT_ALLOWED_IMPURE_PREFIXES ""
#endif

Settings settings;

Settings::Settings()
    : Config({})
    , nixPrefix(NIX_PREFIX)
    , nixStore(canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR))))
    , nixDataDir(canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR)))
    , nixLogDir(canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR)))
    , nixStateDir(canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR)))
    , nixConfDir(canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR)))
    , nixLibexecDir(canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR)))
    , nixBinDir(canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR)))
    , nixManDir(canonPath(NIX_MAN_DIR))
    , nixDaemonSocketFile(canonPath(nixStateDir + DEFAULT_SOCKET_PATH))
{
    buildUsersGroup = getuid() == 0 ? "nixbld" : "";
    lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1";

    caFile = getEnv("NIX_SSL_CERT_FILE", getEnv("SSL_CERT_FILE", ""));
    if (caFile == "") {
        for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
            if (pathExists(fn)) {
                caFile = fn;
                break;
            }
    }

    /* Backwards compatibility. */
    auto s = getEnv("NIX_REMOTE_SYSTEMS");
    if (s != "") {
        Strings ss;
        for (auto & p : tokenizeString<Strings>(s, ":"))
            ss.push_back("@" + p);
        builders = concatStringsSep(" ", ss);
    }

#if defined(__linux__) && defined(SANDBOX_SHELL)
    sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
#endif

    allowedImpureHostPrefixes = tokenizeString<StringSet>(DEFAULT_ALLOWED_IMPURE_PREFIXES);
}

void Settings::loadConfFile()
{
    applyConfigFile(nixConfDir + "/nix.conf");

    /* We only want to send overrides to the daemon, i.e. stuff from
       ~/.nix/nix.conf or the command line. */
    resetOverriden();

    applyConfigFile(getConfigDir() + "/nix/nix.conf");
}

void Settings::set(const string & name, const string & value)
{
    Config::set(name, value);
}

unsigned int Settings::getDefaultCores()
{
    return std::max(1U, std::thread::hardware_concurrency());
}

const string nixVersion = PACKAGE_VERSION;

template<> void BaseSetting<SandboxMode>::set(const std::string & str)
{
    if (str == "true") value = smEnabled;
    else if (str == "relaxed") value = smRelaxed;
    else if (str == "false") value = smDisabled;
    else throw UsageError("option '%s' has invalid value '%s'", name, str);
}

template<> std::string BaseSetting<SandboxMode>::to_string()
{
    if (value == smEnabled) return "true";
    else if (value == smRelaxed) return "relaxed";
    else if (value == smDisabled) return "false";
    else abort();
}

template<> void BaseSetting<SandboxMode>::toJSON(JSONPlaceholder & out)
{
    AbstractSetting::toJSON(out);
}

template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::string & category)
{
    args.mkFlag()
        .longName(name)
        .description("Enable sandboxing.")
        .handler([=](std::vector<std::string> ss) { override(smEnabled); })
        .category(category);
    args.mkFlag()
        .longName("no-" + name)
        .description("Disable sandboxing.")
        .handler([=](std::vector<std::string> ss) { override(smDisabled); })
        .category(category);
    args.mkFlag()
        .longName("relaxed-" + name)
        .description("Enable sandboxing, but allow builds to disable it.")
        .handler([=](std::vector<std::string> ss) { override(smRelaxed); })
        .category(category);
}

void MaxBuildJobsSetting::set(const std::string & str)
{
    if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency());
    else if (!string2Int(str, value))
        throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
}

void initPlugins()
{
    for (const auto & pluginFile : settings.pluginFiles.get()) {
        Paths pluginFiles;
        try {
            auto ents = readDirectory(pluginFile);
            for (const auto & ent : ents)
                pluginFiles.emplace_back(pluginFile + "/" + ent.name);
        } catch (SysError & e) {
            if (e.errNo != ENOTDIR)
                throw;
            pluginFiles.emplace_back(pluginFile);
        }
        for (const auto & file : pluginFiles) {
            /* handle is purposefully leaked as there may be state in the
               DSO needed by the action of the plugin. */
            void *handle =
                dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
            if (!handle)
                throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
        }
    }
    /* We handle settings registrations here, since plugins can add settings */
    if (RegisterSetting::settingRegistrations) {
        for (auto & registration : *RegisterSetting::settingRegistrations)
            settings.addSetting(registration);
        delete RegisterSetting::settingRegistrations;
    }
    settings.handleUnknownSettings();
}

RegisterSetting::SettingRegistrations * RegisterSetting::settingRegistrations;

RegisterSetting::RegisterSetting(AbstractSetting * s)
{
    if (!settingRegistrations)
        settingRegistrations = new SettingRegistrations;
    settingRegistrations->emplace_back(s);
}

}
<|endoftext|>


<commit_before>#include "../BackTrace.h"
#include "../Exception.h"

#include <errno.h>
#include <execinfo.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>

#include <iterator>

using namespace std;
using namespace ExceptionLib;

namespace {
	static bool executable_found = false;
	static string executable;

	void segfaulthandler(int signum)
	{
		signal(SIGSEGV, SIG_DFL);
		signal(SIGBUS, SIG_DFL);
		signal(SIGILL, SIG_DFL);
		signal(SIGFPE, SIG_DFL);

		switch(signum) {
			case SIGSEGV:
				throw SegmentationFault();
				break;
			case SIGBUS:
				throw SegmentationFault();
				break;
			case SIGFPE:
				throw FloatingPointException();
				break;
			case SIGILL:
				throw IllegalInstruction();
				break;
			default:
				throw Exception("Caught unexpected signal");
				break;
		}

		signal(SIGSEGV, segfaulthandler);
		signal(SIGBUS, segfaulthandler);
		signal(SIGILL, segfaulthandler);
		signal(SIGFPE, segfaulthandler);
	}

	char * opt_getcwd (char * stack_buf, int stack_size)
	{
		if (getcwd (stack_buf, stack_size) == stack_buf)
			return stack_buf;
		size_t size = stack_size;

		while (1)
		{
			char *buffer = (char *) malloc (size);
			if (getcwd (buffer, size) == buffer)
				return buffer;
			free (buffer);
			if (errno != ERANGE)
				return 0;
			size *= 2;
		}
	}

	class Finder {
	private:
		vector<string> pathv;
	public:
		Finder() {
			string path(getenv("PATH"));
			const int size = path.size();
			for (int i = 0; i < size; ++i) {
				if (path[i] == ':') path[i] = ' ';
			}
			stringstream splitter;
			splitter << path;

			istream_iterator<string> it(splitter);
			istream_iterator<string> _end;
			for (; it != _end; ++it) {
				pathv.push_back(*it + "/");
			}
		}
		inline bool check_exe_file(const string& path) {
			struct stat statbuf;
			if(!stat(path.c_str(), &statbuf)) {
				if ((statbuf.st_mode & S_IXUSR) || (statbuf.st_mode & S_IXGRP) || (statbuf.st_mode & S_IXOTH)) {
					return true;
				}
			}
			return false;
		}
		bool whereis(const string& file, string& resolved) {

			if (file.size() > 0 && file[0] == '/') {
				if (check_exe_file(file)) {
					resolved = file;
					return true;
				}
				return false;
			}

			char stack_buf[100];
			char * cwd = opt_getcwd(stack_buf, 100);
			string local_path(cwd);
			if (cwd != stack_buf)
				free(cwd);
			local_path += '/';
			local_path += file;
			if (check_exe_file(local_path)) {
				resolved = local_path;
				return true;
			}

			vector<string>::iterator it = pathv.begin();
			vector<string>::iterator end = pathv.end();

			for (; it != end; ++it) {
				string name(*it + file);
				if (check_exe_file(name)) {
					resolved = name;
					return true;
				}
			}

			return false;
		}
	};

	class StackTraceLinux: public ::Backtrace::StackTrace {
	private:
		void * bt[50];
		ssize_t size;
	public:
		StackTraceLinux() {
			size = backtrace(bt, sizeof(bt)/sizeof(void*));
		}

		string getTrace() const {

			stringstream stack;

			if (executable_found) {

				stringstream command;
				command << "addr2line -Cife ";
				command << executable;

				for (int i = 0; i < size; i++) {
				  command << " " << bt[i];
				}
				command << " 2>/dev/null";

				FILE *p = popen(command.str().c_str(), "r");

				if (p) {
				  // workaround
				  int c = fgetc(p);
				  if (c != EOF) ungetc(c, p);

				  if (!feof(p)) {
					size_t lsize = 256;
					char * line = (char*) malloc(lsize);
					ssize_t read;

					bool func_name = true;

					int i = 0;
					while ((read = getline(&line, &lsize, p)) > 0) {
						if (func_name) {
							line[read-1] = ' ';
							func_name = false;
							stack << bt[i++] << ": " << line << "at ";
						} else {
							func_name = true;
							stack << line;
						}
					}

					fclose(p);
					free(line);
				  }
				}
			} else {
				char **strings = backtrace_symbols (bt, size);
				for (int i = 0; i < size; i++)
					stack << strings[i] << endl;

				free (strings);

			}
			return stack.str();
		}
	};

}

namespace Backtrace {
	void initialize(const char* argv0)
	{
		Finder finder;
		string rel_path(argv0);
		executable_found = finder.whereis(rel_path, executable);

		signal(SIGSEGV, segfaulthandler);
		signal(SIGBUS, segfaulthandler);
		signal(SIGILL, segfaulthandler);
		signal(SIGFPE, segfaulthandler);
	}

	StackTrace* trace()
	{
		return new StackTraceLinux();
	}

	bool backtraceSupported()
	{
		return true;
	}
}
<commit_msg>Mudanca no formato do stacktrace no linux<commit_after>#include "../BackTrace.h"
#include "../Exception.h"

#include <errno.h>
#include <execinfo.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <vector>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>

#include <iterator>

using namespace std;
using namespace ExceptionLib;

namespace {
	static bool executable_found = false;
	static string executable;

	void segfaulthandler(int signum)
	{
		signal(SIGSEGV, SIG_DFL);
		signal(SIGBUS, SIG_DFL);
		signal(SIGILL, SIG_DFL);
		signal(SIGFPE, SIG_DFL);

		switch(signum) {
			case SIGSEGV:
				throw SegmentationFault();
				break;
			case SIGBUS:
				throw SegmentationFault();
				break;
			case SIGFPE:
				throw FloatingPointException();
				break;
			case SIGILL:
				throw IllegalInstruction();
				break;
			default:
				throw Exception("Caught unexpected signal");
				break;
		}

		signal(SIGSEGV, segfaulthandler);
		signal(SIGBUS, segfaulthandler);
		signal(SIGILL, segfaulthandler);
		signal(SIGFPE, segfaulthandler);
	}

	char * opt_getcwd (char * stack_buf, int stack_size)
	{
		if (getcwd (stack_buf, stack_size) == stack_buf)
			return stack_buf;
		size_t size = stack_size;

		while (1)
		{
			char *buffer = (char *) malloc (size);
			if (getcwd (buffer, size) == buffer)
				return buffer;
			free (buffer);
			if (errno != ERANGE)
				return 0;
			size *= 2;
		}
	}

	class Finder {
	private:
		vector<string> pathv;
	public:
		Finder() {
			string path(getenv("PATH"));
			const int size = path.size();
			for (int i = 0; i < size; ++i) {
				if (path[i] == ':') path[i] = ' ';
			}
			stringstream splitter;
			splitter << path;

			istream_iterator<string> it(splitter);
			istream_iterator<string> _end;
			for (; it != _end; ++it) {
				pathv.push_back(*it + "/");
			}
		}
		inline bool check_exe_file(const string& path) {
			struct stat statbuf;
			if(!stat(path.c_str(), &statbuf)) {
				if ((statbuf.st_mode & S_IXUSR) || (statbuf.st_mode & S_IXGRP) || (statbuf.st_mode & S_IXOTH)) {
					return true;
				}
			}
			return false;
		}
		bool whereis(const string& file, string& resolved) {

			if (file.size() > 0 && file[0] == '/') {
				if (check_exe_file(file)) {
					resolved = file;
					return true;
				}
				return false;
			}

			char stack_buf[100];
			char * cwd = opt_getcwd(stack_buf, 100);
			string local_path(cwd);
			if (cwd != stack_buf)
				free(cwd);
			local_path += '/';
			local_path += file;
			if (check_exe_file(local_path)) {
				resolved = local_path;
				return true;
			}

			vector<string>::iterator it = pathv.begin();
			vector<string>::iterator end = pathv.end();

			for (; it != end; ++it) {
				string name(*it + file);
				if (check_exe_file(name)) {
					resolved = name;
					return true;
				}
			}

			return false;
		}
	};

	class StackTraceLinux: public ::Backtrace::StackTrace {
	private:
		void * bt[50];
		ssize_t size;
	public:
		StackTraceLinux() {
			size = backtrace(bt, sizeof(bt)/sizeof(void*));
		}

		string getTrace() const {

			stringstream stack;

			if (executable_found) {

				stringstream command;
				command << "addr2line -Cife ";
				command << executable;

				for (int i = 0; i < size; i++) {
				  command << " " << bt[i];
				}
				command << " 2>/dev/null";

				FILE *p = popen(command.str().c_str(), "r");

				if (p) {
				  // workaround
				  int c = fgetc(p);
				  if (c != EOF) ungetc(c, p);

				  if (!feof(p)) {
					size_t lsize = 256;
					char * line = (char*) malloc(lsize);
					ssize_t read;

					bool func_name = true;

					int i = 0;
					while ((read = getline(&line, &lsize, p)) > 0) {
						if (func_name) {
							line[read-1] = ' ';
							func_name = false;
							stack << bt[i++] << ":\t" << line << "\tat ";
						} else {
							func_name = true;
							stack << line;
						}
					}

					fclose(p);
					free(line);
				  }
				}
			} else {
				char **strings = backtrace_symbols (bt, size);
				for (int i = 0; i < size; i++)
					stack << strings[i] << endl;

				free (strings);

			}
			return stack.str();
		}
	};

}

namespace Backtrace {
	void initialize(const char* argv0)
	{
		Finder finder;
		string rel_path(argv0);
		executable_found = finder.whereis(rel_path, executable);

		signal(SIGSEGV, segfaulthandler);
		signal(SIGBUS, segfaulthandler);
		signal(SIGILL, segfaulthandler);
		signal(SIGFPE, segfaulthandler);
	}

	StackTrace* trace()
	{
		return new StackTraceLinux();
	}

	bool backtraceSupported()
	{
		return true;
	}
}
<|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 "config.h"
#include "core/frame/EventHandlerRegistry.h"

#include "core/events/ThreadLocalEventNames.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/page/Chrome.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"

namespace blink {

EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost)
    : m_frameHost(frameHost)
{
}

EventHandlerRegistry::~EventHandlerRegistry()
{
    checkConsistency();
}

bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result)
{
    if (eventType == EventTypeNames::scroll) {
        *result = ScrollEvent;
    } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) {
        *result = WheelEvent;
    } else if (isTouchEventType(eventType)) {
        *result = TouchEvent;
#if ENABLE(ASSERT)
    } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
        *result = EventsForTesting;
#endif
    } else {
        return false;
    }
    return true;
}

const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
{
    checkConsistency();
    return &m_targets[handlerClass];
}

bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
{
    checkConsistency();
    return m_targets[handlerClass].size();
}

bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
{
    EventTargetSet* targets = &m_targets[handlerClass];
    if (op == Add) {
        if (!targets->add(target).isNewEntry) {
            // Just incremented refcount, no real change.
            return false;
        }
    } else {
        ASSERT(op == Remove || op == RemoveAll);
        ASSERT(op == RemoveAll || targets->contains(target));

        if (op == RemoveAll) {
            if (!targets->contains(target))
                return false;
            targets->removeAll(target);
        } else {
            if (!targets->remove(target)) {
                // Just decremented refcount, no real update.
                return false;
            }
        }
    }
    return true;
}

void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
{
    bool hadHandlers = m_targets[handlerClass].size();
    bool targetSetChanged = updateEventHandlerTargets(op, handlerClass, target);
    bool hasHandlers = m_targets[handlerClass].size();

    if (hadHandlers != hasHandlers)
        notifyHasHandlersChanged(handlerClass, hasHandlers);

    if (targetSetChanged)
        notifyDidAddOrRemoveEventHandlerTarget(handlerClass);
}

void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
{
    EventHandlerClass handlerClass;
    if (!eventTypeToClass(eventType, &handlerClass))
        return;
    updateEventHandlerInternal(op, handlerClass, target);
}

void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType)
{
    updateEventHandlerOfType(Add, eventType, &target);
}

void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType)
{
    updateEventHandlerOfType(Remove, eventType, &target);
}

void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass)
{
    updateEventHandlerInternal(Add, handlerClass, &target);
}

void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass)
{
    updateEventHandlerInternal(Remove, handlerClass, &target);
}

void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target)
{
    if (!target.hasEventListeners())
        return;

    Vector<AtomicString> eventTypes = target.eventTypes();
    for (size_t i = 0; i < eventTypes.size(); ++i) {
        EventHandlerClass handlerClass;
        if (!eventTypeToClass(eventTypes[i], &handlerClass))
            continue;
        for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count)
            didAddEventHandler(target, handlerClass);
    }
}

void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target)
{
    didRemoveAllEventHandlers(target);
}

void EventHandlerRegistry::didMoveBetweenFrameHosts(EventTarget& target, FrameHost* oldFrameHost, FrameHost* newFrameHost)
{
    ASSERT(newFrameHost != oldFrameHost);
    for (size_t i = 0; i < EventHandlerClassCount; ++i) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
        const EventTargetSet* targets = &oldFrameHost->eventHandlerRegistry().m_targets[handlerClass];
        for (unsigned count = targets->count(&target); count > 0; --count)
            newFrameHost->eventHandlerRegistry().didAddEventHandler(target, handlerClass);
        oldFrameHost->eventHandlerRegistry().didRemoveAllEventHandlers(target);
    }
}

void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
{
    for (size_t i = 0; i < EventHandlerClassCount; ++i) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
        updateEventHandlerInternal(RemoveAll, handlerClass, &target);
    }
}

void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
{
    switch (handlerClass) {
    case TouchEvent:
        m_frameHost.chrome().client().needTouchEvents(hasActiveHandlers);
        break;
#if ENABLE(ASSERT)
    case EventsForTesting:
        break;
#endif
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}

void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerClass handlerClass)
{
    ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator();
    if (scrollingCoordinator && handlerClass == TouchEvent)
        scrollingCoordinator->touchEventTargetRectsDidChange();
}

void EventHandlerRegistry::documentDetached(Document& document)
{
    // Remove all event targets under the detached document.
    for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex);
        Vector<EventTarget*> targetsToRemove;
        const EventTargetSet* targets = &m_targets[handlerClass];
        for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
            if (Node* node = iter->key->toNode()) {
                if (node->document() == &document) {
                    targetsToRemove.append(iter->key);
                    break;
                }
            } else if (iter->key->toDOMWindow()) {
                // DOMWindows may outlive their documents, so we shouldn't remove their handlers
                // here.
            } else {
                ASSERT_NOT_REACHED();
            }
        }
        for (size_t i = 0; i < targetsToRemove.size(); ++i)
            updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
    }
}

void EventHandlerRegistry::checkConsistency() const
{
#if ENABLE(ASSERT)
    for (size_t i = 0; i < EventHandlerClassCount; ++i) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
        const EventTargetSet* targets = &m_targets[handlerClass];
        for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
            if (Node* node = iter->key->toNode()) {
                // See the comment for |documentDetached| if either of these assertions fails.
                ASSERT(node->document().frameHost());
                ASSERT(node->document().frameHost() == &m_frameHost);
            } else if (LocalDOMWindow* window = iter->key->toDOMWindow()) {
                // If any of these assertions fail, LocalDOMWindow failed to unregister its handlers
                // properly.
                ASSERT(window->frame());
                ASSERT(window->frame()->host());
                ASSERT(window->frame()->host() == &m_frameHost);
            }
        }
    }
#endif // ENABLE(ASSERT)
}

} // namespace blink
<commit_msg>Don't hit ASSERT_NOT_REACHED() when adding a scroll listener.<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 "config.h"
#include "core/frame/EventHandlerRegistry.h"

#include "core/events/ThreadLocalEventNames.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/page/Chrome.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"

namespace blink {

EventHandlerRegistry::EventHandlerRegistry(FrameHost& frameHost)
    : m_frameHost(frameHost)
{
}

EventHandlerRegistry::~EventHandlerRegistry()
{
    checkConsistency();
}

bool EventHandlerRegistry::eventTypeToClass(const AtomicString& eventType, EventHandlerClass* result)
{
    if (eventType == EventTypeNames::scroll) {
        *result = ScrollEvent;
    } else if (eventType == EventTypeNames::wheel || eventType == EventTypeNames::mousewheel) {
        *result = WheelEvent;
    } else if (isTouchEventType(eventType)) {
        *result = TouchEvent;
#if ENABLE(ASSERT)
    } else if (eventType == EventTypeNames::load || eventType == EventTypeNames::mousemove || eventType == EventTypeNames::touchstart) {
        *result = EventsForTesting;
#endif
    } else {
        return false;
    }
    return true;
}

const EventTargetSet* EventHandlerRegistry::eventHandlerTargets(EventHandlerClass handlerClass) const
{
    checkConsistency();
    return &m_targets[handlerClass];
}

bool EventHandlerRegistry::hasEventHandlers(EventHandlerClass handlerClass) const
{
    checkConsistency();
    return m_targets[handlerClass].size();
}

bool EventHandlerRegistry::updateEventHandlerTargets(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
{
    EventTargetSet* targets = &m_targets[handlerClass];
    if (op == Add) {
        if (!targets->add(target).isNewEntry) {
            // Just incremented refcount, no real change.
            return false;
        }
    } else {
        ASSERT(op == Remove || op == RemoveAll);
        ASSERT(op == RemoveAll || targets->contains(target));

        if (op == RemoveAll) {
            if (!targets->contains(target))
                return false;
            targets->removeAll(target);
        } else {
            if (!targets->remove(target)) {
                // Just decremented refcount, no real update.
                return false;
            }
        }
    }
    return true;
}

void EventHandlerRegistry::updateEventHandlerInternal(ChangeOperation op, EventHandlerClass handlerClass, EventTarget* target)
{
    bool hadHandlers = m_targets[handlerClass].size();
    bool targetSetChanged = updateEventHandlerTargets(op, handlerClass, target);
    bool hasHandlers = m_targets[handlerClass].size();

    if (hadHandlers != hasHandlers)
        notifyHasHandlersChanged(handlerClass, hasHandlers);

    if (targetSetChanged)
        notifyDidAddOrRemoveEventHandlerTarget(handlerClass);
}

void EventHandlerRegistry::updateEventHandlerOfType(ChangeOperation op, const AtomicString& eventType, EventTarget* target)
{
    EventHandlerClass handlerClass;
    if (!eventTypeToClass(eventType, &handlerClass))
        return;
    updateEventHandlerInternal(op, handlerClass, target);
}

void EventHandlerRegistry::didAddEventHandler(EventTarget& target, const AtomicString& eventType)
{
    updateEventHandlerOfType(Add, eventType, &target);
}

void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, const AtomicString& eventType)
{
    updateEventHandlerOfType(Remove, eventType, &target);
}

void EventHandlerRegistry::didAddEventHandler(EventTarget& target, EventHandlerClass handlerClass)
{
    updateEventHandlerInternal(Add, handlerClass, &target);
}

void EventHandlerRegistry::didRemoveEventHandler(EventTarget& target, EventHandlerClass handlerClass)
{
    updateEventHandlerInternal(Remove, handlerClass, &target);
}

void EventHandlerRegistry::didMoveIntoFrameHost(EventTarget& target)
{
    if (!target.hasEventListeners())
        return;

    Vector<AtomicString> eventTypes = target.eventTypes();
    for (size_t i = 0; i < eventTypes.size(); ++i) {
        EventHandlerClass handlerClass;
        if (!eventTypeToClass(eventTypes[i], &handlerClass))
            continue;
        for (unsigned count = target.getEventListeners(eventTypes[i]).size(); count > 0; --count)
            didAddEventHandler(target, handlerClass);
    }
}

void EventHandlerRegistry::didMoveOutOfFrameHost(EventTarget& target)
{
    didRemoveAllEventHandlers(target);
}

void EventHandlerRegistry::didMoveBetweenFrameHosts(EventTarget& target, FrameHost* oldFrameHost, FrameHost* newFrameHost)
{
    ASSERT(newFrameHost != oldFrameHost);
    for (size_t i = 0; i < EventHandlerClassCount; ++i) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
        const EventTargetSet* targets = &oldFrameHost->eventHandlerRegistry().m_targets[handlerClass];
        for (unsigned count = targets->count(&target); count > 0; --count)
            newFrameHost->eventHandlerRegistry().didAddEventHandler(target, handlerClass);
        oldFrameHost->eventHandlerRegistry().didRemoveAllEventHandlers(target);
    }
}

void EventHandlerRegistry::didRemoveAllEventHandlers(EventTarget& target)
{
    for (size_t i = 0; i < EventHandlerClassCount; ++i) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
        updateEventHandlerInternal(RemoveAll, handlerClass, &target);
    }
}

void EventHandlerRegistry::notifyHasHandlersChanged(EventHandlerClass handlerClass, bool hasActiveHandlers)
{
    switch (handlerClass) {
    // FIXME(sky): Remove these enums from the EventHandlerClass entirely.
    case ScrollEvent:
    case WheelEvent:
        break;
    case TouchEvent:
        m_frameHost.chrome().client().needTouchEvents(hasActiveHandlers);
        break;
#if ENABLE(ASSERT)
    case EventsForTesting:
        break;
#endif
    default:
        ASSERT_NOT_REACHED();
        break;
    }
}

void EventHandlerRegistry::notifyDidAddOrRemoveEventHandlerTarget(EventHandlerClass handlerClass)
{
    ScrollingCoordinator* scrollingCoordinator = m_frameHost.page().scrollingCoordinator();
    if (scrollingCoordinator && handlerClass == TouchEvent)
        scrollingCoordinator->touchEventTargetRectsDidChange();
}

void EventHandlerRegistry::documentDetached(Document& document)
{
    // Remove all event targets under the detached document.
    for (size_t handlerClassIndex = 0; handlerClassIndex < EventHandlerClassCount; ++handlerClassIndex) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(handlerClassIndex);
        Vector<EventTarget*> targetsToRemove;
        const EventTargetSet* targets = &m_targets[handlerClass];
        for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
            if (Node* node = iter->key->toNode()) {
                if (node->document() == &document) {
                    targetsToRemove.append(iter->key);
                    break;
                }
            } else if (iter->key->toDOMWindow()) {
                // DOMWindows may outlive their documents, so we shouldn't remove their handlers
                // here.
            } else {
                ASSERT_NOT_REACHED();
            }
        }
        for (size_t i = 0; i < targetsToRemove.size(); ++i)
            updateEventHandlerInternal(RemoveAll, handlerClass, targetsToRemove[i]);
    }
}

void EventHandlerRegistry::checkConsistency() const
{
#if ENABLE(ASSERT)
    for (size_t i = 0; i < EventHandlerClassCount; ++i) {
        EventHandlerClass handlerClass = static_cast<EventHandlerClass>(i);
        const EventTargetSet* targets = &m_targets[handlerClass];
        for (EventTargetSet::const_iterator iter = targets->begin(); iter != targets->end(); ++iter) {
            if (Node* node = iter->key->toNode()) {
                // See the comment for |documentDetached| if either of these assertions fails.
                ASSERT(node->document().frameHost());
                ASSERT(node->document().frameHost() == &m_frameHost);
            } else if (LocalDOMWindow* window = iter->key->toDOMWindow()) {
                // If any of these assertions fail, LocalDOMWindow failed to unregister its handlers
                // properly.
                ASSERT(window->frame());
                ASSERT(window->frame()->host());
                ASSERT(window->frame()->host() == &m_frameHost);
            }
        }
    }
#endif // ENABLE(ASSERT)
}

} // namespace blink
<|endoftext|>


<commit_before>//
//  BndNaca4DigitSymm.h
//  NSolver
//
//  Created by 乔磊 on 15/9/14.
//  Copyright (c) 2015年 乔磊. All rights reserved.
//

#include <NSolver/BoundaryManifold/BndNaca4DigitSymm.h>

namespace NSFEMSolver
{
  using namespace dealii;

  BndNaca4DigitSymm::BndNaca4DigitSymm (const unsigned int /*number*/,
                                        const double chord_length_in)
    :
    // max_thickness (static_cast<double> (number%100)/100.0),
    max_thickness (0.12),
    chord_length (chord_length_in)
  {}

  BndNaca4DigitSymm::~BndNaca4DigitSymm()
  {}

  Point<2>
  BndNaca4DigitSymm::get_new_point_on_line (const typename Triangulation<2,2>::line_iterator &line) const
  {

#ifdef DEBUG_BndNaca4DigitSymm
    std::cerr << "\n\n\n";
    static std::ofstream new_points_out ("new_points_debug.txt");
    static std::ofstream old_points_out ("old_points_debug.txt");
    static std::ofstream solve_out ("solve_test.txt");

    new_points_out << std::scientific;
    new_points_out.precision (8);
    old_points_out << std::scientific;
    old_points_out.precision (8);
    solve_out << std::scientific;
    solve_out.precision (8);

    old_points_out << line->vertex (0)[0] << "\t" << line->vertex (0)[1] << std::endl;
    old_points_out << line->vertex (1)[0] << "\t" << line->vertex (1)[1] << std::endl;
#endif

    const Point<2> &p1 = line->vertex (0);
    const Point<2> &p2 = line->vertex (1);
    const Point<2> candidate = (p1 + p2) / 2.0;

#ifdef DEBUG_BndNaca4DigitSymm
    const unsigned int bc_id = line->boundary_id();
    std::cerr << bc_id << ": "
              << line->vertex (0) << "; "
              << line->vertex (1) << std::endl;
    std::cerr << "candidate : " << candidate << std::endl;
#endif
    if (line->boundary_id() == 0)
      {
        return (candidate);
      }

    double s1;
    double s2;
    // Curve length from LE to the two points
    if (std::abs (p1[1]) < 1e-26)
      {
        s1 = fitted_curve_length (p1[0]) * (1.0 - 2.0*std::signbit (p2[1]));
      }
    else
      {
        s1 = fitted_curve_length (p1[0]) * (1.0 - 2.0*std::signbit (p1[1]));
      }
    if (std::abs (p2[1]) < 1e-26)
      {
        s2 = fitted_curve_length (p2[0]) * (1.0 - 2.0*std::signbit (p1[1]));
      }
    else
      {
        s2 = fitted_curve_length (p2[0]) * (1.0 - 2.0*std::signbit (p2[1]));
      }
    //std::abs(p1[1]) and std::abs(p2[1]) should not approximate to zero at same time,
    // which means p1 and p2 are trailing and leading edge.

    // Solve for position with medium curve length with Newton method
    const double s_mid_abs = std::abs (0.5* (s1+s2));
    const double s_mid_sign = 1.0 - 2.0*std::signbit (s1+s2);

    double sol = std::max (candidate[0], 1.0e-16);

    //Newton iteration
#ifdef DEBUG_BndNaca4DigitSymm
    std::cerr << "\n solve mid curve" << std::endl;
#endif
    for (unsigned int n_iter = 0; n_iter < 100; ++n_iter)
      {
        Fad_db x_ad = sol;
        x_ad.diff (0,1);

        Fad_db res_ad = fitted_curve_length<Fad_db> (x_ad) - s_mid_abs;
#ifdef DEBUG_BndNaca4DigitSymm
        std::cerr << res_ad.val() << ",   " << sol << std::endl;
#endif
        if (std::abs (res_ad.val()) < 1.0e-10)
          {
            break;
          }
        sol -= res_ad.val()/res_ad.fastAccessDx (0);
        sol = std::max (sol, 1.0e-16);
#ifdef DEBUG_BndNaca4DigitSymm
        std::cerr << sol << std::endl;
#endif
      }
    const double y_foil = thickness (sol) * s_mid_sign;
#ifdef DEBUG_BndNaca4DigitSymm
    solve_out << candidate[0] << "  " << sol << "  " << candidate[0] - sol << "  "
              << candidate[1] << "  " << y_foil << "  " << candidate[1] - y_foil << "  "
              << std::endl;
#endif
    return (Point<2> (sol, y_foil));
  }

  Tensor<1,2>
  BndNaca4DigitSymm::normal_vector (const typename Triangulation<2,2>::face_iterator &face,
                                    const Point<2> &p) const
  {
    const double x = std::max (p[0], 1e-16);
    Assert (p[0] > -1e-6, ExcMessage ("Point not on foil"));
    Assert (p[0] <  1.0 + 1e-6, ExcMessage ("Point not on foil"));

    Fad_db x_ad = x;
    x_ad.diff (0,1);

    Fad_db y = thickness<Fad_db> (x_ad);
    Assert (std::abs (std::abs (p[1]) - y) < 1e-6, ExcMessage ("Point not on foil"));
    Tensor<1,2> return_value;
    return_value[0] = y.fastAccessDx (0);
    if (p[1] > 0.0)
      {
        return_value[1] = -1.0;
      }
    else if (p[1] < 0.0)
      {
        return_value[1] = 1.0;
      }
    else //if (p[1]  == 0.0)
      {
        bool norm_setted = false;
        for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_face; ++v)
          {
            if (face->vertex (v)[1] != 0.0)
              {
                if (face->vertex (v)[1] > 0.0)
                  {
                    return_value[1] = -1.0;
                  }
                else // if (face->vertex (v)[1]] < 0.0)
                  {
                    return_value[1] = 1.0;
                  }
                norm_setted = true;
                break;
              }
          }
        Assert (norm_setted, ExcMessage ("All vertices on face have zero Y"));
      }
    return (return_value/return_value.norm());
  }

  void
  BndNaca4DigitSymm::get_normals_at_vertices (const typename Triangulation<2,2>::face_iterator &face,
                                              typename Boundary<2,2>::FaceVertexNormals &face_vertex_normals) const
  {
    for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_face; ++v)
      {
        const Point<2> &p = face->vertex (v);
        // Beware upper_or_lower == 1.0 for lower half of the foil
        // and upper_or_lower == -1.0 for upper half of the foil.
        // Because we want the outer normal vector of the flow field
        // rather than the air foil.
        // This may be a surprise.
        double upper_or_lower = 0.0;
        if (p[1] > 0.0)
          {
            upper_or_lower = -1.0;
          }
        else if (p[1] < 0.0)
          {
            upper_or_lower = 1.0;
          }
        else //if (p[1]  == 0.0)
          {
            // Then another vertex must not have zero Y coordinate
            if (face->vertex (1-v)[1] > 0.0)
              {
                upper_or_lower = -1.0;
              }
            else if (face->vertex (1-v)[1] < 0.0)
              {
                upper_or_lower = 1.0;
              }
          }
        Assert (upper_or_lower != 0.0, ExcMessage ("All vertices on face have zero Y"));

        const double x = std::max (p[0], 1e-16);
        Assert (p[0] > -1e-6, ExcMessage ("Point not on foil"));
        Assert (p[0] <  1.0 + 1e-6, ExcMessage ("Point not on foil"));

        Fad_db x_ad = x;
        x_ad.diff (0,1);

        Fad_db y = thickness<Fad_db> (x_ad);
        Assert (std::abs (std::abs (p[1]) - y) < 1e-6, ExcMessage ("Point not on foil"));
        Tensor<1,2> return_value;
        return_value[0] = y.fastAccessDx (0);
        return_value[1] = upper_or_lower;
        face_vertex_normals[v] = return_value/return_value.norm();
      }
    return;
  }

}
<commit_msg>avoid warning "unused-but-set-variable"<commit_after>//
//  BndNaca4DigitSymm.h
//  NSolver
//
//  Created by 乔磊 on 15/9/14.
//  Copyright (c) 2015年 乔磊. All rights reserved.
//

#include <NSolver/BoundaryManifold/BndNaca4DigitSymm.h>

namespace NSFEMSolver
{
  using namespace dealii;

  BndNaca4DigitSymm::BndNaca4DigitSymm (const unsigned int /*number*/,
                                        const double chord_length_in)
    :
    // max_thickness (static_cast<double> (number%100)/100.0),
    max_thickness (0.12),
    chord_length (chord_length_in)
  {}

  BndNaca4DigitSymm::~BndNaca4DigitSymm()
  {}

  Point<2>
  BndNaca4DigitSymm::get_new_point_on_line (const typename Triangulation<2,2>::line_iterator &line) const
  {

#ifdef DEBUG_BndNaca4DigitSymm
    std::cerr << "\n\n\n";
    static std::ofstream new_points_out ("new_points_debug.txt");
    static std::ofstream old_points_out ("old_points_debug.txt");
    static std::ofstream solve_out ("solve_test.txt");

    new_points_out << std::scientific;
    new_points_out.precision (8);
    old_points_out << std::scientific;
    old_points_out.precision (8);
    solve_out << std::scientific;
    solve_out.precision (8);

    old_points_out << line->vertex (0)[0] << "\t" << line->vertex (0)[1] << std::endl;
    old_points_out << line->vertex (1)[0] << "\t" << line->vertex (1)[1] << std::endl;
#endif

    const Point<2> &p1 = line->vertex (0);
    const Point<2> &p2 = line->vertex (1);
    const Point<2> candidate = (p1 + p2) / 2.0;

#ifdef DEBUG_BndNaca4DigitSymm
    const unsigned int bc_id = line->boundary_id();
    std::cerr << bc_id << ": "
              << line->vertex (0) << "; "
              << line->vertex (1) << std::endl;
    std::cerr << "candidate : " << candidate << std::endl;
#endif
    if (line->boundary_id() == 0)
      {
        return (candidate);
      }

    double s1;
    double s2;
    // Curve length from LE to the two points
    if (std::abs (p1[1]) < 1e-26)
      {
        s1 = fitted_curve_length (p1[0]) * (1.0 - 2.0*std::signbit (p2[1]));
      }
    else
      {
        s1 = fitted_curve_length (p1[0]) * (1.0 - 2.0*std::signbit (p1[1]));
      }
    if (std::abs (p2[1]) < 1e-26)
      {
        s2 = fitted_curve_length (p2[0]) * (1.0 - 2.0*std::signbit (p1[1]));
      }
    else
      {
        s2 = fitted_curve_length (p2[0]) * (1.0 - 2.0*std::signbit (p2[1]));
      }
    //std::abs(p1[1]) and std::abs(p2[1]) should not approximate to zero at same time,
    // which means p1 and p2 are trailing and leading edge.

    // Solve for position with medium curve length with Newton method
    const double s_mid_abs = std::abs (0.5* (s1+s2));
    const double s_mid_sign = 1.0 - 2.0*std::signbit (s1+s2);

    double sol = std::max (candidate[0], 1.0e-16);

    //Newton iteration
#ifdef DEBUG_BndNaca4DigitSymm
    std::cerr << "\n solve mid curve" << std::endl;
#endif
    for (unsigned int n_iter = 0; n_iter < 100; ++n_iter)
      {
        Fad_db x_ad = sol;
        x_ad.diff (0,1);

        Fad_db res_ad = fitted_curve_length<Fad_db> (x_ad) - s_mid_abs;
#ifdef DEBUG_BndNaca4DigitSymm
        std::cerr << res_ad.val() << ",   " << sol << std::endl;
#endif
        if (std::abs (res_ad.val()) < 1.0e-10)
          {
            break;
          }
        sol -= res_ad.val()/res_ad.fastAccessDx (0);
        sol = std::max (sol, 1.0e-16);
#ifdef DEBUG_BndNaca4DigitSymm
        std::cerr << sol << std::endl;
#endif
      }
    const double y_foil = thickness (sol) * s_mid_sign;
#ifdef DEBUG_BndNaca4DigitSymm
    solve_out << candidate[0] << "  " << sol << "  " << candidate[0] - sol << "  "
              << candidate[1] << "  " << y_foil << "  " << candidate[1] - y_foil << "  "
              << std::endl;
#endif
    return (Point<2> (sol, y_foil));
  }

  Tensor<1,2>
  BndNaca4DigitSymm::normal_vector (const typename Triangulation<2,2>::face_iterator &face,
                                    const Point<2> &p) const
  {
    const double x = std::max (p[0], 1e-16);
    Assert (p[0] > -1e-6, ExcMessage ("Point not on foil"));
    Assert (p[0] <  1.0 + 1e-6, ExcMessage ("Point not on foil"));

    Fad_db x_ad = x;
    x_ad.diff (0,1);

    Fad_db y = thickness<Fad_db> (x_ad);
    Assert (std::abs (std::abs (p[1]) - y) < 1e-6, ExcMessage ("Point not on foil"));
    Tensor<1,2> return_value;
    return_value[0] = y.fastAccessDx (0);
    if (p[1] > 0.0)
      {
        return_value[1] = -1.0;
      }
    else if (p[1] < 0.0)
      {
        return_value[1] = 1.0;
      }
    else //if (p[1]  == 0.0)
      {
        bool norm_setted = false;
        for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_face; ++v)
          {
            if (face->vertex (v)[1] != 0.0)
              {
                if (face->vertex (v)[1] > 0.0)
                  {
                    return_value[1] = -1.0;
                  }
                else // if (face->vertex (v)[1]] < 0.0)
                  {
                    return_value[1] = 1.0;
                  }
                norm_setted = true;
                break;
              }
          }
        // avoid warning "unused-but-set-variable"
        (void)norm_setted;
        Assert (norm_setted, ExcMessage ("All vertices on face have zero Y"));
      }
    return (return_value/return_value.norm());
  }

  void
  BndNaca4DigitSymm::get_normals_at_vertices (const typename Triangulation<2,2>::face_iterator &face,
                                              typename Boundary<2,2>::FaceVertexNormals &face_vertex_normals) const
  {
    for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_face; ++v)
      {
        const Point<2> &p = face->vertex (v);
        // Beware upper_or_lower == 1.0 for lower half of the foil
        // and upper_or_lower == -1.0 for upper half of the foil.
        // Because we want the outer normal vector of the flow field
        // rather than the air foil.
        // This may be a surprise.
        double upper_or_lower = 0.0;
        if (p[1] > 0.0)
          {
            upper_or_lower = -1.0;
          }
        else if (p[1] < 0.0)
          {
            upper_or_lower = 1.0;
          }
        else //if (p[1]  == 0.0)
          {
            // Then another vertex must not have zero Y coordinate
            if (face->vertex (1-v)[1] > 0.0)
              {
                upper_or_lower = -1.0;
              }
            else if (face->vertex (1-v)[1] < 0.0)
              {
                upper_or_lower = 1.0;
              }
          }
        Assert (upper_or_lower != 0.0, ExcMessage ("All vertices on face have zero Y"));

        const double x = std::max (p[0], 1e-16);
        Assert (p[0] > -1e-6, ExcMessage ("Point not on foil"));
        Assert (p[0] <  1.0 + 1e-6, ExcMessage ("Point not on foil"));

        Fad_db x_ad = x;
        x_ad.diff (0,1);

        Fad_db y = thickness<Fad_db> (x_ad);
        Assert (std::abs (std::abs (p[1]) - y) < 1e-6, ExcMessage ("Point not on foil"));
        Tensor<1,2> return_value;
        return_value[0] = y.fastAccessDx (0);
        return_value[1] = upper_or_lower;
        face_vertex_normals[v] = return_value/return_value.norm();
      }
    return;
  }

}
<|endoftext|>


<commit_before>#include "Genes/Castling_Possible_Gene.h"

#include <string>
#include <map>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"

#include "Utility/Random.h"
#include "Utility/Math.h"

Castling_Possible_Gene::Castling_Possible_Gene() noexcept
{
    normalize_sides();
}

void Castling_Possible_Gene::normalize_sides() noexcept
{
    Math::normalize(opening_kingside_preference, opening_queenside_preference);
    Math::normalize(endgame_kingside_preference, endgame_queenside_preference);
}

void Castling_Possible_Gene::adjust_properties(std::map<std::string, double>& properties) const noexcept
{
    properties["Kingside Preference - Opening"] = opening_kingside_preference;
    properties["Queenside Preference - Opening"] = opening_queenside_preference;
    properties["Kingside Preference - Endgame"] = endgame_kingside_preference;
    properties["Queenside Preference - Endgame"] = endgame_queenside_preference;
    properties["Unmoved Rook Bonus - Opening"] = opening_rook_unmoved_score;
    properties["Unmoved Rook Bonus - Endgame"] = endgame_rook_unmoved_score;
}

void Castling_Possible_Gene::load_gene_properties(const std::map<std::string, double>& properties)
{
    opening_kingside_preference = properties.at("Kingside Preference - Opening");
    opening_queenside_preference = properties.at("Queenside Preference - Opening");
    endgame_kingside_preference = properties.at("Kingside Preference - Endgame");
    endgame_queenside_preference = properties.at("Queenside Preference - Endgame");
    opening_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Opening");
    endgame_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Endgame");
    normalize_sides();
}

std::string Castling_Possible_Gene::name() const noexcept
{
    return "Castling Possible Gene";
}

double Castling_Possible_Gene::score_board(const Board& board, Piece_Color perspective, size_t depth, double game_progress) const noexcept
{
    auto kingside_preference = Math::interpolate(opening_kingside_preference, endgame_kingside_preference, game_progress);
    auto queenside_preference = Math::interpolate(opening_queenside_preference, endgame_queenside_preference, game_progress);

    // check if a castling move lies between here and the actual state of the board
    if(board.player_castled(perspective))
    {
        auto castling_index = board.castling_move_index(perspective);
        auto first_searched_move_index = board.game_length() - depth;
        if(castling_index >= first_searched_move_index) // castling has not occurred on the actual board
        {
            auto castling_distance = castling_index - first_searched_move_index + 1;
            return (board.castling_direction(perspective) > 0 ? kingside_preference : queenside_preference)/castling_distance;
        }
    }

    if( ! board.piece_has_moved(board.find_king(perspective)))
    {
        auto score = 0.0;
        auto base_rank = perspective == Piece_Color::WHITE ? 1 : 8;
        auto unmoved_rook_bonus = Math::interpolate(opening_rook_unmoved_score,
                                                    endgame_rook_unmoved_score,
                                                    game_progress);
        if( ! board.piece_has_moved({'a', base_rank}))
        {
            score += queenside_preference;
        }

        if( ! board.piece_has_moved({'h', base_rank}))
        {
            score += kingside_preference;
        }

        return score*unmoved_rook_bonus;
    }

    return 0.0;
}

void Castling_Possible_Gene::gene_specific_mutation() noexcept
{
    switch(Random::random_integer(1, 6))
    {
        case 1:
            opening_kingside_preference += Random::random_laplace(0.03);
            break;
        case 2:
            endgame_kingside_preference += Random::random_laplace(0.03);
            break;
        case 3:
            opening_queenside_preference += Random::random_laplace(0.03);
            break;
        case 4:
            endgame_queenside_preference += Random::random_laplace(0.03);
            break;
        case 5:
            opening_rook_unmoved_score += Random::random_laplace(0.001);
            break;
        case 6:
            endgame_rook_unmoved_score += Random::random_laplace(0.001);
            break;
        default:
            assert(false);
    }

    normalize_sides();
}
<commit_msg>Increase mutation rate of Unmoved Rook Bonus<commit_after>#include "Genes/Castling_Possible_Gene.h"

#include <string>
#include <map>

#include "Genes/Gene.h"
#include "Game/Board.h"
#include "Game/Color.h"

#include "Utility/Random.h"
#include "Utility/Math.h"

Castling_Possible_Gene::Castling_Possible_Gene() noexcept
{
    normalize_sides();
}

void Castling_Possible_Gene::normalize_sides() noexcept
{
    Math::normalize(opening_kingside_preference, opening_queenside_preference);
    Math::normalize(endgame_kingside_preference, endgame_queenside_preference);
}

void Castling_Possible_Gene::adjust_properties(std::map<std::string, double>& properties) const noexcept
{
    properties["Kingside Preference - Opening"] = opening_kingside_preference;
    properties["Queenside Preference - Opening"] = opening_queenside_preference;
    properties["Kingside Preference - Endgame"] = endgame_kingside_preference;
    properties["Queenside Preference - Endgame"] = endgame_queenside_preference;
    properties["Unmoved Rook Bonus - Opening"] = opening_rook_unmoved_score;
    properties["Unmoved Rook Bonus - Endgame"] = endgame_rook_unmoved_score;
}

void Castling_Possible_Gene::load_gene_properties(const std::map<std::string, double>& properties)
{
    opening_kingside_preference = properties.at("Kingside Preference - Opening");
    opening_queenside_preference = properties.at("Queenside Preference - Opening");
    endgame_kingside_preference = properties.at("Kingside Preference - Endgame");
    endgame_queenside_preference = properties.at("Queenside Preference - Endgame");
    opening_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Opening");
    endgame_rook_unmoved_score = properties.at("Unmoved Rook Bonus - Endgame");
    normalize_sides();
}

std::string Castling_Possible_Gene::name() const noexcept
{
    return "Castling Possible Gene";
}

double Castling_Possible_Gene::score_board(const Board& board, Piece_Color perspective, size_t depth, double game_progress) const noexcept
{
    auto kingside_preference = Math::interpolate(opening_kingside_preference, endgame_kingside_preference, game_progress);
    auto queenside_preference = Math::interpolate(opening_queenside_preference, endgame_queenside_preference, game_progress);

    // check if a castling move lies between here and the actual state of the board
    if(board.player_castled(perspective))
    {
        auto castling_index = board.castling_move_index(perspective);
        auto first_searched_move_index = board.game_length() - depth;
        if(castling_index >= first_searched_move_index) // castling has not occurred on the actual board
        {
            auto castling_distance = castling_index - first_searched_move_index + 1;
            return (board.castling_direction(perspective) > 0 ? kingside_preference : queenside_preference)/castling_distance;
        }
    }

    if( ! board.piece_has_moved(board.find_king(perspective)))
    {
        auto score = 0.0;
        auto base_rank = perspective == Piece_Color::WHITE ? 1 : 8;
        auto unmoved_rook_bonus = Math::interpolate(opening_rook_unmoved_score,
                                                    endgame_rook_unmoved_score,
                                                    game_progress);
        if( ! board.piece_has_moved({'a', base_rank}))
        {
            score += queenside_preference;
        }

        if( ! board.piece_has_moved({'h', base_rank}))
        {
            score += kingside_preference;
        }

        return score*unmoved_rook_bonus;
    }

    return 0.0;
}

void Castling_Possible_Gene::gene_specific_mutation() noexcept
{
    switch(Random::random_integer(1, 6))
    {
        case 1:
            opening_kingside_preference += Random::random_laplace(0.03);
            break;
        case 2:
            endgame_kingside_preference += Random::random_laplace(0.03);
            break;
        case 3:
            opening_queenside_preference += Random::random_laplace(0.03);
            break;
        case 4:
            endgame_queenside_preference += Random::random_laplace(0.03);
            break;
        case 5:
            opening_rook_unmoved_score += Random::random_laplace(0.03);
            break;
        case 6:
            endgame_rook_unmoved_score += Random::random_laplace(0.03);
            break;
        default:
            assert(false);
    }

    normalize_sides();
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/CONCEPT/classTest.h>
#include <BALLTestConfig.h>

///////////////////////////

#include <BALL/STRUCTURE/sideChainPlacementProcessor.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/SYSTEM/file.h>
#include <BALL/KERNEL/system.h>
///////////////////////////

using namespace BALL;

START_TEST(SideChainPlacementProcessor, "$Id:$")

PRECISION(1e-5)

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

SideChainPlacementProcessor* scpp;
CHECK(SideChainPlacementProcessor())
  scpp = new SideChainPlacementProcessor();
	TEST_NOT_EQUAL(scpp,0)
RESULT

CHECK(~SideChainPlacementProcessor())
	delete scpp;
RESULT

CHECK(setDefaultOptions())
	SideChainPlacementProcessor scpp;
	scpp.setDefaultOptions();

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::METHOD),
														 SideChainPlacementProcessor::Default::METHOD)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_BINARY_PATH),
														 SideChainPlacementProcessor::Default::SCWRL_BINARY_PATH)

	TEST_EQUAL(scpp.options.getBool(SideChainPlacementProcessor::Option::MUTATE_SELECTED_SIDE_CHAINS),
																 SideChainPlacementProcessor::Default::MUTATE_SELECTED_SIDE_CHAINS)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_INPUT_FILE),
														 SideChainPlacementProcessor::Default::SCWRL_INPUT_FILE)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_SEQUENCE_FILE),
														 SideChainPlacementProcessor::Default::SCWRL_SEQUENCE_FILE)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE),
														 SideChainPlacementProcessor::Default::SCWRL_OUTPUT_FILE)
RESULT

CHECK( setMutations() / getMutations() )
	SideChainPlacementProcessor scpp;
	TEST_EQUAL(scpp.getMutations(), "")
	scpp.setMutations("CCHHPPTTAA");
	TEST_EQUAL(scpp.getMutations(), "CCHHPPTTAA")
RESULT

CHECK( applied on empty System )
	SideChainPlacementProcessor scpp;
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_INPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_input_1.pdb));
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_1.pdb));

	System sys;
	sys.apply(scpp);
RESULT

CHECK( operator() apply to a system )
	SideChainPlacementProcessor scpp;
	//TODO shouldn't we test the input file as well?
	//scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_INPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_input_1.pdb));
	//	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_SEQUENCE_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_sequence_1.dat));
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_1.pdb));

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;

	sys.apply(scpp);

	// store the result in a temporary file
	String temp;
  File::createTemporaryFilename(temp);
	PDBFile PDB_temp(temp, std::ios::out);
	PDB_temp << sys;
	PDB_temp.close();

	// get the precomputed result
	PDBFile PDB_pre( BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_pre_1.pdb), std::ios::out);

	// compare
	//////// geht leider nicht! TEST_EQUAL(PDB_temp==PDB_pre, true) //TODO

	// remove the temp file
	File::remove(temp);
RESULT

///////////////////TODO////////////////////////////

CHECK(apply to a protein)
	SideChainPlacementProcessor scpp;

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	Protein* prot = sys.getProtein(0);
RESULT

CHECK(apply to a chain)
	SideChainPlacementProcessor scpp;

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	Chain* chain3 = (sys.getProtein(0)->getChain(2));

RESULT

CHECK( apply to a selection)
	SideChainPlacementProcessor scpp;

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	Residue* res = (sys.getProtein(0)->getChain(1))->getResidue(0);
	res->select();
	Chain* chain2 = (sys.getProtein(0)->getChain(1));
	chain2->select();
RESULT

CHECK(mutate)
	SideChainPlacementProcessor scpp;
 	scpp.options.set(SideChainPlacementProcessor::Option::MUTATE_SELECTED_SIDE_CHAINS, true);
	//TODO   scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_mut1.pdb));

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	String mutated_seq = "arCdcCeg";
	scpp.setMutations(mutated_seq);
	sys.apply(scpp); //TODO werden beide cysteine gesetzt?
	TEST_EQUAL(sys.getProtein(0)->getChain(0)->getResidue(2)->getName(), "CYS")
	TEST_EQUAL(sys.getProtein(0)->getChain(1)->getResidue(1)->getName(), "CYS")
	scpp.clear();

	scpp.options.set(SideChainPlacementProcessor::Option::MUTATE_SELECTED_SIDE_CHAINS, true);
// TODO 	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_mut2.pdb));

	System sys2;
	PDBFile mol2(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol2 >> sys2;
	mutated_seq = "arCd";
	scpp.setMutations(mutated_seq);
	Chain* chain1 = (sys.getProtein(0)->getChain(0));
	chain1->apply(scpp);

	sys2.apply(scpp);
	TEST_EQUAL(sys.getProtein(0)->getChain(0)->getResidue(2)->getName(), "CYS")
	TEST_EQUAL(sys.getProtein(0)->getChain(1)->getResidue(1)->getName(), "GLN")

RESULT

CHECK(check energy) //TODO
/*	SideChainPlacementProcessor scpp;
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_AA.pdb));

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_AA.pdb), std::ios::in);
	mol >> sys;

	// energy before
	AmberFF amber_ff;
	amber_ff.setup(sys);
	float before =  amber_ff.updateEnergy();

	sys.apply(scpp);

	// energy after
	amber_ff.setup(sys);
	float after =  amber_ff.updateEnergy();
	TEST_REAL_EQUAL(before > after)
*/
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>Improved mutate test but classTest.h throws uncatchable exception<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/CONCEPT/classTest.h>
#include <BALLTestConfig.h>

///////////////////////////

#include <BALL/STRUCTURE/sideChainPlacementProcessor.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/SYSTEM/file.h>
#include <BALL/KERNEL/system.h>
///////////////////////////

using namespace BALL;

START_TEST(SideChainPlacementProcessor, "$Id:$")

PRECISION(1e-5)

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

SideChainPlacementProcessor* scpp;
CHECK(SideChainPlacementProcessor())
  scpp = new SideChainPlacementProcessor();
	TEST_NOT_EQUAL(scpp,0)
RESULT

CHECK(~SideChainPlacementProcessor())
	delete scpp;
RESULT

CHECK(setDefaultOptions())
	SideChainPlacementProcessor scpp;
	scpp.setDefaultOptions();

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::METHOD),
														 SideChainPlacementProcessor::Default::METHOD)

	//if no SCWRL installed, no path available!
// 	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_BINARY_PATH),
// 														 SideChainPlacementProcessor::Default::SCWRL_BINARY_PATH)

	TEST_EQUAL(scpp.options.getBool(SideChainPlacementProcessor::Option::MUTATE_SELECTED_SIDE_CHAINS),
																 SideChainPlacementProcessor::Default::MUTATE_SELECTED_SIDE_CHAINS)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_INPUT_FILE),
														 SideChainPlacementProcessor::Default::SCWRL_INPUT_FILE)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_SEQUENCE_FILE),
														 SideChainPlacementProcessor::Default::SCWRL_SEQUENCE_FILE)

	TEST_EQUAL(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE),
														 SideChainPlacementProcessor::Default::SCWRL_OUTPUT_FILE)
RESULT

CHECK( setMutations() / getMutations() )
	SideChainPlacementProcessor scpp;
	TEST_EQUAL(scpp.getMutations(), "")
	scpp.setMutations("CCHHPPTTAA");
	TEST_EQUAL(scpp.getMutations(), "CCHHPPTTAA")
RESULT

CHECK( applied on empty System )
	SideChainPlacementProcessor scpp;
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_INPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_input_1.pdb));
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_1.pdb));

	System sys;
	sys.apply(scpp);
RESULT

CHECK( operator() apply to a system )
	SideChainPlacementProcessor scpp;
	//TODO shouldn't we test the input file as well?
	//scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_INPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_input_1.pdb));
	//	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_SEQUENCE_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_sequence_1.dat));
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_1.pdb));

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;

	sys.apply(scpp);

	// store the result in a temporary file
	String temp;
  File::createTemporaryFilename(temp);
	PDBFile PDB_temp(temp, std::ios::out);
	PDB_temp << sys;
	PDB_temp.close();

	// get the precomputed result
	PDBFile PDB_pre( BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_pre_1.pdb), std::ios::out);

	// compare
	//////// geht leider nicht! TEST_EQUAL(PDB_temp==PDB_pre, true) //TODO

	// remove the temp file
	File::remove(temp);
RESULT

///////////////////TODO////////////////////////////

CHECK(apply to a protein)
	SideChainPlacementProcessor scpp;

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	Protein* prot = sys.getProtein(0);
RESULT

CHECK(apply to a chain)
	SideChainPlacementProcessor scpp;

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	Chain* chain3 = (sys.getProtein(0)->getChain(2));

RESULT

CHECK( apply to a selection)
	SideChainPlacementProcessor scpp;

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	Residue* res = (sys.getProtein(0)->getChain(1))->getResidue(0);
	res->select();
	Chain* chain2 = (sys.getProtein(0)->getChain(1));
	chain2->select();
RESULT

CHECK(mutate)
	SideChainPlacementProcessor scpp;
 	scpp.options.set(SideChainPlacementProcessor::Option::MUTATE_SELECTED_SIDE_CHAINS, true);
	//TODO   scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_mut1.pdb));

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol >> sys;
	String mutated_seq = "arCdcCeg";
	scpp.setMutations(mutated_seq);

	//check if SCWRL path is set and the required file exists
	try
	{
	  File file(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_BINARY_PATH));
	  if(file.isExecutable())
	  {
		sys.apply(scpp); //TODO werden beide cysteine gesetzt?
		TEST_EQUAL(sys.getProtein(0)->getChain(0)->getResidue(2)->getName(), "CYS")
		TEST_EQUAL(sys.getProtein(0)->getChain(1)->getResidue(1)->getName(), "CYS")
		scpp.clear();
	  }
	}
	//TODO in classTest.h catch handler throws "caught exception" error/message
	catch(...)
	{
	  std::cout << "catch FileNotFound" << std::endl;
	}

	scpp.options.set(SideChainPlacementProcessor::Option::MUTATE_SELECTED_SIDE_CHAINS, true);
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_mut2.pdb));

	System sys2;
	PDBFile mol2(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test.pdb), std::ios::in);
	mol2 >> sys2;
	mutated_seq = "arCd";
	scpp.setMutations(mutated_seq);
	Chain* chain1 = (sys.getProtein(0)->getChain(0));
	chain1->apply(scpp);

	//check if SCWRL path is set and the required file exists
	try
	{
	  File file2(scpp.options.get(SideChainPlacementProcessor::Option::SCWRL_BINARY_PATH));
	  if(file2.isExecutable())
	  {
		sys2.apply(scpp);
		TEST_EQUAL(sys.getProtein(0)->getChain(0)->getResidue(2)->getName(), "CYS")
		TEST_EQUAL(sys.getProtein(0)->getChain(1)->getResidue(1)->getName(), "GLN")
	  }
	}
	//TODO in classTest.h catch handler throws "caught exception" error/message
	catch(...)
	{
	  std::cout << "catch FileNotFound" << std::endl;
	}

RESULT

CHECK(check energy) //TODO
/*	SideChainPlacementProcessor scpp;
	scpp.options.set(SideChainPlacementProcessor::Option::SCWRL_OUTPUT_FILE, BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_output_AA.pdb));

	System sys;
	PDBFile mol(BALL_TEST_DATA_PATH(SideChainPlacementProcessor_test_AA.pdb), std::ios::in);
	mol >> sys;

	// energy before
	AmberFF amber_ff;
	amber_ff.setup(sys);
	float before =  amber_ff.updateEnergy();

	sys.apply(scpp);

	// energy after
	amber_ff.setup(sys);
	float after =  amber_ff.updateEnergy();
	TEST_REAL_EQUAL(before > after)
*/
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>