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

#include "RequestManagerVirtualMachine.h"
#include "Nebula.h"

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

bool RequestManagerVirtualMachine::vm_authorization(int oid,
                                                    int hid,
                                                    ImageTemplate *tmpl,
                                                    RequestAttributes& att)
{
    PoolObjectSQL * object;

    int  ouid;
    int  ogid;

    if ( att.uid == 0 )
    {
        return true;
    }

    object = pool->get(oid,true);

    if ( object == 0 )
    {
        failure_response(NO_EXISTS,
                get_error(object_name(auth_object),oid),
                att);

        return false;
    }

    ouid = object->get_uid();
    ogid = object->get_gid();

    object->unlock();

    AuthRequest ar(att.uid, att.gid);

    ar.add_auth(auth_object, oid, ogid, auth_op, ouid, false);

    if (hid != -1)
    {
        ar.add_auth(AuthRequest::HOST,hid,-1,AuthRequest::USE,0,false);
    }
    else if (tmpl != 0)
    {
        string t64;

        ar.add_auth(AuthRequest::IMAGE,
                    tmpl->to_xml(t64),
                    -1,
                    AuthRequest::CREATE,
                    att.uid,
                    false);
    }

    if (UserPool::authorize(ar) == -1)
    {
        failure_response(AUTHORIZATION,
                authorization_error(ar.message, att),
                att);

        return false;
    }

    return true;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int RequestManagerVirtualMachine::get_host_information(int hid,
                                                string& name,
                                                string& vmm,
                                                string& tm,
                                                RequestAttributes& att)
{
    Nebula&    nd    = Nebula::instance();
    HostPool * hpool = nd.get_hpool();

    Host * host;

    host = hpool->get(hid,true);

    if ( host == 0 )
    {
        failure_response(NO_EXISTS,
                get_error(object_name(AuthRequest::HOST),hid),
                att);

        return -1;
    }

    name = host->get_name();
    vmm  = host->get_vmm_mad();
    tm   = host->get_tm_mad();

    host->unlock();

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

VirtualMachine * RequestManagerVirtualMachine::get_vm(int id,
                                                      RequestAttributes& att)
{
    VirtualMachine * vm;

    vm = static_cast<VirtualMachine *>(pool->get(id,true));

    if ( vm == 0 )
    {
        failure_response(NO_EXISTS,get_error(object_name(auth_object),id), att);
        return 0;
    }

    return vm;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int RequestManagerVirtualMachine::add_history(VirtualMachine * vm,
                                       int              hid,
                                       const string&    hostname,
                                       const string&    vmm_mad,
                                       const string&    tm_mad,
                                       RequestAttributes& att)
{
    Nebula& nd = Nebula::instance();
    string  vmdir;

    int     rc;

    VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);

    nd.get_configuration_attribute("VM_DIR",vmdir);

    vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad);

    rc = vmpool->update_history(vm);

    if ( rc != 0 )
    {
        failure_response(INTERNAL,
                request_error("Can not update virtual machine history",""),
                att);

        return -1;
    }

    vmpool->update(vm);

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineAction::request_execute(xmlrpc_c::paramList const& paramList,
                                           RequestAttributes& att)
{
    string action = xmlrpc_c::value_string(paramList.getString(1));
    int    id     = xmlrpc_c::value_int(paramList.getInt(2));

    int    rc;

    Nebula& nd = Nebula::instance();
    DispatchManager * dm = nd.get_dm();

    if ( vm_authorization(id,-1,0,att) == false )
    {
        return;
    }

    if (action == "shutdown")
    {
        rc = dm->shutdown(id);
    }
    else if (action == "hold")
    {
        rc = dm->hold(id);
    }
    else if (action == "release")
    {
        rc = dm->release(id);
    }
    else if (action == "stop")
    {
        rc = dm->stop(id);
    }
    else if (action == "cancel")
    {
        rc = dm->cancel(id);
    }
    else if (action == "suspend")
    {
        rc = dm->suspend(id);
    }
    else if (action == "resume")
    {
        rc = dm->resume(id);
    }
    else if (action == "restart")
    {
        rc = dm->restart(id);
    }
    else if (action == "finalize")
    {
        rc = dm->finalize(id);
    }
    else if (action == "resubmit")
    {
        rc = dm->resubmit(id);
    }

    switch (rc)
    {
        case 0:
            success_response(id, att);
            break;
        case -1:
            failure_response(NO_EXISTS,
                    get_error(object_name(auth_object),id),
                    att);
            break;
        case -2:
             failure_response(ACTION,
                     request_error("Worng state to perform action",""),
                     att);
             break;
        case -3:
            failure_response(ACTION,
                    request_error("Virtual machine action not supported",""),
                    att);
            break;
        default:
            failure_response(INTERNAL,
                    request_error("Internal error","Action result not defined"),
                    att);
    }

    return;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
                                           RequestAttributes& att)
{
    Nebula&             nd = Nebula::instance();
    DispatchManager *   dm = nd.get_dm();

    VirtualMachine * vm;

    string hostname;
    string vmm_mad;
    string tm_mad;

    int id  = xmlrpc_c::value_int(paramList.getInt(1));
    int hid = xmlrpc_c::value_int(paramList.getInt(2));

    if ( vm_authorization(id,hid,0,att) == false )
    {
        return;
    }

    if (get_host_information(hid,hostname,vmm_mad,tm_mad, att) != 0)
    {
        return;
    }

    if ( (vm = get_vm(id, att)) == 0 )
    {
        return;
    }

    if ( vm->get_state() != VirtualMachine::PENDING )
    {
        failure_response(ACTION,
                request_error("Worng state to perform action",""),
                att);

        vm->unlock();
        return;
    }

    if ( add_history(vm,hid,hostname,vmm_mad,tm_mad,att) != 0)
    {
        vm->unlock();
        return;
    }

    dm->deploy(vm);

    vm->unlock();

    success_response(id, att);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList,
                                            RequestAttributes& att)
{
    Nebula&             nd = Nebula::instance();
    DispatchManager *   dm = nd.get_dm();

    VirtualMachine * vm;

    string hostname;
    string vmm_mad;
    string tm_mad;

    int  id   = xmlrpc_c::value_int(paramList.getInt(1));
    int  hid  = xmlrpc_c::value_int(paramList.getInt(2));
    bool live = xmlrpc_c::value_boolean(paramList.getBoolean(3));

    if ( vm_authorization(id,hid,0,att) == false )
    {
        return;
    }

    if (get_host_information(hid,hostname,vmm_mad,tm_mad,att) != 0)
    {
        return;
    }

    if ( (vm = get_vm(id, att)) == 0 )
    {
        return;
    }

    if((vm->get_state()     != VirtualMachine::ACTIVE)  ||
       (vm->get_lcm_state() != VirtualMachine::RUNNING) ||
       (vm->hasPreviousHistory() && vm->get_previous_reason() == History::NONE))
    {
        failure_response(ACTION,
                request_error("Worng state to perform action",""),
                att);

        vm->unlock();
        return;
    }

    if ( add_history(vm,hid,hostname,vmm_mad,tm_mad,att) != 0)
    {
        vm->unlock();
        return;
    }

    if ( live == true )
    {
        dm->live_migrate(vm);
    }
    else
    {
        dm->migrate(vm);
    }

    vm->unlock();

    success_response(id, att);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramList,
                                             RequestAttributes& att)
{
    Nebula&     nd    = Nebula::instance();
    ImagePool * ipool = nd.get_ipool();

    int    id       = xmlrpc_c::value_int(paramList.getInt(1));
    int    disk_id  = xmlrpc_c::value_int(paramList.getInt(2));
    string img_name = xmlrpc_c::value_string(paramList.getString(3));

    VirtualMachine * vm;
    string           vm_owner;

    int              iid;
    ImageTemplate *  itemplate;

    int           rc;
    ostringstream oss;
    string        error_str;
    char *        error_char;

    // ------------------ Template for the new image ------------------

    oss << "NAME= " << img_name << endl;
    oss << "PUBLIC = NO " << endl;
    oss << "SOURCE = - " << endl;

    itemplate = new ImageTemplate;

    itemplate->parse(oss.str(), &error_char);

    // ------------------ Authorize the operation ------------------

    if ( vm_authorization(id,-1,itemplate,att) == false )
    {
        return;
    }

    // ------------------ Create the image ------------------

    rc = ipool->allocate(att.uid, att.gid, att.uname, att.gname, itemplate,
            &iid, error_str);

    if (rc < 0)
    {
        failure_response(INTERNAL,
                allocate_error(AuthRequest::IMAGE, error_str), att);
        return;
    }

    // ------------------ Store image id to save the disk ------------------

    if ( (vm = get_vm(id, att)) == 0 )
    {
        Image * img;

        if ( (img = ipool->get(iid,true)) != 0 )
        {
            string tmp_error;

            ipool->drop(img, tmp_error);
            img->unlock();
        }

        return;
    }

    rc = vm->save_disk(disk_id, iid, error_str);

    if ( rc == 0 )
    {
        pool->update(vm);
    }

    vm->unlock();

    if ( rc == -1 )
    {
        Image * img;

        if ( (img = ipool->get(iid,true)) != 0 )
        {
            string tmp_error;

            ipool->drop(img, tmp_error);
            img->unlock();
        }

        failure_response(INTERNAL,
                request_error("Can not save_as disk",error_str),
                att);
        return;
    }

    // Return the new allocated Image ID
    success_response(iid, att);
}

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

#include "RequestManagerVirtualMachine.h"
#include "Nebula.h"

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

bool RequestManagerVirtualMachine::vm_authorization(int oid,
                                                    int hid,
                                                    ImageTemplate *tmpl,
                                                    RequestAttributes& att)
{
    PoolObjectSQL * object;

    int  ouid;
    int  ogid;

    if ( att.uid == 0 )
    {
        return true;
    }

    object = pool->get(oid,true);

    if ( object == 0 )
    {
        failure_response(NO_EXISTS,
                get_error(object_name(auth_object),oid),
                att);

        return false;
    }

    ouid = object->get_uid();
    ogid = object->get_gid();

    object->unlock();

    AuthRequest ar(att.uid, att.gid);

    ar.add_auth(auth_object, oid, ogid, auth_op, ouid, false);

    if (hid != -1)
    {
        ar.add_auth(AuthRequest::HOST,hid,-1,AuthRequest::USE,0,false);
    }
    else if (tmpl != 0)
    {
        string t64;

        ar.add_auth(AuthRequest::IMAGE,
                    tmpl->to_xml(t64),
                    -1,
                    AuthRequest::CREATE,
                    att.uid,
                    false);
    }

    if (UserPool::authorize(ar) == -1)
    {
        failure_response(AUTHORIZATION,
                authorization_error(ar.message, att),
                att);

        return false;
    }

    return true;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int RequestManagerVirtualMachine::get_host_information(int hid,
                                                string& name,
                                                string& vmm,
                                                string& tm,
                                                RequestAttributes& att)
{
    Nebula&    nd    = Nebula::instance();
    HostPool * hpool = nd.get_hpool();

    Host * host;

    host = hpool->get(hid,true);

    if ( host == 0 )
    {
        failure_response(NO_EXISTS,
                get_error(object_name(AuthRequest::HOST),hid),
                att);

        return -1;
    }

    name = host->get_name();
    vmm  = host->get_vmm_mad();
    tm   = host->get_tm_mad();

    host->unlock();

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

VirtualMachine * RequestManagerVirtualMachine::get_vm(int id,
                                                      RequestAttributes& att)
{
    VirtualMachine * vm;

    vm = static_cast<VirtualMachine *>(pool->get(id,true));

    if ( vm == 0 )
    {
        failure_response(NO_EXISTS,get_error(object_name(auth_object),id), att);
        return 0;
    }

    return vm;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int RequestManagerVirtualMachine::add_history(VirtualMachine * vm,
                                       int              hid,
                                       const string&    hostname,
                                       const string&    vmm_mad,
                                       const string&    tm_mad,
                                       RequestAttributes& att)
{
    Nebula& nd = Nebula::instance();
    string  vmdir;

    int     rc;

    VirtualMachinePool * vmpool = static_cast<VirtualMachinePool *>(pool);

    nd.get_configuration_attribute("VM_DIR",vmdir);

    vm->add_history(hid,hostname,vmdir,vmm_mad,tm_mad);

    rc = vmpool->update_history(vm);

    if ( rc != 0 )
    {
        failure_response(INTERNAL,
                request_error("Can not update virtual machine history",""),
                att);

        return -1;
    }

    vmpool->update(vm);

    return 0;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void VirtualMachineAction::request_execute(xmlrpc_c::paramList const& paramList,
                                           RequestAttributes& att)
{
    string action = xmlrpc_c::value_string(paramList.getString(1));
    int    id     = xmlrpc_c::value_int(paramList.getInt(2));

    int    rc;

    Nebula& nd = Nebula::instance();
    DispatchManager * dm = nd.get_dm();

    if ( vm_authorization(id,-1,0,att) == false )
    {
        return;
    }

    if (action == "shutdown")
    {
        rc = dm->shutdown(id);
    }
    else if (action == "hold")
    {
        rc = dm->hold(id);
    }
    else if (action == "release")
    {
        rc = dm->release(id);
    }
    else if (action == "stop")
    {
        rc = dm->stop(id);
    }
    else if (action == "cancel")
    {
        rc = dm->cancel(id);
    }
    else if (action == "suspend")
    {
        rc = dm->suspend(id);
    }
    else if (action == "resume")
    {
        rc = dm->resume(id);
    }
    else if (action == "restart")
    {
        rc = dm->restart(id);
    }
    else if (action == "finalize")
    {
        rc = dm->finalize(id);
    }
    else if (action == "resubmit")
    {
        rc = dm->resubmit(id);
    }

    switch (rc)
    {
        case 0:
            success_response(id, att);
            break;
        case -1:
            failure_response(NO_EXISTS,
                    get_error(object_name(auth_object),id),
                    att);
            break;
        case -2:
             failure_response(ACTION,
                     request_error("Wrong state to perform action",""),
                     att);
             break;
        case -3:
            failure_response(ACTION,
                    request_error("Virtual machine action not supported",""),
                    att);
            break;
        default:
            failure_response(INTERNAL,
                    request_error("Internal error","Action result not defined"),
                    att);
    }

    return;
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
                                           RequestAttributes& att)
{
    Nebula&             nd = Nebula::instance();
    DispatchManager *   dm = nd.get_dm();

    VirtualMachine * vm;

    string hostname;
    string vmm_mad;
    string tm_mad;

    int id  = xmlrpc_c::value_int(paramList.getInt(1));
    int hid = xmlrpc_c::value_int(paramList.getInt(2));

    if ( vm_authorization(id,hid,0,att) == false )
    {
        return;
    }

    if (get_host_information(hid,hostname,vmm_mad,tm_mad, att) != 0)
    {
        return;
    }

    if ( (vm = get_vm(id, att)) == 0 )
    {
        return;
    }

    if ( vm->get_state() != VirtualMachine::PENDING )
    {
        failure_response(ACTION,
                request_error("Wrong state to perform action",""),
                att);

        vm->unlock();
        return;
    }

    if ( add_history(vm,hid,hostname,vmm_mad,tm_mad,att) != 0)
    {
        vm->unlock();
        return;
    }

    dm->deploy(vm);

    vm->unlock();

    success_response(id, att);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList,
                                            RequestAttributes& att)
{
    Nebula&             nd = Nebula::instance();
    DispatchManager *   dm = nd.get_dm();

    VirtualMachine * vm;

    string hostname;
    string vmm_mad;
    string tm_mad;

    int  id   = xmlrpc_c::value_int(paramList.getInt(1));
    int  hid  = xmlrpc_c::value_int(paramList.getInt(2));
    bool live = xmlrpc_c::value_boolean(paramList.getBoolean(3));

    if ( vm_authorization(id,hid,0,att) == false )
    {
        return;
    }

    if (get_host_information(hid,hostname,vmm_mad,tm_mad,att) != 0)
    {
        return;
    }

    if ( (vm = get_vm(id, att)) == 0 )
    {
        return;
    }

    if((vm->get_state()     != VirtualMachine::ACTIVE)  ||
       (vm->get_lcm_state() != VirtualMachine::RUNNING) ||
       (vm->hasPreviousHistory() && vm->get_previous_reason() == History::NONE))
    {
        failure_response(ACTION,
                request_error("Wrong state to perform action",""),
                att);

        vm->unlock();
        return;
    }

    if ( add_history(vm,hid,hostname,vmm_mad,tm_mad,att) != 0)
    {
        vm->unlock();
        return;
    }

    if ( live == true )
    {
        dm->live_migrate(vm);
    }
    else
    {
        dm->migrate(vm);
    }

    vm->unlock();

    success_response(id, att);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void VirtualMachineSaveDisk::request_execute(xmlrpc_c::paramList const& paramList,
                                             RequestAttributes& att)
{
    Nebula&     nd    = Nebula::instance();
    ImagePool * ipool = nd.get_ipool();

    int    id       = xmlrpc_c::value_int(paramList.getInt(1));
    int    disk_id  = xmlrpc_c::value_int(paramList.getInt(2));
    string img_name = xmlrpc_c::value_string(paramList.getString(3));

    VirtualMachine * vm;
    string           vm_owner;

    int              iid;
    ImageTemplate *  itemplate;

    int           rc;
    ostringstream oss;
    string        error_str;
    char *        error_char;

    // ------------------ Template for the new image ------------------

    oss << "NAME= " << img_name << endl;
    oss << "PUBLIC = NO " << endl;
    oss << "SOURCE = - " << endl;

    itemplate = new ImageTemplate;

    itemplate->parse(oss.str(), &error_char);

    // ------------------ Authorize the operation ------------------

    if ( vm_authorization(id,-1,itemplate,att) == false )
    {
        return;
    }

    // ------------------ Create the image ------------------

    rc = ipool->allocate(att.uid, att.gid, att.uname, att.gname, itemplate,
            &iid, error_str);

    if (rc < 0)
    {
        failure_response(INTERNAL,
                allocate_error(AuthRequest::IMAGE, error_str), att);
        return;
    }

    // ------------------ Store image id to save the disk ------------------

    if ( (vm = get_vm(id, att)) == 0 )
    {
        Image * img;

        if ( (img = ipool->get(iid,true)) != 0 )
        {
            string tmp_error;

            ipool->drop(img, tmp_error);
            img->unlock();
        }

        return;
    }

    rc = vm->save_disk(disk_id, iid, error_str);

    if ( rc == 0 )
    {
        pool->update(vm);
    }

    vm->unlock();

    if ( rc == -1 )
    {
        Image * img;

        if ( (img = ipool->get(iid,true)) != 0 )
        {
            string tmp_error;

            ipool->drop(img, tmp_error);
            img->unlock();
        }

        failure_response(INTERNAL,
                request_error("Can not save_as disk",error_str),
                att);
        return;
    }

    // Return the new allocated Image ID
    success_response(iid, att);
}

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
<|endoftext|>


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

/*
 * NaCl inter-module communication primitives.
 *
 * This file implements common parts of IMC for "UNIX like systems" (i.e. not
 * used on Windows).
 */

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#if NACL_ANDROID
#include <linux/ashmem.h>
#endif

#include <algorithm>

#include "native_client/src/include/atomic_ops.h"

#include "native_client/src/shared/imc/nacl_imc_c.h"
#include "native_client/src/shared/platform/nacl_check.h"

static const char kNaClTempPrefixVar[] = "NACL_TMPFS_PREFIX";

/*
 * The pathname or SHM-namespace prefixes for memory objects created
 * by CreateMemoryObject().
 */
static const char kShmTempPrefix[] = "/tmp/google-nacl-shm-";
static const char kShmOpenPrefix[] = "/google-nacl-shm-";

static NaClCreateMemoryObjectFunc g_create_memory_object_func = NULL;

/* Duplicate a file descriptor. */
NaClHandle NaClDuplicateNaClHandle(NaClHandle handle) {
  return dup(handle);
}

void NaClSetCreateMemoryObjectFunc(NaClCreateMemoryObjectFunc func) {
  g_create_memory_object_func = func;
}

#if NACL_ANDROID
#define ASHMEM_DEVICE "/dev/ashmem"

static int AshmemCreateRegion(size_t size) {
  int fd;

  fd = open(ASHMEM_DEVICE, O_RDWR);
  if (fd < 0)
    return -1;

  if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) {
    close(fd);
    return -1;
  }

  return fd;
}
#endif

int NaClWouldBlock(void) {
  return errno == EAGAIN;
}

int NaClGetLastErrorString(char* buffer, size_t length) {
#if NACL_LINUX && !NACL_ANDROID
  char* message;
  /*
   * Note some Linux distributions provide only GNU version of strerror_r().
   */
  if (buffer == NULL || length == 0) {
    errno = ERANGE;
    return -1;
  }
  message = strerror_r(errno, buffer, length);
  if (message != buffer) {
    size_t message_bytes = strlen(message) + 1;
    length = std::min(message_bytes, length);
    memmove(buffer, message, length);
    buffer[length - 1] = '\0';
  }
  return 0;
#else
  return strerror_r(errno, buffer, length);
#endif
}

#if !NACL_ANDROID
static Atomic32 memory_object_count = 0;

static int TryShmOrTempOpen(size_t length, const char* prefix, bool use_temp) {
  char name[PATH_MAX];
  if (0 == length) {
    return -1;
  }

  for (;;) {
    int m;
    snprintf(name, sizeof name, "%s-%u.%u", prefix,
             getpid(),
             (int) AtomicIncrement(&memory_object_count, 1));
    if (use_temp) {
      m = open(name, O_RDWR | O_CREAT | O_EXCL, 0);
    } else {
      /*
       * Using 0 for the mode causes shm_unlink to fail with EACCES on Mac
       * OS X 10.8. As of 10.8, the kernel requires the user to have write
       * permission to successfully shm_unlink.
       */
      m = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IWUSR);
    }
    if (0 <= m) {
      if (use_temp) {
        int rc = unlink(name);
        DCHECK(rc == 0);
      } else {
        int rc = shm_unlink(name);
        DCHECK(rc == 0);
      }
      if (ftruncate(m, length) == -1) {
        close(m);
        m = -1;
      }
      return m;
    }
    if (errno != EEXIST) {
      return -1;
    }
    /* Retry only if we got EEXIST. */
  }
}
#endif

NaClHandle NaClCreateMemoryObject(size_t length, int executable) {
  int fd;

  if (0 == length) {
    return -1;
  }

  if (g_create_memory_object_func != NULL) {
    fd = g_create_memory_object_func(length, executable);
    if (fd >= 0)
      return fd;
  }

#if NACL_ANDROID
  return AshmemCreateRegion(length);
#else
  /*
   * /dev/shm is not always available on Linux.
   * Sometimes it's mounted as noexec.
   * To handle this case, sel_ldr can take a path
   * to tmpfs from the environment.
   */
#if NACL_LINUX && defined(NACL_ENABLE_TMPFS_REDIRECT_VAR)
  if (NACL_ENABLE_TMPFS_REDIRECT_VAR) {
    const char* prefix = getenv(kNaClTempPrefixVar);
    if (prefix != NULL) {
      fd = TryShmOrTempOpen(length, prefix, true);
      if (fd >= 0) {
        return fd;
      }
    }
  }
#endif

  if (NACL_OSX && executable) {
    /*
     * On Mac OS X, shm_open() gives us file descriptors that the OS
     * won't mmap() with PROT_EXEC, which is no good for the dynamic
     * code region, so we must use /tmp instead.
     */
    return TryShmOrTempOpen(length, kShmTempPrefix, true);
  }

  /* Try shm_open(). */
  return TryShmOrTempOpen(length, kShmOpenPrefix, false);
#endif  /* !NACL_ANDROID */
}

void* NaClMap(struct NaClDescEffector* effp,
              void* start, size_t length, int prot, int flags,
              NaClHandle memory, off_t offset) {
  static const int kPosixProt[] = {
    PROT_NONE,
    PROT_READ,
    PROT_WRITE,
    PROT_READ | PROT_WRITE,
    PROT_EXEC,
    PROT_READ | PROT_EXEC,
    PROT_WRITE | PROT_EXEC,
    PROT_READ | PROT_WRITE | PROT_EXEC
  };
  int adjusted = 0;
  UNREFERENCED_PARAMETER(effp);

  if (flags & NACL_MAP_SHARED) {
    adjusted |= MAP_SHARED;
  }
  if (flags & NACL_MAP_PRIVATE) {
    adjusted |= MAP_PRIVATE;
  }
  if (flags & NACL_MAP_FIXED) {
    adjusted |= MAP_FIXED;
  }
  return mmap(start, length, kPosixProt[prot & 7], adjusted, memory, offset);
}

int NaClUnmap(void* start, size_t length) {
  return munmap(start, length);
}
<commit_msg>Conditionalize conditionally-used variable kNaClTempPrefixVar<commit_after>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/*
 * NaCl inter-module communication primitives.
 *
 * This file implements common parts of IMC for "UNIX like systems" (i.e. not
 * used on Windows).
 */

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#if NACL_ANDROID
#include <linux/ashmem.h>
#endif

#include <algorithm>

#include "native_client/src/include/atomic_ops.h"

#include "native_client/src/shared/imc/nacl_imc_c.h"
#include "native_client/src/shared/platform/nacl_check.h"

#if NACL_LINUX && defined(NACL_ENABLE_TMPFS_REDIRECT_VAR)
static const char kNaClTempPrefixVar[] = "NACL_TMPFS_PREFIX";
#endif

/*
 * The pathname or SHM-namespace prefixes for memory objects created
 * by CreateMemoryObject().
 */
static const char kShmTempPrefix[] = "/tmp/google-nacl-shm-";
static const char kShmOpenPrefix[] = "/google-nacl-shm-";

static NaClCreateMemoryObjectFunc g_create_memory_object_func = NULL;

/* Duplicate a file descriptor. */
NaClHandle NaClDuplicateNaClHandle(NaClHandle handle) {
  return dup(handle);
}

void NaClSetCreateMemoryObjectFunc(NaClCreateMemoryObjectFunc func) {
  g_create_memory_object_func = func;
}

#if NACL_ANDROID
#define ASHMEM_DEVICE "/dev/ashmem"

static int AshmemCreateRegion(size_t size) {
  int fd;

  fd = open(ASHMEM_DEVICE, O_RDWR);
  if (fd < 0)
    return -1;

  if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) {
    close(fd);
    return -1;
  }

  return fd;
}
#endif

int NaClWouldBlock(void) {
  return errno == EAGAIN;
}

int NaClGetLastErrorString(char* buffer, size_t length) {
#if NACL_LINUX && !NACL_ANDROID
  char* message;
  /*
   * Note some Linux distributions provide only GNU version of strerror_r().
   */
  if (buffer == NULL || length == 0) {
    errno = ERANGE;
    return -1;
  }
  message = strerror_r(errno, buffer, length);
  if (message != buffer) {
    size_t message_bytes = strlen(message) + 1;
    length = std::min(message_bytes, length);
    memmove(buffer, message, length);
    buffer[length - 1] = '\0';
  }
  return 0;
#else
  return strerror_r(errno, buffer, length);
#endif
}

#if !NACL_ANDROID
static Atomic32 memory_object_count = 0;

static int TryShmOrTempOpen(size_t length, const char* prefix, bool use_temp) {
  char name[PATH_MAX];
  if (0 == length) {
    return -1;
  }

  for (;;) {
    int m;
    snprintf(name, sizeof name, "%s-%u.%u", prefix,
             getpid(),
             (int) AtomicIncrement(&memory_object_count, 1));
    if (use_temp) {
      m = open(name, O_RDWR | O_CREAT | O_EXCL, 0);
    } else {
      /*
       * Using 0 for the mode causes shm_unlink to fail with EACCES on Mac
       * OS X 10.8. As of 10.8, the kernel requires the user to have write
       * permission to successfully shm_unlink.
       */
      m = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IWUSR);
    }
    if (0 <= m) {
      if (use_temp) {
        int rc = unlink(name);
        DCHECK(rc == 0);
      } else {
        int rc = shm_unlink(name);
        DCHECK(rc == 0);
      }
      if (ftruncate(m, length) == -1) {
        close(m);
        m = -1;
      }
      return m;
    }
    if (errno != EEXIST) {
      return -1;
    }
    /* Retry only if we got EEXIST. */
  }
}
#endif

NaClHandle NaClCreateMemoryObject(size_t length, int executable) {
  int fd;

  if (0 == length) {
    return -1;
  }

  if (g_create_memory_object_func != NULL) {
    fd = g_create_memory_object_func(length, executable);
    if (fd >= 0)
      return fd;
  }

#if NACL_ANDROID
  return AshmemCreateRegion(length);
#else
  /*
   * /dev/shm is not always available on Linux.
   * Sometimes it's mounted as noexec.
   * To handle this case, sel_ldr can take a path
   * to tmpfs from the environment.
   */
#if NACL_LINUX && defined(NACL_ENABLE_TMPFS_REDIRECT_VAR)
  if (NACL_ENABLE_TMPFS_REDIRECT_VAR) {
    const char* prefix = getenv(kNaClTempPrefixVar);
    if (prefix != NULL) {
      fd = TryShmOrTempOpen(length, prefix, true);
      if (fd >= 0) {
        return fd;
      }
    }
  }
#endif

  if (NACL_OSX && executable) {
    /*
     * On Mac OS X, shm_open() gives us file descriptors that the OS
     * won't mmap() with PROT_EXEC, which is no good for the dynamic
     * code region, so we must use /tmp instead.
     */
    return TryShmOrTempOpen(length, kShmTempPrefix, true);
  }

  /* Try shm_open(). */
  return TryShmOrTempOpen(length, kShmOpenPrefix, false);
#endif  /* !NACL_ANDROID */
}

void* NaClMap(struct NaClDescEffector* effp,
              void* start, size_t length, int prot, int flags,
              NaClHandle memory, off_t offset) {
  static const int kPosixProt[] = {
    PROT_NONE,
    PROT_READ,
    PROT_WRITE,
    PROT_READ | PROT_WRITE,
    PROT_EXEC,
    PROT_READ | PROT_EXEC,
    PROT_WRITE | PROT_EXEC,
    PROT_READ | PROT_WRITE | PROT_EXEC
  };
  int adjusted = 0;
  UNREFERENCED_PARAMETER(effp);

  if (flags & NACL_MAP_SHARED) {
    adjusted |= MAP_SHARED;
  }
  if (flags & NACL_MAP_PRIVATE) {
    adjusted |= MAP_PRIVATE;
  }
  if (flags & NACL_MAP_FIXED) {
    adjusted |= MAP_FIXED;
  }
  return mmap(start, length, kPosixProt[prot & 7], adjusted, memory, offset);
}

int NaClUnmap(void* start, size_t length) {
  return munmap(start, length);
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stout/none.hpp>
#include <stout/subcommand.hpp>

#include "slave/containerizer/mesos/launch.hpp"
#include "slave/containerizer/mesos/mount.hpp"

using namespace mesos::internal::slave;

int main(int argc, char** argv)
{
  return Subcommand::dispatch(
      None(),
      argc,
      argv,
      new MesosContainerizerLaunch(),
      new MesosContainerizerMount());
}
<commit_msg>Added CNI helper subcommand to `mesos-containerizer`.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stout/none.hpp>
#include <stout/subcommand.hpp>

#include "slave/containerizer/mesos/launch.hpp"
#include "slave/containerizer/mesos/mount.hpp"

#ifdef __linux__
#include "slave/containerizer/mesos/isolators/network/cni/cni.hpp"
#endif

using namespace mesos::internal::slave;

int main(int argc, char** argv)
{
#ifdef __linux__
  return Subcommand::dispatch(
      None(),
      argc,
      argv,
      new MesosContainerizerLaunch(),
      new MesosContainerizerMount(),
      new NetworkCniIsolatorSetup());
#else
  return Subcommand::dispatch(
      None(),
      argc,
      argv,
      new MesosContainerizerLaunch(),
      new MesosContainerizerMount());
#endif
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#if defined(SVG_RENDERER)

// mapnik
#include <mapnik/symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/transform_path_adapter.hpp>
#include <mapnik/svg/output/svg_renderer.hpp>
#include <mapnik/svg/geometry_svg_generator_impl.hpp>
#include <mapnik/svg/output/svg_output_grammars.hpp>
#include <mapnik/svg/output/svg_output_attributes.hpp>
#include <mapnik/symbolizer_dispatch.hpp>
#include <mapnik/vertex_processor.hpp>
#include <mapnik/geometry_transform.hpp>
// boost
#include <boost/spirit/include/karma.hpp>

namespace mapnik { namespace geometry {

template <typename CalculationType>
struct coord_transformer
{
    using calc_type = CalculationType;

    coord_transformer(view_transform const& tr, proj_transform const& prj_trans)
        : tr_(tr), prj_trans_(prj_trans) {}

    template <typename P1, typename P2>
    inline bool apply(P1 const& p1, P2 & p2) const
    {
        using coordinate_type = typename boost::geometry::coordinate_type<P2>::type;
        calc_type x = boost::geometry::get<0>(p1);
        calc_type y = boost::geometry::get<1>(p1);
        calc_type z = 0.0;
        if (!prj_trans_.backward(x, y, z)) return false;
        tr_.forward(&x,&y);
        boost::geometry::set<0>(p2, boost::numeric_cast<coordinate_type>(x));
        boost::geometry::set<1>(p2, boost::numeric_cast<coordinate_type>(y));
        return true;
    }

    view_transform const& tr_;
    proj_transform const& prj_trans_;
};

} // ns geometry

struct symbol_type_dispatch
{
    template <typename Symbolizer>
    bool operator()(Symbolizer const&) const
    {
        return false;
    }
    bool operator()(line_symbolizer const&) const
    {
        return true;
    }
    bool operator()(polygon_symbolizer const&) const
    {
        return true;
    }
};

bool is_path_based(symbolizer const& sym)
{
    return util::apply_visitor(symbol_type_dispatch(), sym);
}

template <typename OutputIterator, typename PathType>
void generate_path_impl(OutputIterator & output_iterator, PathType const& path, svg::path_output_attributes const& path_attributes)
{
    using path_dash_array_grammar = svg::svg_path_dash_array_grammar<OutputIterator>;
    using path_attributes_grammar = svg::svg_path_attributes_grammar<OutputIterator>;
    static const path_attributes_grammar attributes_grammar;
    static const path_dash_array_grammar dash_array_grammar;
    static const svg::svg_path_generator<OutputIterator,PathType> svg_path_grammer;
    boost::spirit::karma::lit_type lit;
    boost::spirit::karma::generate(output_iterator, lit("<path ") << svg_path_grammer, path);
    boost::spirit::karma::generate(output_iterator, lit(" ") << dash_array_grammar, path_attributes.stroke_dasharray());
    boost::spirit::karma::generate(output_iterator, lit(" ") << attributes_grammar << lit("/>\n"), path_attributes);
}

namespace detail {

template <typename OutputIterator>
struct generate_path
{
    generate_path( OutputIterator & out, svg::path_output_attributes const& path_attributes)
        : out_(out),
          path_attributes_(path_attributes) {}

    template <typename Adapter>
    void operator() (Adapter const& adapter) const
    {
        generate_path_impl(out_, adapter, path_attributes_);
    }
    OutputIterator & out_;
    svg::path_output_attributes const& path_attributes_;
};

} // ns detail

template <typename OutputIterator>
bool svg_renderer<OutputIterator>::process(rule::symbolizers const& syms,
                                           mapnik::feature_impl & feature,
                                           proj_transform const& prj_trans)
{
    // svg renderer supports processing of multiple symbolizers.
    using path_type = transform_path_adapter<view_transform, vertex_adapter>;

    bool process_path = false;
    // process each symbolizer to collect its (path) information.
    // path information (attributes from line_ and polygon_ symbolizers)
    // is collected with the path_attributes_ data member.
    for (auto const& sym : syms)
    {
        if (is_path_based(sym))
        {
            process_path = true;
        }
        util::apply_visitor(symbolizer_dispatch<svg_renderer<OutputIterator>>(*this, feature, prj_trans), sym);
    }

    if (process_path)
    {
        // generate path output for each geometry of the current feature.

        // FIXME! needs generic adapter
        //vertex_adapter va(geom);
        //path_type path(common_.t_, va, prj_trans);
        //generate_path(generator_.output_iterator_, path, path_attributes_);
        auto transformed_geom = geometry::transform(feature.get_geometry(), geometry::coord_transformer<double>(common_.t_, prj_trans));
        using vertex_processor_type = geometry::vertex_processor<detail::generate_path<OutputIterator> >;
        detail::generate_path<OutputIterator> apply_generator(generator_.output_iterator_,path_attributes_);
        //mapnik::util::apply_visitor(vertex_processor_type(apply_generator),feature.get_geometry());

        // set the previously collected values back to their defaults
        // for the feature that will be processed next.
        path_attributes_.reset();
    }
    return true;
}

template bool svg_renderer<std::ostream_iterator<char> >::process(rule::symbolizers const& syms,
                                                                  mapnik::feature_impl & feature,
                                                                  proj_transform const& prj_trans);

}

#endif
<commit_msg>use geometry_to_path to convert geometry<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#if defined(SVG_RENDERER)

// mapnik
#include <mapnik/symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/transform_path_adapter.hpp>
#include <mapnik/svg/output/svg_renderer.hpp>
#include <mapnik/svg/geometry_svg_generator_impl.hpp>
#include <mapnik/svg/output/svg_output_grammars.hpp>
#include <mapnik/svg/output/svg_output_attributes.hpp>
#include <mapnik/symbolizer_dispatch.hpp>
#include <mapnik/vertex_processor.hpp>
#include <mapnik/geometry_transform.hpp>
#include <mapnik/geometry_to_path.hpp>
// boost
#include <boost/spirit/include/karma.hpp>

namespace mapnik { namespace geometry {

template <typename CalculationType>
struct coord_transformer
{
    using calc_type = CalculationType;

    coord_transformer(view_transform const& tr, proj_transform const& prj_trans)
        : tr_(tr), prj_trans_(prj_trans) {}

    template <typename P1, typename P2>
    inline bool apply(P1 const& p1, P2 & p2) const
    {
        using coordinate_type = typename boost::geometry::coordinate_type<P2>::type;
        calc_type x = boost::geometry::get<0>(p1);
        calc_type y = boost::geometry::get<1>(p1);
        calc_type z = 0.0;
        if (!prj_trans_.backward(x, y, z)) return false;
        tr_.forward(&x,&y);
        boost::geometry::set<0>(p2, boost::numeric_cast<coordinate_type>(x));
        boost::geometry::set<1>(p2, boost::numeric_cast<coordinate_type>(y));
        return true;
    }

    view_transform const& tr_;
    proj_transform const& prj_trans_;
};

} // ns geometry

struct symbol_type_dispatch
{
    template <typename Symbolizer>
    bool operator()(Symbolizer const&) const
    {
        return false;
    }
    bool operator()(line_symbolizer const&) const
    {
        return true;
    }
    bool operator()(polygon_symbolizer const&) const
    {
        return true;
    }
};

bool is_path_based(symbolizer const& sym)
{
    return util::apply_visitor(symbol_type_dispatch(), sym);
}

template <typename OutputIterator, typename PathType>
void generate_path_impl(OutputIterator & output_iterator, PathType const& path, svg::path_output_attributes const& path_attributes)
{
    using path_dash_array_grammar = svg::svg_path_dash_array_grammar<OutputIterator>;
    using path_attributes_grammar = svg::svg_path_attributes_grammar<OutputIterator>;
    static const path_attributes_grammar attributes_grammar;
    static const path_dash_array_grammar dash_array_grammar;
    static const svg::svg_path_generator<OutputIterator,PathType> svg_path_grammer;
    boost::spirit::karma::lit_type lit;
    boost::spirit::karma::generate(output_iterator, lit("<path ") << svg_path_grammer, path);
    boost::spirit::karma::generate(output_iterator, lit(" ") << dash_array_grammar, path_attributes.stroke_dasharray());
    boost::spirit::karma::generate(output_iterator, lit(" ") << attributes_grammar << lit("/>\n"), path_attributes);
}

template <typename OutputIterator>
bool svg_renderer<OutputIterator>::process(rule::symbolizers const& syms,
                                           mapnik::feature_impl & feature,
                                           proj_transform const& prj_trans)
{
    // svg renderer supports processing of multiple symbolizers.
    using trans_path_type = transform_path_adapter<view_transform, vertex_adapter>;

    bool process_path = false;
    // process each symbolizer to collect its (path) information.
    // path information (attributes from line_ and polygon_ symbolizers)
    // is collected with the path_attributes_ data member.
    for (auto const& sym : syms)
    {
        if (is_path_based(sym))
        {
            process_path = true;
        }
        util::apply_visitor(symbolizer_dispatch<svg_renderer<OutputIterator>>(*this, feature, prj_trans), sym);
    }

    if (process_path)
    {
        // generate path output for each geometry of the current feature.
        path_type path;
        geometry::to_path(feature.get_geometry(), path);
        vertex_adapter va(path);
        trans_path_type trans_path(common_.t_, va, prj_trans);
        generate_path_impl(generator_.output_iterator_, trans_path, path_attributes_);
        // set the previously collected values back to their defaults
        // for the feature that will be processed next.
        path_attributes_.reset();
    }
    return true;
}

template bool svg_renderer<std::ostream_iterator<char> >::process(rule::symbolizers const& syms,
                                                                  mapnik::feature_impl & feature,
                                                                  proj_transform const& prj_trans);

}

#endif
<|endoftext|>


<commit_before>#ifndef __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__
#define __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__

#include <gtest/gtest.h>
#include <test/models/utility.hpp>
#include <stan/mcmc/chains.hpp>
#include <utility>
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/binomial.hpp>

/**
 * Model_Test_Fixture is a test fixture for google test
 * to aid in running models.
 *
 * Derived classes must define:
 *   static std::vector<std::string> get_model_path()
 *   static bool has_data()
 *   - indicates whether the model has data
 */
template <class Derived>
class Model_Test_Fixture : public ::testing::Test {

public:
  static char path_separator;
  static std::string model_path;
  static stan::mcmc::chains<> *chains;
  static size_t num_chains;
  static std::vector<std::string> command_outputs;
  static const size_t skip;
  static size_t iterations;

  /**
   * SetUpTestCase() called by google test once
   * a test case.
   *
   * Sets:
   *  - path_separator: '\' for Windows, '/' for all else.
   *  - base_name:      location of model without ".stan"
   *  - chains:         creates a chains object by reading
   *                    the header of a csv file
   */
  static void SetUpTestCase() {
    model_path = convert_model_path(get_model_path());

    iterations = num_iterations();

    chains = create_chains();
  }

  /**
   * TearDownTestCase() called by google test once
   * a test case.
   *
   * Deletes chains.
   */
  static void TearDownTestCase() {
    delete chains;
  }

  /**
   * Returns the csv file for the chain number.
   *
   * @param chain the chain number
   *
   * @return the file location of the csv file
   */
  static std::string get_csv_file(size_t chain) {
    std::stringstream csv_file;
    csv_file << model_path << "." << chain << ".csv";
    return csv_file.str();
  }

  /**
   * Returns the command to run in a shell on the OS.
   *
   * @param chain the chain number
   *
   * @return a string command that can be run from a shell.
   */
  static std::string get_command(size_t chain) {
    std::stringstream command;
    command << model_path;
    command << " --samples=" << get_csv_file(chain);
    if (has_data()) {
      command << " --data=" << model_path << ".Rdata";
    }
    if (has_init()) {
      command << " --init=" << model_path << "_init.Rdata";
    }
    command << " --iter=" << iterations;
    command << " --refresh=" << iterations;
    return command.str();
  }

  /**
   * Populates the chains object with data from csv files.
   */
  static void default_populate_chains() {
    if (chains->num_kept_samples() == 0U) {
      for (size_t chain = 0U; chain < num_chains; chain++) {
        stan::mcmc::add_chain(*chains, chain, get_csv_file(chain), skip);
      }
    }
  }

  static void populate_chains() {
    Derived::populate_chains();
  }

  static void test_gradient() {
    std::string command = get_command(0U);
    command += " --test_grad";
    std::string command_output;
    EXPECT_NO_THROW(command_output = run_command(command))
      << "Gradient test failed. \n"
      << "\tRan command: " << command << "\n"
      << "\tCommand output: " << command_output;
    //std::cout << "command_output: " << command_output << "\n";
  }

  /**
   * Runs the model num_chains times.
   * Populates the chains object after running the model.
   */
  static void run_model() {
    for (size_t chain = 0; chain < num_chains; chain++) {
      std::string command_output;
      EXPECT_NO_THROW(command_output = run_command(get_command(chain)))
        << "Can not execute command: " << get_command(chain);
      command_outputs.push_back(command_output);
    }
    populate_chains();
  }

  /**
   * Creates a chains object.
   *
   * Runs the model for 0 iterations to read the
   * names and dimensions of the parameters.
   *
   * @return An initialized chains object.
   */
  static stan::mcmc::chains<>* create_chains() {
    std::stringstream command;
    command << get_command(num_chains)
	    << " --iter=0";
    EXPECT_NO_THROW(run_command(command.str()))
      << "Can not build header using: " << command.str();

    std::vector<std::string> names;
    std::vector<std::vector<size_t> > dimss;
    stan::mcmc::read_variables(get_csv_file(num_chains), skip,
                               names, dimss);

    return (new stan::mcmc::chains<>(num_chains, names, dimss));
  }

  /**
   * Return the path to the model (without the extension) as
   * a vector.
   *
   * @return the path to the model
   */
  static std::vector<std::string> get_model_path() {
    return Derived::get_model_path();
  }

  /**
   * Return true if the model has data.
   *
   * @return true if the model has data;
   *         false otherwise.
   */
  static bool has_data() {
    return Derived::has_data();
  }

  /**
   * Return true if the model has an initialization file.
   *
   * @return true if the model has an initialization file;
   *         false otherwise.
   */
  static bool has_init() {
    return Derived::has_init();
  }

  static size_t num_iterations() {
    return Derived::num_iterations();
  }

  static std::vector<std::pair<size_t, double> >
  get_expected_values() {
    return Derived::get_expected_values();
  }

};

template<class Derived>
stan::mcmc::chains<> *Model_Test_Fixture<Derived>::chains;

template<class Derived>
size_t Model_Test_Fixture<Derived>::num_chains = 2;

template<class Derived>
std::string Model_Test_Fixture<Derived>::model_path;

template<class Derived>
std::vector<std::string> Model_Test_Fixture<Derived>::command_outputs;

template<class Derived>
const size_t Model_Test_Fixture<Derived>::skip = 3U;

template<class Derived>
size_t Model_Test_Fixture<Derived>::iterations = 2000U;

TYPED_TEST_CASE_P(Model_Test_Fixture);

TYPED_TEST_P(Model_Test_Fixture, TestGradient) {
  TypeParam::test_gradient();
}

TYPED_TEST_P(Model_Test_Fixture, RunModel) {
  TypeParam::run_model();
}

TYPED_TEST_P(Model_Test_Fixture, ChainsTest) {
  std::vector<std::string> err_message;
  for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
    std::vector<std::pair<std::string, std::string> > options =
      parse_command_output(TypeParam::command_outputs[chain]);
    parse_command_output(TypeParam::command_outputs[chain]);

    std::string msg = "Seed is : ";
    for (size_t option = 0; option < options.size(); option++) {
      if (options[option].first == "seed")
        msg += options[option].second;
    }
    err_message.push_back(msg);
  }

  stan::mcmc::chains<> *c = TypeParam::chains;
  size_t num_chains = c->num_chains();
  size_t num_params = c->num_params();
  for (size_t chain = 0; chain < num_chains; chain++) {
    for (size_t param = 0; param < num_params; param++) {
      EXPECT_GT(c->variance(chain, param), 0)
        << "Chain " << chain << ", param " << param
        << ": variance is 0" << std::endl
        << err_message[chain];
      // made this 1.2 to fail less often
      EXPECT_LT(c->split_potential_scale_reduction(param), 1.2)
	<< "Chain " << chain << ", param " << param
        << ": split r hat > 1.2" << std::endl
        << err_message[chain];
    }
  }
}

TYPED_TEST_P(Model_Test_Fixture, ExpectedValuesTest) {
  using std::vector;
  using std::pair;
  using std::sqrt;
  using std::fabs;
  using std::setw;

  using boost::math::students_t;
  using boost::math::binomial;
  using boost::math::quantile;

  vector<pair<size_t, double> > expected_values = TypeParam::get_expected_values();
  size_t n = expected_values.size();
  if (n == 0)
    return;

  stan::mcmc::chains<> *c = TypeParam::chains;
  double alpha = 0.005;
  if (n < 3)
    alpha = 0.001;

  int failed = 0;
  std::stringstream err_message;
  for (size_t i = 0; i < n; i++) {
    size_t index = expected_values[i].first;
    double expected_mean = expected_values[i].second;

    double neff = c->effective_sample_size(index);
    double sample_mean = c->mean(index);
    double se = c->sd(index) / sqrt(neff);
    double z = quantile(students_t(neff-1.0), 1 - alpha/2.0);

    // that 2.0 is there to make the test fail less often.
    if (fabs(expected_mean - sample_mean) > z*se * 2.0) {
      failed++;
      // want the error message to have which, what, how
      err_message << "parameter index: " << index
                  << "\n\texpected:    " << setw(10) << expected_mean
                  << "\n\tsampled:     " << setw(10) << sample_mean
		  << "\n\tsd:          " << setw(10) << c->sd(index)
                  << "\n\tneff:        " << setw(10) << neff
                  << "\n\tsplit R.hat: " << setw(10) << c->split_potential_scale_reduction(index)
                  << "\n\tz:           " << setw(10) << z
                  << "\n\tse:          " << setw(10) << se
                  << "\n\n\tfabs(diff) > z * se: "
                  << fabs(expected_mean - sample_mean) << " > " << z*se << "\n\n";
    }
  }

  if (failed == 0)
    return;

  double p = 1 - cdf(binomial(n, alpha), failed);
  // this test should fail less than 0.01% of the time.
  // (if all the parameters are failing independently... ha)
  if (p < 0.0001) {
    err_message << "------------------------------------------------------------\n";
    for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
      std::vector<std::pair<std::string, std::string> > options =
        parse_command_output(TypeParam::command_outputs[chain]);

      for (size_t option = 0; option < options.size(); option++) {
        if (options[option].first == "seed")
          err_message << "seed: " << options[option].second << std::endl;
      }
    }

    EXPECT_EQ(0, failed)
      << "Failed " << failed << " of " << expected_values.size() << " comparisons\n"
      << "p: " << p << std::endl
      << "------------------------------------------------------------\n"
      << err_message.str() << std::endl
      << "------------------------------------------------------------\n";

  }
}

REGISTER_TYPED_TEST_CASE_P(Model_Test_Fixture,
                           TestGradient,
                           RunModel,
                           ChainsTest,
                           ExpectedValuesTest);

#endif
<commit_msg>model-tests: should fail less<commit_after>#ifndef __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__
#define __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__

#include <gtest/gtest.h>
#include <test/models/utility.hpp>
#include <stan/mcmc/chains.hpp>
#include <utility>
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/binomial.hpp>

/**
 * Model_Test_Fixture is a test fixture for google test
 * to aid in running models.
 *
 * Derived classes must define:
 *   static std::vector<std::string> get_model_path()
 *   static bool has_data()
 *   - indicates whether the model has data
 */
template <class Derived>
class Model_Test_Fixture : public ::testing::Test {

public:
  static char path_separator;
  static std::string model_path;
  static stan::mcmc::chains<> *chains;
  static size_t num_chains;
  static std::vector<std::string> command_outputs;
  static const size_t skip;
  static size_t iterations;

  /**
   * SetUpTestCase() called by google test once
   * a test case.
   *
   * Sets:
   *  - path_separator: '\' for Windows, '/' for all else.
   *  - base_name:      location of model without ".stan"
   *  - chains:         creates a chains object by reading
   *                    the header of a csv file
   */
  static void SetUpTestCase() {
    model_path = convert_model_path(get_model_path());

    iterations = num_iterations();

    chains = create_chains();
  }

  /**
   * TearDownTestCase() called by google test once
   * a test case.
   *
   * Deletes chains.
   */
  static void TearDownTestCase() {
    delete chains;
  }

  /**
   * Returns the csv file for the chain number.
   *
   * @param chain the chain number
   *
   * @return the file location of the csv file
   */
  static std::string get_csv_file(size_t chain) {
    std::stringstream csv_file;
    csv_file << model_path << "." << chain << ".csv";
    return csv_file.str();
  }

  /**
   * Returns the command to run in a shell on the OS.
   *
   * @param chain the chain number
   *
   * @return a string command that can be run from a shell.
   */
  static std::string get_command(size_t chain) {
    std::stringstream command;
    command << model_path;
    command << " --samples=" << get_csv_file(chain);
    if (has_data()) {
      command << " --data=" << model_path << ".Rdata";
    }
    if (has_init()) {
      command << " --init=" << model_path << "_init.Rdata";
    }
    command << " --iter=" << iterations;
    command << " --refresh=" << iterations;
    return command.str();
  }

  /**
   * Populates the chains object with data from csv files.
   */
  static void default_populate_chains() {
    if (chains->num_kept_samples() == 0U) {
      for (size_t chain = 0U; chain < num_chains; chain++) {
        stan::mcmc::add_chain(*chains, chain, get_csv_file(chain), skip);
      }
    }
  }

  static void populate_chains() {
    Derived::populate_chains();
  }

  static void test_gradient() {
    std::string command = get_command(0U);
    command += " --test_grad";
    std::string command_output;
    EXPECT_NO_THROW(command_output = run_command(command))
      << "Gradient test failed. \n"
      << "\tRan command: " << command << "\n"
      << "\tCommand output: " << command_output;
    //std::cout << "command_output: " << command_output << "\n";
  }

  /**
   * Runs the model num_chains times.
   * Populates the chains object after running the model.
   */
  static void run_model() {
    for (size_t chain = 0; chain < num_chains; chain++) {
      std::string command_output;
      EXPECT_NO_THROW(command_output = run_command(get_command(chain)))
        << "Can not execute command: " << get_command(chain);
      command_outputs.push_back(command_output);
    }
    populate_chains();
  }

  /**
   * Creates a chains object.
   *
   * Runs the model for 0 iterations to read the
   * names and dimensions of the parameters.
   *
   * @return An initialized chains object.
   */
  static stan::mcmc::chains<>* create_chains() {
    std::stringstream command;
    command << get_command(num_chains)
	    << " --iter=0";
    EXPECT_NO_THROW(run_command(command.str()))
      << "Can not build header using: " << command.str();

    std::vector<std::string> names;
    std::vector<std::vector<size_t> > dimss;
    stan::mcmc::read_variables(get_csv_file(num_chains), skip,
                               names, dimss);

    return (new stan::mcmc::chains<>(num_chains, names, dimss));
  }

  /**
   * Return the path to the model (without the extension) as
   * a vector.
   *
   * @return the path to the model
   */
  static std::vector<std::string> get_model_path() {
    return Derived::get_model_path();
  }

  /**
   * Return true if the model has data.
   *
   * @return true if the model has data;
   *         false otherwise.
   */
  static bool has_data() {
    return Derived::has_data();
  }

  /**
   * Return true if the model has an initialization file.
   *
   * @return true if the model has an initialization file;
   *         false otherwise.
   */
  static bool has_init() {
    return Derived::has_init();
  }

  static size_t num_iterations() {
    return Derived::num_iterations();
  }

  static std::vector<std::pair<size_t, double> >
  get_expected_values() {
    return Derived::get_expected_values();
  }

};

template<class Derived>
stan::mcmc::chains<> *Model_Test_Fixture<Derived>::chains;

template<class Derived>
size_t Model_Test_Fixture<Derived>::num_chains = 2;

template<class Derived>
std::string Model_Test_Fixture<Derived>::model_path;

template<class Derived>
std::vector<std::string> Model_Test_Fixture<Derived>::command_outputs;

template<class Derived>
const size_t Model_Test_Fixture<Derived>::skip = 3U;

template<class Derived>
size_t Model_Test_Fixture<Derived>::iterations = 2000U;

TYPED_TEST_CASE_P(Model_Test_Fixture);

TYPED_TEST_P(Model_Test_Fixture, TestGradient) {
  TypeParam::test_gradient();
}

TYPED_TEST_P(Model_Test_Fixture, RunModel) {
  TypeParam::run_model();
}

TYPED_TEST_P(Model_Test_Fixture, ChainsTest) {
  std::vector<std::string> err_message;
  for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
    std::vector<std::pair<std::string, std::string> > options =
      parse_command_output(TypeParam::command_outputs[chain]);
    parse_command_output(TypeParam::command_outputs[chain]);

    std::string msg = "Seed is : ";
    for (size_t option = 0; option < options.size(); option++) {
      if (options[option].first == "seed")
        msg += options[option].second;
    }
    err_message.push_back(msg);
  }

  stan::mcmc::chains<> *c = TypeParam::chains;
  size_t num_chains = c->num_chains();
  size_t num_params = c->num_params();
  for (size_t chain = 0; chain < num_chains; chain++) {
    for (size_t param = 0; param < num_params; param++) {
      EXPECT_GT(c->variance(chain, param), 0)
        << "Chain " << chain << ", param " << param
        << ": variance is 0" << std::endl
        << err_message[chain];
      // made this 1.2 to fail less often
      EXPECT_LT(c->split_potential_scale_reduction(param), 1.2)
	<< "Chain " << chain << ", param " << param
        << ": split r hat > 1.2" << std::endl
        << err_message[chain];
    }
  }
}

TYPED_TEST_P(Model_Test_Fixture, ExpectedValuesTest) {
  using std::vector;
  using std::pair;
  using std::sqrt;
  using std::fabs;
  using std::setw;

  using boost::math::students_t;
  using boost::math::binomial;
  using boost::math::quantile;

  vector<pair<size_t, double> > expected_values = TypeParam::get_expected_values();
  size_t n = expected_values.size();
  if (n == 0)
    return;

  stan::mcmc::chains<> *c = TypeParam::chains;
  double alpha = 0.01;
  if (n < 3)
    alpha = 0.0001;

  int failed = 0;
  std::stringstream err_message;
  for (size_t i = 0; i < n; i++) {
    size_t index = expected_values[i].first;
    double expected_mean = expected_values[i].second;

    double neff = c->effective_sample_size(index);
    double sample_mean = c->mean(index);
    double se = c->sd(index) / sqrt(neff);
    double z = quantile(students_t(neff-1.0), 1 - alpha/2.0);

    // that 2.0 is there to make the test fail less often.
    if (fabs(expected_mean - sample_mean) > z*se * 2.0) {
      failed++;
      // want the error message to have which, what, how
      err_message << "parameter index: " << index
                  << "\n\texpected:    " << setw(10) << expected_mean
                  << "\n\tsampled:     " << setw(10) << sample_mean
		  << "\n\tsd:          " << setw(10) << c->sd(index)
                  << "\n\tneff:        " << setw(10) << neff
                  << "\n\tsplit R.hat: " << setw(10) << c->split_potential_scale_reduction(index)
                  << "\n\tz:           " << setw(10) << z
                  << "\n\tse:          " << setw(10) << se
                  << "\n\n\tfabs(diff) > z * se: "
                  << fabs(expected_mean - sample_mean) << " > " << z*se << "\n\n";
    }
  }

  if (failed == 0)
    return;

  double p = 1 - cdf(binomial(n, alpha), failed);
  // this test should fail less than 0.01% of the time.
  // (if all the parameters are failing independently... ha)
  if (p < 0.0001) {
    err_message << "------------------------------------------------------------\n";
    for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
      std::vector<std::pair<std::string, std::string> > options =
        parse_command_output(TypeParam::command_outputs[chain]);

      for (size_t option = 0; option < options.size(); option++) {
        if (options[option].first == "seed")
          err_message << "seed: " << options[option].second << std::endl;
      }
    }

    EXPECT_EQ(0, failed)
      << "Failed " << failed << " of " << expected_values.size() << " comparisons\n"
      << "p: " << p << std::endl
      << "------------------------------------------------------------\n"
      << err_message.str() << std::endl
      << "------------------------------------------------------------\n";

  }
}

REGISTER_TYPED_TEST_CASE_P(Model_Test_Fixture,
                           TestGradient,
                           RunModel,
                           ChainsTest,
                           ExpectedValuesTest);

#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE gaussian_quadratures_test

// Standard includes
#include <fstream>

// Third party includes
#include <boost/test/unit_test.hpp>

// Local VOTCA includes
#include "votca/xtp/quadrature_factory.h"

// VOTCA includes
#include <votca/tools/eigenio_matrixmarket.h>

using namespace votca::xtp;
using namespace votca;

// defines a Gaussian as integration test
// result should by ~sqrt(pi)
class FunctionEvaluation {
 public:
  FunctionEvaluation(){};

  double operator()(Index j, double point, bool symmetry) const {
    double factor;
    if (j < 100) {
      if (symmetry) {
        factor = 2.0;
      } else {
        factor = 1.0;
      }
    }

    return factor * exp(-std::pow(point, 2));
  }
};

BOOST_AUTO_TEST_SUITE(gaussian_quadratures_test)

BOOST_AUTO_TEST_CASE(gauss_legendre) {

  QuadratureFactory::RegisterAll();
  std::unique_ptr<GaussianQuadratureBase> _gq =
      std::unique_ptr<GaussianQuadratureBase>(Quadratures().Create("legendre"));

  std::vector<int> orders{8, 10, 12, 14, 16, 18, 20, 40, 100};
  FunctionEvaluation f = FunctionEvaluation();

  Eigen::VectorXd integrals(9);
  for (Index i = 0; i < 9; i++) {
    _gq->configure(orders[i]);
    integrals(i) = _gq->Integrate(f);
  }

  Eigen::VectorXd integrals_ref =
      votca::tools::EigenIO_MatrixMarket::ReadVector(
          std::string(XTP_TEST_DATA_FOLDER) +
          "/gaussian_quadratures/gauss_legendre.mm");

  bool check_integral = integrals.isApprox(integrals_ref, 1e-10);
  if (!check_integral) {
    std::cout << "Gauss-Legendre" << std::endl;
    std::cout << integrals << std::endl;
    std::cout << "Gauss-Legendre ref" << std::endl;
    std::cout << integrals_ref << std::endl;
  }
  BOOST_CHECK_EQUAL(check_integral, true);
}

BOOST_AUTO_TEST_CASE(gauss_laguerre) {

  QuadratureFactory::RegisterAll();
  std::unique_ptr<GaussianQuadratureBase> _gq =
      std::unique_ptr<GaussianQuadratureBase>(Quadratures().Create("laguerre"));
  std::vector<int> orders{8, 10, 12, 14, 16, 18, 20, 40, 100};
  FunctionEvaluation f = FunctionEvaluation();

  Eigen::VectorXd integrals(9);
  for (Index i = 0; i < 9; i++) {
    _gq->configure(orders[i]);
    integrals(i) = _gq->Integrate(f);
  }

  Eigen::VectorXd integrals_ref =
      votca::tools::EigenIO_MatrixMarket::ReadVector(
          std::string(XTP_TEST_DATA_FOLDER) +
          "/gaussian_quadratures/gauss_laguerre.mm");

  bool check_integral = integrals.isApprox(integrals_ref, 1e-10);
  if (!check_integral) {
    std::cout << "Gauss-Laguerre" << std::endl;
    std::cout << integrals << std::endl;
    std::cout << "Gauss-Laguerre ref" << std::endl;
    std::cout << integrals_ref << std::endl;
  }
  BOOST_CHECK_EQUAL(check_integral, true);
}

BOOST_AUTO_TEST_CASE(gauss_hermite) {

  QuadratureFactory::RegisterAll();
  std::unique_ptr<GaussianQuadratureBase> _gq =
      std::unique_ptr<GaussianQuadratureBase>(Quadratures().Create("hermite"));
  std::vector<int> orders{8, 10, 12, 14, 16, 18, 20, 40, 100};
  FunctionEvaluation f = FunctionEvaluation();

  Eigen::VectorXd integrals(9);
  for (Index i = 0; i < 9; i++) {
    _gq->configure(orders[i]);
    integrals(i) = _gq->Integrate(f);
  }

  Eigen::VectorXd integrals_ref =
      votca::tools::EigenIO_MatrixMarket::ReadVector(
          std::string(XTP_TEST_DATA_FOLDER) +
          "/gaussian_quadratures/gauss_hermite.mm");

  bool check_integral = integrals.isApprox(integrals_ref, 1e-10);
  if (!check_integral) {
    std::cout << "Gauss-Hermite" << std::endl;
    std::cout << integrals << std::endl;
    std::cout << "Gauss-Hermite ref" << std::endl;
    std::cout << integrals_ref << std::endl;
  }
  BOOST_CHECK_EQUAL(check_integral, true);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>possible unassiged variable warning<commit_after>/*
 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE gaussian_quadratures_test

// Standard includes
#include <fstream>

// Third party includes
#include <boost/test/unit_test.hpp>

// Local VOTCA includes
#include "votca/xtp/quadrature_factory.h"

// VOTCA includes
#include <votca/tools/eigenio_matrixmarket.h>

using namespace votca::xtp;
using namespace votca;

// defines a Gaussian as integration test
// result should by ~sqrt(pi)
class FunctionEvaluation {
 public:
  FunctionEvaluation(){};

  double operator()(Index j, double point, bool symmetry) const {
    double factor = 0.0;
    // this is only here to staisfy the unused variable warning
    if (j < 100) {
      if (symmetry) {
        factor = 2.0;
      } else {
        factor = 1.0;
      }
    }

    return factor * exp(-std::pow(point, 2));
  }
};

BOOST_AUTO_TEST_SUITE(gaussian_quadratures_test)

BOOST_AUTO_TEST_CASE(gauss_legendre) {

  QuadratureFactory::RegisterAll();
  std::unique_ptr<GaussianQuadratureBase> _gq =
      std::unique_ptr<GaussianQuadratureBase>(Quadratures().Create("legendre"));

  std::vector<int> orders{8, 10, 12, 14, 16, 18, 20, 40, 100};
  FunctionEvaluation f = FunctionEvaluation();

  Eigen::VectorXd integrals(9);
  for (Index i = 0; i < 9; i++) {
    _gq->configure(orders[i]);
    integrals(i) = _gq->Integrate(f);
  }

  Eigen::VectorXd integrals_ref =
      votca::tools::EigenIO_MatrixMarket::ReadVector(
          std::string(XTP_TEST_DATA_FOLDER) +
          "/gaussian_quadratures/gauss_legendre.mm");

  bool check_integral = integrals.isApprox(integrals_ref, 1e-10);
  if (!check_integral) {
    std::cout << "Gauss-Legendre" << std::endl;
    std::cout << integrals << std::endl;
    std::cout << "Gauss-Legendre ref" << std::endl;
    std::cout << integrals_ref << std::endl;
  }
  BOOST_CHECK_EQUAL(check_integral, true);
}

BOOST_AUTO_TEST_CASE(gauss_laguerre) {

  QuadratureFactory::RegisterAll();
  std::unique_ptr<GaussianQuadratureBase> _gq =
      std::unique_ptr<GaussianQuadratureBase>(Quadratures().Create("laguerre"));
  std::vector<int> orders{8, 10, 12, 14, 16, 18, 20, 40, 100};
  FunctionEvaluation f = FunctionEvaluation();

  Eigen::VectorXd integrals(9);
  for (Index i = 0; i < 9; i++) {
    _gq->configure(orders[i]);
    integrals(i) = _gq->Integrate(f);
  }

  Eigen::VectorXd integrals_ref =
      votca::tools::EigenIO_MatrixMarket::ReadVector(
          std::string(XTP_TEST_DATA_FOLDER) +
          "/gaussian_quadratures/gauss_laguerre.mm");

  bool check_integral = integrals.isApprox(integrals_ref, 1e-10);
  if (!check_integral) {
    std::cout << "Gauss-Laguerre" << std::endl;
    std::cout << integrals << std::endl;
    std::cout << "Gauss-Laguerre ref" << std::endl;
    std::cout << integrals_ref << std::endl;
  }
  BOOST_CHECK_EQUAL(check_integral, true);
}

BOOST_AUTO_TEST_CASE(gauss_hermite) {

  QuadratureFactory::RegisterAll();
  std::unique_ptr<GaussianQuadratureBase> _gq =
      std::unique_ptr<GaussianQuadratureBase>(Quadratures().Create("hermite"));
  std::vector<int> orders{8, 10, 12, 14, 16, 18, 20, 40, 100};
  FunctionEvaluation f = FunctionEvaluation();

  Eigen::VectorXd integrals(9);
  for (Index i = 0; i < 9; i++) {
    _gq->configure(orders[i]);
    integrals(i) = _gq->Integrate(f);
  }

  Eigen::VectorXd integrals_ref =
      votca::tools::EigenIO_MatrixMarket::ReadVector(
          std::string(XTP_TEST_DATA_FOLDER) +
          "/gaussian_quadratures/gauss_hermite.mm");

  bool check_integral = integrals.isApprox(integrals_ref, 1e-10);
  if (!check_integral) {
    std::cout << "Gauss-Hermite" << std::endl;
    std::cout << integrals << std::endl;
    std::cout << "Gauss-Hermite ref" << std::endl;
    std::cout << integrals_ref << std::endl;
  }
  BOOST_CHECK_EQUAL(check_integral, true);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/* dlvhex -- Answer-Set Programming with external interfaces.
 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer
 *
 * This file is part of dlvhex.
 *
 * dlvhex is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * dlvhex is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with dlvhex; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */

/**
 * @file ASPsolverTest.cpp
 * @author Roman Schindlauer
 * @date Thu Jun 30 12:39:40 2005
 *
 * @brief Testsuite class for testing the ASP solver class.
 *
 *
 *
 */

#include "testsuite/dlvhex/ASPsolverTest.h"

#include "dlvhex/Error.h"
#include "dlvhex/globals.h"
#include "dlvhex/DLVProcess.h"
#include "dlvhex/Program.h"
#include "dlvhex/ASPSolver.h"

DLVHEX_NAMESPACE_BEGIN

// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION(ASPsolverTest);

void
ASPsolverTest::setUp()
{
    Globals::Instance()->setOption("NoPredicate", 0);
}

void
ASPsolverTest::tearDown()
{
}

void
ASPsolverTest::testResult()
{
    DLVProcess dlv;

    std::vector<AtomSet> answersets;
    std::vector<AtomSet>::const_iterator as;

    std::auto_ptr<BaseASPSolver> solver(dlv.createSolver());

    //
    // empty model: { a :- b }
    //
    Program idb2;
    AtomSet edb2;
    RuleHead_t h2;
    RuleBody_t b2;
    h2.insert(AtomPtr(new Atom(Tuple(1, Term("a")))));
    b2.insert(new Literal(AtomPtr(new Atom(Tuple(1, Term("b"))))));
    Rule* r2 = new Rule(h2, b2);
    idb2.addRule(r2);
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb2, edb2, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 0);
    answersets.clear();

    //
    // no model: { a, -a }
    //
    Program idb1;
    AtomSet edb1;
    Tuple t1;
    edb1.insert(AtomPtr(new Atom(Tuple(1, Term("a")))));
    edb1.insert(AtomPtr(new Atom(Tuple(1, Term("a")), true)));
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb1, edb1, answersets));
    CPPUNIT_ASSERT(answersets.size() == 0);
    answersets.clear();

    //
    // single model: { b, a :- b }
    //
    edb2.insert(AtomPtr(new Atom(Tuple(1, Term("b")))));
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb2, edb2, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 1);
    answersets.clear();

    //
    // two models: { p(X) :- not q(X), s(X); q(X) :- not p(X), s(X); s(a) }
    //
    Program idb3;
    AtomSet edb3;
    RuleHead_t h31;
    RuleHead_t h32;
    RuleBody_t b31;
    RuleBody_t b32;
    Tuple t31;
    t31.push_back(Term("p"));
    t31.push_back(Term("X"));
    Tuple t32;
    t32.push_back(Term("q"));
    t32.push_back(Term("X"));
    h31.insert(AtomPtr(new Atom(t31)));
    h32.insert(AtomPtr(new Atom(t32)));
    Tuple t33;
    t33.push_back(Term("s"));
    t33.push_back(Term("X"));
    b31.insert(new Literal(AtomPtr(new Atom(t32)), true));
    b31.insert(new Literal(AtomPtr(new Atom(t33))));
    b32.insert(new Literal(AtomPtr(new Atom(t31)), true));
    b32.insert(new Literal(AtomPtr(new Atom(t33))));
    Rule* r31 = new Rule(h31, b31);
    Rule* r32 = new Rule(h32, b32);
    idb3.addRule(r31);
    idb3.addRule(r32);
    Tuple t34;
    t34.push_back(Term("s"));
    t34.push_back(Term("a"));
    edb3.insert(AtomPtr(new Atom(t34)));
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb3, edb3, answersets));
    CPPUNIT_ASSERT(answersets.size() == 2);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 1);
    ++as;
    CPPUNIT_ASSERT(as->size() == 1);
    answersets.clear();

    //
    // single fact program
    //
    Program idb4;
    AtomSet edb4;
    Tuple t4;
    t4.push_back(Term("b"));
    edb4.insert(AtomPtr(new Atom(t4)));

    // b should not be in the result then!
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb4, edb4, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 0);
    answersets.clear();

}

DLVHEX_NAMESPACE_END

// Local Variables:
// mode: C++
// End:
<commit_msg>Add test for ASP solver with list of options.<commit_after>/* dlvhex -- Answer-Set Programming with external interfaces.
 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer
 *
 * This file is part of dlvhex.
 *
 * dlvhex is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * dlvhex is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with dlvhex; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA.
 */

/**
 * @file ASPsolverTest.cpp
 * @author Roman Schindlauer
 * @date Thu Jun 30 12:39:40 2005
 *
 * @brief Testsuite class for testing the ASP solver class.
 *
 *
 *
 */

#include "testsuite/dlvhex/ASPsolverTest.h"

#include "dlvhex/Error.h"
#include "dlvhex/globals.h"
#include "dlvhex/DLVProcess.h"
#include "dlvhex/Program.h"
#include "dlvhex/ASPSolver.h"
#include "dlvhex/PrintVisitor.h"
#include "dlvhex/DLVresultParserDriver.h"

DLVHEX_NAMESPACE_BEGIN

// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION(ASPsolverTest);

void
ASPsolverTest::setUp()
{
    Globals::Instance()->setOption("NoPredicate", 0);
}

void
ASPsolverTest::tearDown()
{
}

void
ASPsolverTest::testResult()
{
    DLVProcess dlv;

    std::vector<AtomSet> answersets;
    std::vector<AtomSet>::const_iterator as;

    std::auto_ptr<BaseASPSolver> solver(dlv.createSolver());

    //
    // empty model: { a :- b }
    //
    Program idb2;
    AtomSet edb2;
    RuleHead_t h2;
    RuleBody_t b2;
    h2.insert(AtomPtr(new Atom(Tuple(1, Term("a")))));
    b2.insert(new Literal(AtomPtr(new Atom(Tuple(1, Term("b"))))));
    Rule* r2 = new Rule(h2, b2);
    idb2.addRule(r2);
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb2, edb2, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 0);
    answersets.clear();

    //
    // no model: { a, -a }
    //
    Program idb1;
    AtomSet edb1;
    Tuple t1;
    edb1.insert(AtomPtr(new Atom(Tuple(1, Term("a")))));
    edb1.insert(AtomPtr(new Atom(Tuple(1, Term("a")), true)));
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb1, edb1, answersets));
    CPPUNIT_ASSERT(answersets.size() == 0);
    answersets.clear();

    //
    // single model: { b, a :- b }
    //
    edb2.insert(AtomPtr(new Atom(Tuple(1, Term("b")))));
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb2, edb2, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 1);
    answersets.clear();

    //
    // two models: { p(X) :- not q(X), s(X); q(X) :- not p(X), s(X); s(a) }
    //
    Program idb3;
    AtomSet edb3;
    RuleHead_t h31;
    RuleHead_t h32;
    RuleBody_t b31;
    RuleBody_t b32;
    Tuple t31;
    t31.push_back(Term("p"));
    t31.push_back(Term("X"));
    Tuple t32;
    t32.push_back(Term("q"));
    t32.push_back(Term("X"));
    h31.insert(AtomPtr(new Atom(t31)));
    h32.insert(AtomPtr(new Atom(t32)));
    Tuple t33;
    t33.push_back(Term("s"));
    t33.push_back(Term("X"));
    b31.insert(new Literal(AtomPtr(new Atom(t32)), true));
    b31.insert(new Literal(AtomPtr(new Atom(t33))));
    b32.insert(new Literal(AtomPtr(new Atom(t31)), true));
    b32.insert(new Literal(AtomPtr(new Atom(t33))));
    Rule* r31 = new Rule(h31, b31);
    Rule* r32 = new Rule(h32, b32);
    idb3.addRule(r31);
    idb3.addRule(r32);
    Tuple t34;
    t34.push_back(Term("s"));
    t34.push_back(Term("a"));
    edb3.insert(AtomPtr(new Atom(t34)));
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb3, edb3, answersets));
    CPPUNIT_ASSERT(answersets.size() == 2);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 1);
    ++as;
    CPPUNIT_ASSERT(as->size() == 1);
    answersets.clear();

    //
    // single fact program
    //
    Program idb4;
    AtomSet edb4;
    Tuple t4;
    t4.push_back(Term("b"));
    edb4.insert(AtomPtr(new Atom(t4)));

    // b should not be in the result then!
    CPPUNIT_ASSERT_NO_THROW(solver->solve(idb4, edb4, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 0);
    answersets.clear();

    //
    // empty program using hardcoded program options
    //
    std::vector<std::string> opt;
    opt.push_back("-silent");
    opt.push_back("/dev/null");

    ASPSolver<DLVPrintVisitor,DLVresultParserDriver> mysolver(dlv);
    CPPUNIT_ASSERT_NO_THROW(mysolver.solve(opt, answersets));
    CPPUNIT_ASSERT(answersets.size() == 1);
    as = answersets.begin();
    CPPUNIT_ASSERT(as->size() == 0);
    answersets.clear();
}

DLVHEX_NAMESPACE_END

// Local Variables:
// mode: C++
// End:
<|endoftext|>