<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2006-2012 ARM Limited
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "rtos/Thread.h"

#include "mbed.h"
#include "rtos/rtos_idle.h"
#include "mbed_assert.h"

#define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) +  ((align) - (pos) % (align)) : (pos))
MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error");
MBED_STATIC_ASSERT(ALIGN_UP(1, 8) == 8, "ALIGN_UP macro error");

#define ALIGN_DOWN(pos, align) ((pos) - ((pos) % (align)))
MBED_STATIC_ASSERT(ALIGN_DOWN(7, 8) == 0, "ALIGN_DOWN macro error");
MBED_STATIC_ASSERT(ALIGN_DOWN(8, 8) == 8, "ALIGN_DOWN macro error");

static void (*terminate_hook)(osThreadId_t id) = 0;
extern "C" void thread_terminate_hook(osThreadId_t id)
{
    if (terminate_hook != (void (*)(osThreadId_t))NULL) {
        terminate_hook(id);
    }
}

namespace rtos {

void Thread::constructor(osPriority priority,
        uint32_t stack_size, unsigned char *stack_mem, const char *name) {

    const uintptr_t unaligned_mem = reinterpret_cast<uintptr_t>(stack_mem);
    const uintptr_t aligned_mem = ALIGN_UP(unaligned_mem, 8);
    const uint32_t offset = aligned_mem - unaligned_mem;
    const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8);

    _tid = 0;
    _dynamic_stack = (stack_mem == NULL);
    _finished = false;
    memset(&_obj_mem, 0, sizeof(_obj_mem));
    memset(&_attr, 0, sizeof(_attr));
    _attr.priority = priority;
    _attr.stack_size = aligned_size;
    _attr.name = name ? name : "application_unnamed_thread";
    _attr.stack_mem = reinterpret_cast<uint32_t*>(aligned_mem);
}

void Thread::constructor(Callback<void()> task,
        osPriority priority, uint32_t stack_size, unsigned char *stack_mem, const char *name) {
    constructor(priority, stack_size, stack_mem, name);

    switch (start(task)) {
        case osErrorResource:
            error("OS ran out of threads!\n");
            break;
        case osErrorParameter:
            error("Thread already running!\n");
            break;
        case osErrorNoMemory:
            error("Error allocating the stack memory\n");
        default:
            break;
    }
}

osStatus Thread::start(Callback<void()> task) {
    _mutex.lock();

    if ((_tid != 0) || _finished) {
        _mutex.unlock();
        return osErrorParameter;
    }

    if (_attr.stack_mem == NULL) {
        _attr.stack_mem = new uint32_t[_attr.stack_size/sizeof(uint32_t)];
        MBED_ASSERT(_attr.stack_mem != NULL);
    }

    //Fill the stack with a magic word for maximum usage checking
    for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) {
        ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5;
    }

    memset(&_obj_mem, 0, sizeof(_obj_mem));
    _attr.cb_size = sizeof(_obj_mem);
    _attr.cb_mem = &_obj_mem;
    _task = task;
    _tid = osThreadNew(Thread::_thunk, this, &_attr);
    if (_tid == NULL) {
        if (_dynamic_stack) {
            delete[] (uint32_t *)(_attr.stack_mem);
            _attr.stack_mem = (uint32_t*)NULL;
        }
        _mutex.unlock();
        _join_sem.release();
        return osErrorResource;
    }

    _mutex.unlock();
    return osOK;
}

osStatus Thread::terminate() {
    osStatus_t ret = osOK;
    _mutex.lock();

    // Set the Thread's tid to NULL and
    // release the semaphore before terminating
    // since this thread could be terminating itself
    osThreadId_t local_id = _tid;
    _join_sem.release();
    _tid = (osThreadId_t)NULL;
    if (!_finished) {
        _finished = true;
        // if local_id == 0 Thread was not started in first place
        // and does not have to be terminated
        if(local_id != 0) {
            ret = osThreadTerminate(local_id);
        }
    }
    _mutex.unlock();
    return ret;
}

osStatus Thread::join() {
    int32_t ret = _join_sem.wait();
    if (ret < 0) {
        return osError;
    }

    // The semaphore has been released so this thread is being
    // terminated or has been terminated. Once the mutex has
    // been locked it is ensured that the thread is deleted.
    _mutex.lock();
    MBED_ASSERT(NULL == _tid);
    _mutex.unlock();

    // Release sem so any other threads joining this thread wake up
    _join_sem.release();
    return osOK;
}

osStatus Thread::set_priority(osPriority priority) {
    osStatus_t ret;
    _mutex.lock();

    ret = osThreadSetPriority(_tid, priority);

    _mutex.unlock();
    return ret;
}

osPriority Thread::get_priority() {
    osPriority_t ret;
    _mutex.lock();

    ret = osThreadGetPriority(_tid);

    _mutex.unlock();
    return ret;
}

int32_t Thread::signal_set(int32_t flags) {
    return osThreadFlagsSet(_tid, flags);
}

Thread::State Thread::get_state() {
    uint8_t state = osThreadTerminated;

    _mutex.lock();

    if (_tid != NULL) {
#if defined(MBED_OS_BACKEND_RTX5)
        state = _obj_mem.state;
#else
        state = osThreadGetState(_tid);
#endif
    }

    _mutex.unlock();

    State user_state;

    switch(state) {
        case osThreadInactive:
            user_state = Inactive;
            break;
        case osThreadReady:
            user_state = Ready;
            break;
        case osThreadRunning:
            user_state = Running;
            break;
#if defined(MBED_OS_BACKEND_RTX5)
        case osRtxThreadWaitingDelay:
            user_state = WaitingDelay;
            break;
        case osRtxThreadWaitingJoin:
            user_state = WaitingJoin;
            break;
        case osRtxThreadWaitingThreadFlags:
            user_state = WaitingThreadFlag;
            break;
        case osRtxThreadWaitingEventFlags:
            user_state = WaitingEventFlag;
            break;
        case osRtxThreadWaitingMutex:
            user_state = WaitingMutex;
            break;
        case osRtxThreadWaitingSemaphore:
            user_state = WaitingSemaphore;
            break;
        case osRtxThreadWaitingMemoryPool:
            user_state = WaitingMemoryPool;
            break;
        case osRtxThreadWaitingMessageGet:
            user_state = WaitingMessageGet;
            break;
        case osRtxThreadWaitingMessagePut:
            user_state = WaitingMessagePut;
            break;
#endif
        case osThreadTerminated:
        default:
            user_state = Deleted;
            break;
    }

    return user_state;
}

uint32_t Thread::stack_size() {
    uint32_t size = 0;
    _mutex.lock();

    if (_tid != NULL) {
        size = osThreadGetStackSize(_tid);
    }

    _mutex.unlock();
    return size;
}

uint32_t Thread::free_stack() {
    uint32_t size = 0;
    _mutex.lock();

#if defined(MBED_OS_BACKEND_RTX5)
    if (_tid != NULL) {
        os_thread_t *thread = (os_thread_t *)_tid;
        size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem;
    }
#endif

    _mutex.unlock();
    return size;
}

uint32_t Thread::used_stack() {
    uint32_t size = 0;
    _mutex.lock();

#if defined(MBED_OS_BACKEND_RTX5)
    if (_tid != NULL) {
        os_thread_t *thread = (os_thread_t *)_tid;
        size = ((uint32_t)thread->stack_mem + thread->stack_size) - thread->sp;
    }
#endif

    _mutex.unlock();
    return size;
}

uint32_t Thread::max_stack() {
    uint32_t size = 0;
    _mutex.lock();

    if (_tid != NULL) {
#if defined(MBED_OS_BACKEND_RTX5)
        os_thread_t *thread = (os_thread_t *)_tid;
        uint32_t high_mark = 0;
        while (((uint32_t *)(thread->stack_mem))[high_mark] == 0xE25A2EA5)
            high_mark++;
        size = thread->stack_size - (high_mark * sizeof(uint32_t));
#else
        size = osThreadGetStackSize(_tid) - osThreadGetStackSpace(_tid);
#endif
    }

    _mutex.unlock();
    return size;
}

const char *Thread::get_name() {
    return _attr.name;
}

int32_t Thread::signal_clr(int32_t flags) {
    return osThreadFlagsClear(flags);
}

osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
    uint32_t res;
    osEvent evt;
    uint32_t options = osFlagsWaitAll;
    if (signals == 0) {
        options = osFlagsWaitAny;
        signals = 0x7FFFFFFF;
    }
    res = osThreadFlagsWait(signals, options, millisec);
    if (res & osFlagsError) {
        switch (res) {
            case osFlagsErrorISR:
                evt.status = osErrorISR;
                break;
            case osFlagsErrorResource:
                evt.status = osOK;
                break;
            case osFlagsErrorTimeout:
                evt.status = (osStatus)osEventTimeout;
                break;
            case osFlagsErrorParameter:
            default:
                evt.status = (osStatus)osErrorValue;
                break;
        }
    } else {
        evt.status = (osStatus)osEventSignal;
        evt.value.signals = res;
    }

    return evt;
}

osStatus Thread::wait(uint32_t millisec) {
    return osDelay(millisec);
}

osStatus Thread::yield() {
    return osThreadYield();
}

osThreadId Thread::gettid() {
    return osThreadGetId();
}

void Thread::attach_idle_hook(void (*fptr)(void)) {
    rtos_attach_idle_hook(fptr);
}

void Thread::attach_terminate_hook(void (*fptr)(osThreadId_t id)) {
    terminate_hook = fptr;
}

Thread::~Thread() {
    // terminate is thread safe
    terminate();
    if (_dynamic_stack) {
        delete[] (uint32_t*)(_attr.stack_mem);
        _attr.stack_mem = (uint32_t*)NULL;
    }
}

void Thread::_thunk(void * thread_ptr)
{
    Thread *t = (Thread*)thread_ptr;
    t->_task();
    t->_mutex.lock();
    t->_tid = (osThreadId)NULL;
    t->_finished = true;
    t->_join_sem.release();
    // rtos will release the mutex automatically
}

}
<commit_msg>Fixed whitespace<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2006-2012 ARM Limited
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "rtos/Thread.h"

#include "mbed.h"
#include "rtos/rtos_idle.h"
#include "mbed_assert.h"

#define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) +  ((align) - (pos) % (align)) : (pos))
MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error");
MBED_STATIC_ASSERT(ALIGN_UP(1, 8) == 8, "ALIGN_UP macro error");

#define ALIGN_DOWN(pos, align) ((pos) - ((pos) % (align)))
MBED_STATIC_ASSERT(ALIGN_DOWN(7, 8) == 0, "ALIGN_DOWN macro error");
MBED_STATIC_ASSERT(ALIGN_DOWN(8, 8) == 8, "ALIGN_DOWN macro error");

static void (*terminate_hook)(osThreadId_t id) = 0;
extern "C" void thread_terminate_hook(osThreadId_t id)
{
    if (terminate_hook != (void (*)(osThreadId_t))NULL) {
        terminate_hook(id);
    }
}

namespace rtos {

void Thread::constructor(osPriority priority,
        uint32_t stack_size, unsigned char *stack_mem, const char *name) {

    const uintptr_t unaligned_mem = reinterpret_cast<uintptr_t>(stack_mem);
    const uintptr_t aligned_mem = ALIGN_UP(unaligned_mem, 8);
    const uint32_t offset = aligned_mem - unaligned_mem;
    const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8);

    _tid = 0;
    _dynamic_stack = (stack_mem == NULL);
    _finished = false;
    memset(&_obj_mem, 0, sizeof(_obj_mem));
    memset(&_attr, 0, sizeof(_attr));
    _attr.priority = priority;
    _attr.stack_size = aligned_size;
    _attr.name = name ? name : "application_unnamed_thread";
    _attr.stack_mem = reinterpret_cast<uint32_t*>(aligned_mem);
}

void Thread::constructor(Callback<void()> task,
        osPriority priority, uint32_t stack_size, unsigned char *stack_mem, const char *name) {
    constructor(priority, stack_size, stack_mem, name);

    switch (start(task)) {
        case osErrorResource:
            error("OS ran out of threads!\n");
            break;
        case osErrorParameter:
            error("Thread already running!\n");
            break;
        case osErrorNoMemory:
            error("Error allocating the stack memory\n");
        default:
            break;
    }
}

osStatus Thread::start(Callback<void()> task) {
    _mutex.lock();

    if ((_tid != 0) || _finished) {
        _mutex.unlock();
        return osErrorParameter;
    }

    if (_attr.stack_mem == NULL) {
        _attr.stack_mem = new uint32_t[_attr.stack_size/sizeof(uint32_t)];
        MBED_ASSERT(_attr.stack_mem != NULL);
    }

    //Fill the stack with a magic word for maximum usage checking
    for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) {
        ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5;
    }

    memset(&_obj_mem, 0, sizeof(_obj_mem));
    _attr.cb_size = sizeof(_obj_mem);
    _attr.cb_mem = &_obj_mem;
    _task = task;
    _tid = osThreadNew(Thread::_thunk, this, &_attr);
    if (_tid == NULL) {
        if (_dynamic_stack) {
            delete[] (uint32_t *)(_attr.stack_mem);
            _attr.stack_mem = (uint32_t*)NULL;
        }
        _mutex.unlock();
        _join_sem.release();
        return osErrorResource;
    }

    _mutex.unlock();
    return osOK;
}

osStatus Thread::terminate() {
    osStatus_t ret = osOK;
    _mutex.lock();

    // Set the Thread's tid to NULL and
    // release the semaphore before terminating
    // since this thread could be terminating itself
    osThreadId_t local_id = _tid;
    _join_sem.release();
    _tid = (osThreadId_t)NULL;
    if (!_finished) {
        _finished = true;
        // if local_id == 0 Thread was not started in first place
        // and does not have to be terminated
        if (local_id != 0) {
            ret = osThreadTerminate(local_id);
        }
    }
    _mutex.unlock();
    return ret;
}

osStatus Thread::join() {
    int32_t ret = _join_sem.wait();
    if (ret < 0) {
        return osError;
    }

    // The semaphore has been released so this thread is being
    // terminated or has been terminated. Once the mutex has
    // been locked it is ensured that the thread is deleted.
    _mutex.lock();
    MBED_ASSERT(NULL == _tid);
    _mutex.unlock();

    // Release sem so any other threads joining this thread wake up
    _join_sem.release();
    return osOK;
}

osStatus Thread::set_priority(osPriority priority) {
    osStatus_t ret;
    _mutex.lock();

    ret = osThreadSetPriority(_tid, priority);

    _mutex.unlock();
    return ret;
}

osPriority Thread::get_priority() {
    osPriority_t ret;
    _mutex.lock();

    ret = osThreadGetPriority(_tid);

    _mutex.unlock();
    return ret;
}

int32_t Thread::signal_set(int32_t flags) {
    return osThreadFlagsSet(_tid, flags);
}

Thread::State Thread::get_state() {
    uint8_t state = osThreadTerminated;

    _mutex.lock();

    if (_tid != NULL) {
#if defined(MBED_OS_BACKEND_RTX5)
        state = _obj_mem.state;
#else
        state = osThreadGetState(_tid);
#endif
    }

    _mutex.unlock();

    State user_state;

    switch(state) {
        case osThreadInactive:
            user_state = Inactive;
            break;
        case osThreadReady:
            user_state = Ready;
            break;
        case osThreadRunning:
            user_state = Running;
            break;
#if defined(MBED_OS_BACKEND_RTX5)
        case osRtxThreadWaitingDelay:
            user_state = WaitingDelay;
            break;
        case osRtxThreadWaitingJoin:
            user_state = WaitingJoin;
            break;
        case osRtxThreadWaitingThreadFlags:
            user_state = WaitingThreadFlag;
            break;
        case osRtxThreadWaitingEventFlags:
            user_state = WaitingEventFlag;
            break;
        case osRtxThreadWaitingMutex:
            user_state = WaitingMutex;
            break;
        case osRtxThreadWaitingSemaphore:
            user_state = WaitingSemaphore;
            break;
        case osRtxThreadWaitingMemoryPool:
            user_state = WaitingMemoryPool;
            break;
        case osRtxThreadWaitingMessageGet:
            user_state = WaitingMessageGet;
            break;
        case osRtxThreadWaitingMessagePut:
            user_state = WaitingMessagePut;
            break;
#endif
        case osThreadTerminated:
        default:
            user_state = Deleted;
            break;
    }

    return user_state;
}

uint32_t Thread::stack_size() {
    uint32_t size = 0;
    _mutex.lock();

    if (_tid != NULL) {
        size = osThreadGetStackSize(_tid);
    }

    _mutex.unlock();
    return size;
}

uint32_t Thread::free_stack() {
    uint32_t size = 0;
    _mutex.lock();

#if defined(MBED_OS_BACKEND_RTX5)
    if (_tid != NULL) {
        os_thread_t *thread = (os_thread_t *)_tid;
        size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem;
    }
#endif

    _mutex.unlock();
    return size;
}

uint32_t Thread::used_stack() {
    uint32_t size = 0;
    _mutex.lock();

#if defined(MBED_OS_BACKEND_RTX5)
    if (_tid != NULL) {
        os_thread_t *thread = (os_thread_t *)_tid;
        size = ((uint32_t)thread->stack_mem + thread->stack_size) - thread->sp;
    }
#endif

    _mutex.unlock();
    return size;
}

uint32_t Thread::max_stack() {
    uint32_t size = 0;
    _mutex.lock();

    if (_tid != NULL) {
#if defined(MBED_OS_BACKEND_RTX5)
        os_thread_t *thread = (os_thread_t *)_tid;
        uint32_t high_mark = 0;
        while (((uint32_t *)(thread->stack_mem))[high_mark] == 0xE25A2EA5)
            high_mark++;
        size = thread->stack_size - (high_mark * sizeof(uint32_t));
#else
        size = osThreadGetStackSize(_tid) - osThreadGetStackSpace(_tid);
#endif
    }

    _mutex.unlock();
    return size;
}

const char *Thread::get_name() {
    return _attr.name;
}

int32_t Thread::signal_clr(int32_t flags) {
    return osThreadFlagsClear(flags);
}

osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
    uint32_t res;
    osEvent evt;
    uint32_t options = osFlagsWaitAll;
    if (signals == 0) {
        options = osFlagsWaitAny;
        signals = 0x7FFFFFFF;
    }
    res = osThreadFlagsWait(signals, options, millisec);
    if (res & osFlagsError) {
        switch (res) {
            case osFlagsErrorISR:
                evt.status = osErrorISR;
                break;
            case osFlagsErrorResource:
                evt.status = osOK;
                break;
            case osFlagsErrorTimeout:
                evt.status = (osStatus)osEventTimeout;
                break;
            case osFlagsErrorParameter:
            default:
                evt.status = (osStatus)osErrorValue;
                break;
        }
    } else {
        evt.status = (osStatus)osEventSignal;
        evt.value.signals = res;
    }

    return evt;
}

osStatus Thread::wait(uint32_t millisec) {
    return osDelay(millisec);
}

osStatus Thread::yield() {
    return osThreadYield();
}

osThreadId Thread::gettid() {
    return osThreadGetId();
}

void Thread::attach_idle_hook(void (*fptr)(void)) {
    rtos_attach_idle_hook(fptr);
}

void Thread::attach_terminate_hook(void (*fptr)(osThreadId_t id)) {
    terminate_hook = fptr;
}

Thread::~Thread() {
    // terminate is thread safe
    terminate();
    if (_dynamic_stack) {
        delete[] (uint32_t*)(_attr.stack_mem);
        _attr.stack_mem = (uint32_t*)NULL;
    }
}

void Thread::_thunk(void * thread_ptr)
{
    Thread *t = (Thread*)thread_ptr;
    t->_task();
    t->_mutex.lock();
    t->_tid = (osThreadId)NULL;
    t->_finished = true;
    t->_join_sem.release();
    // rtos will release the mutex automatically
}

}
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 */

#include <gtest/gtest.h>

#include <sys/stat.h>
#include <unistd.h>

#include "../../cvmfs/catalog.h"
#include "../../cvmfs/catalog_mgr.h"
#include "../../cvmfs/catalog_rw.h"
#include "../../cvmfs/hash.h"
#include "../../cvmfs/shortstring.h"
#include "../../cvmfs/util.h"
#include "testutil.h"

using namespace std;  // NOLINT

namespace catalog {

class T_CatalogManager : public ::testing::Test {
 protected:
  void SetUp() {
    catalog_mgr_ = new MockCatalogManager(&statistics_);
    catalog_mgr_->Init();
  }

  void TearDown() {
    delete catalog_mgr_;
  }

 private:
  MockCatalogManager *catalog_mgr_;
  perf::Statistics statistics_;
};

TEST_F(T_CatalogManager, ) {

}

}
<commit_msg>TEST: Added LoopUp text to t_catalog_mgr.cc<commit_after>/**
 * This file is part of the CernVM File System.
 */

#include <gtest/gtest.h>

#include <sys/stat.h>
#include <unistd.h>

#include "../../cvmfs/catalog.h"
#include "../../cvmfs/catalog_mgr.h"
#include "../../cvmfs/hash.h"
#include "../../cvmfs/shortstring.h"
#include "../../cvmfs/util.h"
#include "testutil.h"

using namespace std;  // NOLINT

namespace catalog {

class T_CatalogManager : public ::testing::Test {
 protected:
  void SetUp() {
    catalog_mgr_ = new MockCatalogManager(&statistics_);
  }

  void TearDown() {
    delete catalog_mgr_;
  }

  void AddTree() {
    const shash::Any empty_hash = shash::Any();
    const int size = 32;
    const size_t file_size = 4096;
    const char suffix = shash::kSha1;
    ASSERT_TRUE(catalog_mgr_->Init());
    shash::Any hash;
    shash::Any empty_content;
    // adding ""
    MockCatalog *root_catalog = catalog_mgr_->RetrieveRootCatalog();
    root_catalog->AddFile(empty_content, file_size, "", "");
    // adding "/dir"
    root_catalog->AddFile(empty_content, file_size, "", "dir");
    // adding "/file1"
    hash = shash::Any(shash::kSha1,
                      reinterpret_cast<const unsigned char*>(hashes[1]),
                      size, suffix);
    root_catalog->AddFile(hash, file_size, "", "file1");
    // adding "/dir/dir"
    root_catalog->AddFile(empty_content, file_size, "/dir", "dir");
    // adding "/dir/dir/file2"
    hash = shash::Any(shash::kSha1,
                      reinterpret_cast<const unsigned char*>(hashes[1]),
                      size, suffix);
    root_catalog->AddFile(hash, file_size, "/dir/dir", "file1");
    // adding "/dir/dir/dir"
    root_catalog->AddFile(empty_content, file_size, "/dir/dir", "dir");
    // adding a nested catalog in "/dir/dir/dir"
    string catalog_path_str = "/dir/dir/dir";
    PathString catalog_path(catalog_path_str.c_str(),
                            catalog_path_str.length());
    MockCatalog *new_catalog = catalog_mgr_->CreateCatalog(
        catalog_path, shash::Any(), root_catalog);
    ASSERT_NE(static_cast<MockCatalog*>(NULL), new_catalog);
    ASSERT_EQ(1u, root_catalog->GetChildren().size());
    // adding "/dir/dir/dir/file3" to the new nested catalog
    hash = shash::Any(shash::kSha1,
                          reinterpret_cast<const unsigned char*>(hashes[2]),
                          size, suffix);
    new_catalog->AddFile(hash, file_size, "/dir/dir/dir", "file3");
    // adding "/dir/dir/dir/file4" to the new nested catalog
    hash = shash::Any(shash::kSha1,
                          reinterpret_cast<const unsigned char*>(hashes[3]),
                          size, suffix);
    new_catalog->AddFile(hash, file_size, "/dir/dir/dir", "file4");
    // detach the recently created catalog
    catalog_mgr_->DetachNested();
    ASSERT_EQ(0u, root_catalog->GetChildren().size());
    ASSERT_EQ(1, catalog_mgr_->GetNumCatalogs());
  }

 protected:
  const static char *hashes[];
  MockCatalogManager *catalog_mgr_;
  perf::Statistics statistics_;
};

const char *T_CatalogManager::hashes[] = {
     "b026324c6904b2a9cb4b88d6d61c81d1000000",
     "26ab0db90d72e28ad0ba1e22ee510510000000",
     "6d7fce9fee471194aa8b5b6e47267f03000000",
     "48a24b70a0b376535542b996af517398000000",
     "1dcca23355272056f04fe8bf20edfce0000000"
};

TEST_F(T_CatalogManager, InitialConfiguration) {
  EXPECT_TRUE(catalog_mgr_->Init());
  EXPECT_EQ(1, catalog_mgr_->GetNumCatalogs());
  EXPECT_EQ(1u, catalog_mgr_->GetRevision());
  EXPECT_FALSE(catalog_mgr_->GetVolatileFlag());
  EXPECT_EQ(0u, catalog_mgr_->GetTTL());
}

TEST_F(T_CatalogManager, Statistics) {
  EXPECT_TRUE(catalog_mgr_->Init());
  Statistics st = catalog_mgr_->statistics();
  EXPECT_EQ(0u, st.n_listing->Get());
  EXPECT_EQ(0u, st.n_lookup_inode->Get());
  EXPECT_EQ(0u, st.n_lookup_path->Get());
  EXPECT_EQ(0u, st.n_lookup_path_negative->Get());
  EXPECT_EQ(0u, st.n_lookup_xattrs->Get());
  EXPECT_EQ(0u, st.n_nested_listing->Get());
}

TEST_F(T_CatalogManager, InodeConfiguration) {
  InodeGenerationAnnotation annotation;
  catalog_mgr_->SetInodeAnnotation(&annotation);
  EXPECT_TRUE(catalog_mgr_->Init());
}

TEST_F(T_CatalogManager, Lookup) {
  AddTree();
  catalog::DirectoryEntry dirent;
  LookupOptions option = kLookupSole;
  EXPECT_TRUE(catalog_mgr_->LookupPath("/dir", option, &dirent));
}

TEST_F(T_CatalogManager, Remount) {
  EXPECT_TRUE(catalog_mgr_->Init());
  EXPECT_EQ(kLoadNew, catalog_mgr_->Remount(true));
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef ROSETTASTONE_TRIGGER_ENUMS_HPP
#define ROSETTASTONE_TRIGGER_ENUMS_HPP

namespace RosettaStone
{
//! \brief An enumerator for identifying trigger type.
enum class TriggerType
{
    NONE,        //!< The effect has nothing.
    TURN_START,  //!< The effect will be triggered at the start of turn.
    TURN_END,    //!< The effect will be triggered at the end of turn.
    HEAL,        //!< The effect will be triggered when characters are healed.
};

//! \brief An enumerator for identifying trigger source.
enum class TriggerSource
{
    NONE,
    ALL_MINIONS,
};

//! \brief An enumerator for identifying sequence type.
enum class SequenceType
{
    NONE,
};
}  // namespace RosettaStone

#endif  // ROSETTASTONE_TRIGGER_ENUMS_HPP
<commit_msg>feat(card-impl): Add 'ATTACK' to enum 'TriggerType'<commit_after>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#ifndef ROSETTASTONE_TRIGGER_ENUMS_HPP
#define ROSETTASTONE_TRIGGER_ENUMS_HPP

namespace RosettaStone
{
//! \brief An enumerator for identifying trigger type.
enum class TriggerType
{
    NONE,        //!< The effect has nothing.
    TURN_START,  //!< The effect will be triggered at the start of turn.
    TURN_END,    //!< The effect will be triggered at the end of turn.
    HEAL,        //!< The effect will be triggered when characters are healed.
    ATTACK,      //!< The effect will be triggered when characters attack.
};

//! \brief An enumerator for identifying trigger source.
enum class TriggerSource
{
    NONE,
    HERO,
    ALL_MINIONS,
};

//! \brief An enumerator for identifying sequence type.
enum class SequenceType
{
    NONE,
};
}  // namespace RosettaStone

#endif  // ROSETTASTONE_TRIGGER_ENUMS_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander All developers are free to add the calls needed to export their modules

#include "HOOMDMath.h"
#include "ExecutionConfiguration.h"
#include "ClockSource.h"
#include "Profiler.h"
#include "ParticleData.h"
#include "SystemDefinition.h"
#include "BondedGroupData.h"
#include "Initializers.h"
#include "GetarInitializer.h"
#include "GSDReader.h"
#include "Compute.h"
#include "ComputeThermo.h"
#include "CellList.h"
#include "CellListStencil.h"
#include "ForceCompute.h"
#include "ForceConstraint.h"
#include "ConstForceCompute.h"
#include "Analyzer.h"
#include "IMDInterface.h"
#include "DCDDumpWriter.h"
#include "GetarDumpWriter.h"
#include "GSDDumpWriter.h"
#include "Logger.h"
#include "LogPlainTXT.h"
#include "LogMatrix.h"
#include "LogHDF5.h"
#include "CallbackAnalyzer.h"
#include "Updater.h"
#include "Integrator.h"
#include "SFCPackUpdater.h"
#include "BoxResizeUpdater.h"
#include "System.h"
#include "Variant.h"
#include "Messenger.h"
#include "SnapshotSystemData.h"

// include GPU classes
#ifdef ENABLE_CUDA
#include <cuda.h>
#include "CellListGPU.h"
#include "ComputeThermoGPU.h"
#include "SFCPackUpdaterGPU.h"

#include <cuda_profiler_api.h>
#endif

// include MPI classes
#ifdef ENABLE_MPI
#include "Communicator.h"
#include "DomainDecomposition.h"
#include "LoadBalancer.h"

#ifdef ENABLE_CUDA
#include "CommunicatorGPU.h"
#include "LoadBalancerGPU.h"
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

#include "SignalHandler.h"

#include "HOOMDVersion.h"
#include "hoomd/extern/num_util.h"

#include <hoomd/extern/pybind/include/pybind11/pybind11.h>
#include <hoomd/extern/pybind/include/pybind11/stl_bind.h>

#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;

/*! \file hoomd_module.cc
    \brief Brings all of the export_* functions together to export the hoomd python module
*/

/* numpy is terrible (see /opt/local/Library/Frameworks/Python.framework/Versions/2.7/
lib/python2.7/site-packages/numpy/core/generate_numpy_array.py)
The following #defines help get around this
*/

#if PY_VERSION_HEX >= 0x03000000
#define MY_PY_VER_3x
#else
#define MY_PY_VER_2x
#endif

#ifdef MY_PY_VER_3x
void *my_import_array()
    {
    import_array();
    return NULL;
    }
#endif
#ifdef MY_PY_VER_2x
void my_import_array()
    {
    import_array();
    }
#endif

//! Method for getting the current version of HOOMD
/*! \returns Current HOOMD version identification string
*/
string get_hoomd_version()
    {
    ostringstream ver;
    // always outputting main version number: #402
    ver << "HOOMD-blue " << HOOMD_VERSION << endl;

    return ver.str();
    }

//! Layer for omp_get_num_procs()
int get_num_procs()
    {
    return 1;
    }

//! Get the hoomd version as a tuple
pybind11::object get_hoomd_version_tuple()
    {
    return pybind11::make_tuple(HOOMD_VERSION_MAJOR, HOOMD_VERSION_MINOR, HOOMD_VERSION_PATCH);
    }

//! Get the CUDA version as a tuple
pybind11::object get_cuda_version_tuple()
    {
    #ifdef ENABLE_CUDA
    int major = CUDA_VERSION / 1000;
    int minor = CUDA_VERSION / 10 % 100;
    return pybind11::make_tuple(major, minor);
    #else
    return pybind11::make_tuple(0,0);
    #endif
    }

//! Get the compiler version
string get_compiler_version()
    {
    #if defined(__GNUC__) && !(defined(__clang__) || defined(__INTEL_COMPILER))
    ostringstream o;
    o << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." <<  __GNUC_PATCHLEVEL__;
    return o.str();

    #elif defined(__clang__)
    ostringstream o;
    o << "clang " << __clang_major__ << "." << __clang_minor__ << "." <<  __clang_patchlevel__;
    return o.str();

    #elif defined(__INTEL_COMPILER)
    ostringstream o;
    o << "icc " << __INTEL_COMPILER;
    return o.str();

    #else
    return string("unknown");

    #endif
    }

//! Determine availability of MPI support
bool is_MPI_available()
   {
   return
#ifdef ENABLE_MPI
       true;
#else
       false;
#endif
    }

void mpi_barrier_world()
    {
    #ifdef ENABLE_MPI
    MPI_Barrier(MPI_COMM_WORLD);
    #endif
    }

//! Start the CUDA profiler
void cuda_profile_start()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStart();
    #endif
    }

//! Stop the CUDA profiler
void cuda_profile_stop()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStop();
    #endif
    }

// values used in measuring hoomd launch timing
unsigned int hoomd_launch_time, hoomd_start_time, hoomd_mpi_init_time;
bool hoomd_launch_timing=false;

#ifdef ENABLE_MPI
//! Environment variables needed for setting up MPI
char env_enable_mpi_cuda[] = "MV2_USE_CUDA=1";

//! Initialize the MPI environment
void initialize_mpi()
    {
    #ifdef ENABLE_MPI_CUDA
    // if we are using an MPI-CUDA implementation, enable this feature
    // before the MPI_Init
    putenv(env_enable_mpi_cuda);
    #endif

    // benchmark hoomd launch times
    if (getenv("HOOMD_LAUNCH_TIME"))
        {
        // get the time that mpirun was called
        hoomd_launch_time = atoi(getenv("HOOMD_LAUNCH_TIME"));

        // compute the number of seconds to get here
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_start_time = t.tv_sec - hoomd_launch_time;
        hoomd_launch_timing = true;
        }

    // initalize MPI
    MPI_Init(0, (char ***) NULL);

    if (hoomd_launch_timing)
        {
        // compute the number of seconds to get past mpi_init
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_mpi_init_time = t.tv_sec - hoomd_launch_time;
        }
    }

//! Get the processor name associated to this rank
string get_mpi_proc_name()
    {
    char proc_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(proc_name, &name_len);
    return string(proc_name);
    }

//! Finalize MPI environment
void finalize_mpi()
    {
    MPI_Finalize();
    }
#endif

//! Abort MPI runs
void abort_mpi(std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    if(exec_conf->getNRanksGlobal() > 1)
        {
        MPI_Abort(exec_conf->getMPICommunicator(), MPI_ERR_OTHER);
        }
    #endif
    }

//! broadcast string from root rank to all other ranks
std::string mpi_bcast_str(const std::string& s, std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    std::string result = s;
    bcast(result, 0, exec_conf->getMPICommunicator());
    return result;
    #else
    return s;
    #endif
    }

//! Create the python module
/*! each class setup their own python exports in a function export_ClassName
    create the hoomd python module and define the exports here.
*/
PYBIND11_PLUGIN(_hoomd)
    {
    pybind11::module m("_hoomd");

    #ifdef ENABLE_MPI
    // initialize MPI early
    initialize_mpi();

    // register clean-up function
    Py_AtExit(finalize_mpi);
    m.def("get_mpi_proc_name", get_mpi_proc_name);
    #endif

    // setup needed for numpy
    my_import_array();

    m.def("abort_mpi", abort_mpi);
    m.def("mpi_barrier_world", mpi_barrier_world);
    m.def("mpi_bcast_str", mpi_bcast_str);

    m.def("hoomd_compile_flags", &hoomd_compile_flags);
    m.def("output_version_info", &output_version_info);
    m.def("get_hoomd_version", &get_hoomd_version);

    m.def("get_num_procs", &get_num_procs);
    m.attr("__version__") = get_hoomd_version_tuple();
    m.attr("__git_sha1__") = pybind11::str(HOOMD_GIT_SHA1);
    m.attr("__git_refspec__") = pybind11::str(HOOMD_GIT_REFSPEC);
    m.attr("__cuda_version__") = get_cuda_version_tuple();
    m.attr("__compiler_version__") = pybind11::str(get_compiler_version());

    m.def("is_MPI_available", &is_MPI_available);

    m.def("cuda_profile_start", &cuda_profile_start);
    m.def("cuda_profile_stop", &cuda_profile_stop);

    pybind11::bind_vector<Scalar>(m,"std_vector_scalar");
    pybind11::bind_vector<string>(m,"std_vector_string");
    pybind11::bind_vector<unsigned int>(m,"std_vector_uint");
    pybind11::bind_vector<int>(m,"std_vector_int");
    pybind11::bind_vector<Scalar3>(m,"std_vector_scalar3");
    pybind11::bind_vector<Scalar4>(m,"std_vector_scalar4");

    InstallSIGINTHandler();

    // utils
    export_hoomd_math_functions(m);
    export_ClockSource(m);
    export_Profiler(m);

    // data structures
    export_BoxDim(m);
    export_ParticleData(m);
    export_SnapshotParticleData(m);
    export_ExecutionConfiguration(m);
    export_SystemDefinition(m);
    export_SnapshotSystemData(m);
    export_BondedGroupData<BondData,Bond>(m,"BondData","BondDataSnapshot");
    export_BondedGroupData<AngleData,Angle>(m,"AngleData","AngleDataSnapshot");
    export_BondedGroupData<DihedralData,Dihedral>(m,"DihedralData","DihedralDataSnapshot");
    export_BondedGroupData<ImproperData,Dihedral>(m,"ImproperData","ImproperDataSnapshot",false);
    export_BondedGroupData<ConstraintData,Constraint>(m,"ConstraintData","ConstraintDataSnapshot");
    export_BondedGroupData<PairData,Bond>(m,"PairData","PairDataSnapshot",false);

    // initializers
    export_GSDReader(m);
    getardump::export_GetarInitializer(m);

    // computes
    export_Compute(m);
    export_ComputeThermo(m);
    export_CellList(m);
    export_CellListStencil(m);
    export_ForceCompute(m);
    export_ForceConstraint(m);
    export_ConstForceCompute(m);

#ifdef ENABLE_CUDA
    export_CellListGPU(m);
    export_ComputeThermoGPU(m);
#endif

    // analyzers
    export_Analyzer(m);
    export_IMDInterface(m);
    export_DCDDumpWriter(m);
    getardump::export_GetarDumpWriter(m);
    export_GSDDumpWriter(m);
    export_Logger(m);
    export_LogPlainTXT(m);
    export_LogMatrix(m);
    export_LogHDF5(m);
    export_CallbackAnalyzer(m);
    export_ParticleGroup(m);

    // updaters
    export_Updater(m);
    export_Integrator(m);
    export_BoxResizeUpdater(m);
    export_SFCPackUpdater(m);
#ifdef ENABLE_CUDA
    export_SFCPackUpdaterGPU(m);
#endif

#ifdef ENABLE_MPI
    export_Communicator(m);
    export_DomainDecomposition(m);
    export_LoadBalancer(m);
#ifdef ENABLE_CUDA
    export_CommunicatorGPU(m);
    export_LoadBalancerGPU(m);
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

    // system
    export_System(m);

    // variant
    export_Variant(m);

    // messenger
    export_Messenger(m);

    return m.ptr();
    }
<commit_msg>Validate pybind11 version<commit_after>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander All developers are free to add the calls needed to export their modules

#include "HOOMDMath.h"
#include "ExecutionConfiguration.h"
#include "ClockSource.h"
#include "Profiler.h"
#include "ParticleData.h"
#include "SystemDefinition.h"
#include "BondedGroupData.h"
#include "Initializers.h"
#include "GetarInitializer.h"
#include "GSDReader.h"
#include "Compute.h"
#include "ComputeThermo.h"
#include "CellList.h"
#include "CellListStencil.h"
#include "ForceCompute.h"
#include "ForceConstraint.h"
#include "ConstForceCompute.h"
#include "Analyzer.h"
#include "IMDInterface.h"
#include "DCDDumpWriter.h"
#include "GetarDumpWriter.h"
#include "GSDDumpWriter.h"
#include "Logger.h"
#include "LogPlainTXT.h"
#include "LogMatrix.h"
#include "LogHDF5.h"
#include "CallbackAnalyzer.h"
#include "Updater.h"
#include "Integrator.h"
#include "SFCPackUpdater.h"
#include "BoxResizeUpdater.h"
#include "System.h"
#include "Variant.h"
#include "Messenger.h"
#include "SnapshotSystemData.h"

// include GPU classes
#ifdef ENABLE_CUDA
#include <cuda.h>
#include "CellListGPU.h"
#include "ComputeThermoGPU.h"
#include "SFCPackUpdaterGPU.h"

#include <cuda_profiler_api.h>
#endif

// include MPI classes
#ifdef ENABLE_MPI
#include "Communicator.h"
#include "DomainDecomposition.h"
#include "LoadBalancer.h"

#ifdef ENABLE_CUDA
#include "CommunicatorGPU.h"
#include "LoadBalancerGPU.h"
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

#include "SignalHandler.h"

#include "HOOMDVersion.h"
#include "hoomd/extern/num_util.h"

#include <hoomd/extern/pybind/include/pybind11/pybind11.h>
#include <hoomd/extern/pybind/include/pybind11/stl_bind.h>

#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;

/*! \file hoomd_module.cc
    \brief Brings all of the export_* functions together to export the hoomd python module
*/

/* numpy is terrible (see /opt/local/Library/Frameworks/Python.framework/Versions/2.7/
lib/python2.7/site-packages/numpy/core/generate_numpy_array.py)
The following #defines help get around this
*/

#if (PYBIND11_VERSION_MAJOR) != 1 || (PYBIND11_VERSION_MINOR) != 8
#error HOOMD-blue requires pybind11 1.8.x
#endif

#if PY_VERSION_HEX >= 0x03000000
#define MY_PY_VER_3x
#else
#define MY_PY_VER_2x
#endif

#ifdef MY_PY_VER_3x
void *my_import_array()
    {
    import_array();
    return NULL;
    }
#endif
#ifdef MY_PY_VER_2x
void my_import_array()
    {
    import_array();
    }
#endif

//! Method for getting the current version of HOOMD
/*! \returns Current HOOMD version identification string
*/
string get_hoomd_version()
    {
    ostringstream ver;
    // always outputting main version number: #402
    ver << "HOOMD-blue " << HOOMD_VERSION << endl;

    return ver.str();
    }

//! Layer for omp_get_num_procs()
int get_num_procs()
    {
    return 1;
    }

//! Get the hoomd version as a tuple
pybind11::object get_hoomd_version_tuple()
    {
    return pybind11::make_tuple(HOOMD_VERSION_MAJOR, HOOMD_VERSION_MINOR, HOOMD_VERSION_PATCH);
    }

//! Get the CUDA version as a tuple
pybind11::object get_cuda_version_tuple()
    {
    #ifdef ENABLE_CUDA
    int major = CUDA_VERSION / 1000;
    int minor = CUDA_VERSION / 10 % 100;
    return pybind11::make_tuple(major, minor);
    #else
    return pybind11::make_tuple(0,0);
    #endif
    }

//! Get the compiler version
string get_compiler_version()
    {
    #if defined(__GNUC__) && !(defined(__clang__) || defined(__INTEL_COMPILER))
    ostringstream o;
    o << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." <<  __GNUC_PATCHLEVEL__;
    return o.str();

    #elif defined(__clang__)
    ostringstream o;
    o << "clang " << __clang_major__ << "." << __clang_minor__ << "." <<  __clang_patchlevel__;
    return o.str();

    #elif defined(__INTEL_COMPILER)
    ostringstream o;
    o << "icc " << __INTEL_COMPILER;
    return o.str();

    #else
    return string("unknown");

    #endif
    }

//! Determine availability of MPI support
bool is_MPI_available()
   {
   return
#ifdef ENABLE_MPI
       true;
#else
       false;
#endif
    }

void mpi_barrier_world()
    {
    #ifdef ENABLE_MPI
    MPI_Barrier(MPI_COMM_WORLD);
    #endif
    }

//! Start the CUDA profiler
void cuda_profile_start()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStart();
    #endif
    }

//! Stop the CUDA profiler
void cuda_profile_stop()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStop();
    #endif
    }

// values used in measuring hoomd launch timing
unsigned int hoomd_launch_time, hoomd_start_time, hoomd_mpi_init_time;
bool hoomd_launch_timing=false;

#ifdef ENABLE_MPI
//! Environment variables needed for setting up MPI
char env_enable_mpi_cuda[] = "MV2_USE_CUDA=1";

//! Initialize the MPI environment
void initialize_mpi()
    {
    #ifdef ENABLE_MPI_CUDA
    // if we are using an MPI-CUDA implementation, enable this feature
    // before the MPI_Init
    putenv(env_enable_mpi_cuda);
    #endif

    // benchmark hoomd launch times
    if (getenv("HOOMD_LAUNCH_TIME"))
        {
        // get the time that mpirun was called
        hoomd_launch_time = atoi(getenv("HOOMD_LAUNCH_TIME"));

        // compute the number of seconds to get here
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_start_time = t.tv_sec - hoomd_launch_time;
        hoomd_launch_timing = true;
        }

    // initalize MPI
    MPI_Init(0, (char ***) NULL);

    if (hoomd_launch_timing)
        {
        // compute the number of seconds to get past mpi_init
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_mpi_init_time = t.tv_sec - hoomd_launch_time;
        }
    }

//! Get the processor name associated to this rank
string get_mpi_proc_name()
    {
    char proc_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(proc_name, &name_len);
    return string(proc_name);
    }

//! Finalize MPI environment
void finalize_mpi()
    {
    MPI_Finalize();
    }
#endif

//! Abort MPI runs
void abort_mpi(std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    if(exec_conf->getNRanksGlobal() > 1)
        {
        MPI_Abort(exec_conf->getMPICommunicator(), MPI_ERR_OTHER);
        }
    #endif
    }

//! broadcast string from root rank to all other ranks
std::string mpi_bcast_str(const std::string& s, std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    std::string result = s;
    bcast(result, 0, exec_conf->getMPICommunicator());
    return result;
    #else
    return s;
    #endif
    }

//! Create the python module
/*! each class setup their own python exports in a function export_ClassName
    create the hoomd python module and define the exports here.
*/
PYBIND11_PLUGIN(_hoomd)
    {
    pybind11::module m("_hoomd");

    #ifdef ENABLE_MPI
    // initialize MPI early
    initialize_mpi();

    // register clean-up function
    Py_AtExit(finalize_mpi);
    m.def("get_mpi_proc_name", get_mpi_proc_name);
    #endif

    // setup needed for numpy
    my_import_array();

    m.def("abort_mpi", abort_mpi);
    m.def("mpi_barrier_world", mpi_barrier_world);
    m.def("mpi_bcast_str", mpi_bcast_str);

    m.def("hoomd_compile_flags", &hoomd_compile_flags);
    m.def("output_version_info", &output_version_info);
    m.def("get_hoomd_version", &get_hoomd_version);

    m.def("get_num_procs", &get_num_procs);
    m.attr("__version__") = get_hoomd_version_tuple();
    m.attr("__git_sha1__") = pybind11::str(HOOMD_GIT_SHA1);
    m.attr("__git_refspec__") = pybind11::str(HOOMD_GIT_REFSPEC);
    m.attr("__cuda_version__") = get_cuda_version_tuple();
    m.attr("__compiler_version__") = pybind11::str(get_compiler_version());

    m.def("is_MPI_available", &is_MPI_available);

    m.def("cuda_profile_start", &cuda_profile_start);
    m.def("cuda_profile_stop", &cuda_profile_stop);

    pybind11::bind_vector<Scalar>(m,"std_vector_scalar");
    pybind11::bind_vector<string>(m,"std_vector_string");
    pybind11::bind_vector<unsigned int>(m,"std_vector_uint");
    pybind11::bind_vector<int>(m,"std_vector_int");
    pybind11::bind_vector<Scalar3>(m,"std_vector_scalar3");
    pybind11::bind_vector<Scalar4>(m,"std_vector_scalar4");

    InstallSIGINTHandler();

    // utils
    export_hoomd_math_functions(m);
    export_ClockSource(m);
    export_Profiler(m);

    // data structures
    export_BoxDim(m);
    export_ParticleData(m);
    export_SnapshotParticleData(m);
    export_ExecutionConfiguration(m);
    export_SystemDefinition(m);
    export_SnapshotSystemData(m);
    export_BondedGroupData<BondData,Bond>(m,"BondData","BondDataSnapshot");
    export_BondedGroupData<AngleData,Angle>(m,"AngleData","AngleDataSnapshot");
    export_BondedGroupData<DihedralData,Dihedral>(m,"DihedralData","DihedralDataSnapshot");
    export_BondedGroupData<ImproperData,Dihedral>(m,"ImproperData","ImproperDataSnapshot",false);
    export_BondedGroupData<ConstraintData,Constraint>(m,"ConstraintData","ConstraintDataSnapshot");
    export_BondedGroupData<PairData,Bond>(m,"PairData","PairDataSnapshot",false);

    // initializers
    export_GSDReader(m);
    getardump::export_GetarInitializer(m);

    // computes
    export_Compute(m);
    export_ComputeThermo(m);
    export_CellList(m);
    export_CellListStencil(m);
    export_ForceCompute(m);
    export_ForceConstraint(m);
    export_ConstForceCompute(m);

#ifdef ENABLE_CUDA
    export_CellListGPU(m);
    export_ComputeThermoGPU(m);
#endif

    // analyzers
    export_Analyzer(m);
    export_IMDInterface(m);
    export_DCDDumpWriter(m);
    getardump::export_GetarDumpWriter(m);
    export_GSDDumpWriter(m);
    export_Logger(m);
    export_LogPlainTXT(m);
    export_LogMatrix(m);
    export_LogHDF5(m);
    export_CallbackAnalyzer(m);
    export_ParticleGroup(m);

    // updaters
    export_Updater(m);
    export_Integrator(m);
    export_BoxResizeUpdater(m);
    export_SFCPackUpdater(m);
#ifdef ENABLE_CUDA
    export_SFCPackUpdaterGPU(m);
#endif

#ifdef ENABLE_MPI
    export_Communicator(m);
    export_DomainDecomposition(m);
    export_LoadBalancer(m);
#ifdef ENABLE_CUDA
    export_CommunicatorGPU(m);
    export_LoadBalancerGPU(m);
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

    // system
    export_System(m);

    // variant
    export_Variant(m);

    // messenger
    export_Messenger(m);

    return m.ptr();
    }
<|endoftext|>


<commit_before>// -*-mode: c++; indent-tabs-mode: nil; -*-

#include <iostream>
#include <fstream>

#include <sys/types.h> // opendir
#include <dirent.h>    // opendir

#include <sys/types.h> // stat
#include <sys/stat.h>  // stat
#include <unistd.h>    // stat

#include <set>
#include <vector>

#include <limits.h>    // realpath
#include <stdlib.h>    // realpath

#include <string.h>    // strerror_r
#include <errno.h>     // errno

#include <limits.h> // PATH_MAX http://stackoverflow.com/a/9449307/257924

namespace VerboseNS {

  enum VerbosityLevel {
    E_NONE      = 0
    , E_VERBOSE = 1 << 0
    , E_DEBUG   = 1 << 1
  };

  class VerbosityTracker
  {
  public:

    VerbosityTracker() : _verbosity(E_NONE) {}

    bool isAtVerbosity(int level) { return (_verbosity & level) != 0; }

    void setVerbosity(int value)
    {
      _verbosity = value;
    }

#define DEFINE_SET_VERBOSITY_METHOD(TYPE)       \
  TYPE & setVerbosity(int value) \
  { \
    _verbosity.setVerbosity(value); \
    return *this; \
  }

  private:
    int _verbosity;
  };

};

class UniqueFileVisitor
{
public:
  virtual bool visit(const std::string & absPath) = 0;
};

class UniqueFileScanner
{
public:
  UniqueFileScanner()
    : _visitor(NULL)
  {}

  UniqueFileScanner & setVisitor(UniqueFileVisitor * visitor)
  {
    _visitor = visitor;
    return *this;
  }

  DEFINE_SET_VERBOSITY_METHOD(UniqueFileScanner);

  bool scan(const std::string & inDir)
  {
    DIR * dirfp = opendir(inDir.c_str());

    if (!dirfp) {
      std::cerr << "ERROR: Failed to open directory: " << inDir << std::endl;
      return false;
    }

    struct dirent entry;
    struct dirent *result = NULL;
    int readdir_retval = 0;
    struct stat statbuf;
    std::string absPath;
    char realpathBuf[PATH_MAX];
    const char * realPath = NULL;
    while ((readdir_retval = readdir_r(dirfp, &entry, &result)) == 0 && result) {

      std::string basename = entry.d_name;

      // Skip directories we obviously should not traverse into:
      if (basename == "." || basename == ".." || basename == ".git")
        continue;

      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << std::endl;
      }

      // Fully-qualify the directory entry in preparation for calling stat:
      absPath = inDir;
      absPath += "/";
      absPath += basename;
      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << "absPath  " << absPath << std::endl;
      }

      // Identify the type of file it is:
      int status = stat(absPath.c_str(), &statbuf);
      if (status == 0) { // stat succeeded

        // Get the realPath for duplicate detection.
        realPath = realpath(absPath.c_str(), realpathBuf);
        // Warn about bad links:
        if (!realPath) {
          char strbuf[1024];
          const char * errstring = strerror_r(errno, strbuf, sizeof(strbuf));
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cerr << "WARNING: Failed resolve link: " << absPath << " : " << errstring << std::endl;
          }
          continue;
        }
        realPath = realPath;
        if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
          std::cout << "realPath " << realPath << std::endl;
        }

        // Avoid parsing the same file or directory twice (can happen via symbolic links):
        SetT::iterator iter = _seen.find(realPath);
        if(iter != _seen.end()) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping previously processed file or directory: " << realPath << std::endl;
          }
          continue;
        }
        _seen.insert(realPath);

        if ( S_ISDIR(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "directory absPath " << absPath << std::endl;
          }
          // recurse:
          if (!scan(absPath)) {
            return false;
          }
        } else if ( S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "parsable absPath " << absPath << std::endl;
          }
          if (!_visitor->visit(absPath))
            return false;
        } else {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping non-regular file: " << absPath << std::endl;
          }
          continue;
        }
      } else { // stat failed
        if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
          std::cerr << "WARNING: Failed to stat: " << absPath << std::endl;
        }
        continue;
      }

    }

    if (readdir_retval) {
      std::cerr << "ERROR: Failed to read from directory: " << inDir << std::endl;
      return false;
    }

    closedir(dirfp);
    return true;
  }

private:
  typedef std::set<std::string> SetT;
  SetT _seen;
  UniqueFileVisitor * _visitor; // not owned by this object.
  VerboseNS::VerbosityTracker _verbosity;
};

class OrgIDParser : public UniqueFileVisitor
{
public:
 OrgIDParser() {}

  virtual bool visit(const std::string & absPath)
  {

    // Only work on Org-mode files:
    static const char * orgExtension = ".org";
    std::size_t pos;
    if ( (pos = absPath.rfind(orgExtension)) != std::string::npos ) {
      if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
        std::cout << "Processing " << absPath << std::endl;
      }

      // Parse the file:
      return parse(absPath);

    }
    return true;
  }

  bool parse(const std::string & absPath)
  {
    std::ifstream stream(absPath.c_str(), std::ifstream::binary);
    if (!stream) {
      std::cerr << "ERROR: Failed to open: " << absPath << std::endl;
      return false;
    }

    // Get length of file:
    stream.seekg (0, stream.end);
    std::streampos length = stream.tellg();
    stream.seekg (0, stream.beg);

    // Allocate memory:
    std::vector<char> buffer(length);

    // Read data as a block:
    stream.read(&(buffer[0]), length);

    stream.close();

    // Print content:
    std::cout.write(&(buffer[0]), length);

    return true;
  }

  DEFINE_SET_VERBOSITY_METHOD(OrgIDParser);

private:
  VerboseNS::VerbosityTracker _verbosity;
};

int main(int argc, char *argv[], char *const envp[])
{
  int verbosity = VerboseNS::E_NONE;
  bool readingDirectories = false;
  typedef std::vector<std::string> DirectoryListT;
  DirectoryListT directories;
  for (int i = 0; i < argc; i++)
  {
    std::string arg = argv[i];
    if (arg.empty()) break;
    if (readingDirectories) {
      directories.push_back(arg);
    } else {
      if (arg == "--") {
        readingDirectories = true;
      } else if (arg == "-verbose") {
        verbosity |= VerboseNS::E_VERBOSE;
      } else if (arg == "-debug") {
        verbosity |= VerboseNS::E_DEBUG;
      }
    }
  }

  if (directories.empty()) {
    std::cerr << "ERROR: No directories specified." << std::endl;
    return 1;
  }

  // OrgIDParser will house the results:
  OrgIDParser parser;
  parser.setVerbosity(verbosity);

  // UniqueFileScanner scans for files and removes duplicates, visiting each
  // with the parser:
  UniqueFileScanner scanner;
  scanner
    .setVerbosity(verbosity)
    .setVisitor(&parser);
  for (DirectoryListT::iterator cur = directories.begin(); cur != directories.end(); ++cur)
  {
    int success = scanner.scan(*cur);
    if (!success) {
      return 1;
    }
  }
  // Write out the org id file:

  return 0;
} // end main

<commit_msg>change buffer type from std::vector to std::string<commit_after>// -*-mode: c++; indent-tabs-mode: nil; -*-

#include <iostream>
#include <fstream>

#include <sys/types.h> // opendir
#include <dirent.h>    // opendir

#include <sys/types.h> // stat
#include <sys/stat.h>  // stat
#include <unistd.h>    // stat

#include <set>
#include <vector>

#include <limits.h>    // realpath
#include <stdlib.h>    // realpath

#include <string.h>    // strerror_r
#include <errno.h>     // errno

#include <limits.h> // PATH_MAX http://stackoverflow.com/a/9449307/257924

namespace VerboseNS {

  enum VerbosityLevel {
    E_NONE      = 0
    , E_VERBOSE = 1 << 0
    , E_DEBUG   = 1 << 1
  };

  class VerbosityTracker
  {
  public:

    VerbosityTracker() : _verbosity(E_NONE) {}

    bool isAtVerbosity(int level) { return (_verbosity & level) != 0; }

    void setVerbosity(int value)
    {
      _verbosity = value;
    }

#define DEFINE_SET_VERBOSITY_METHOD(TYPE)       \
  TYPE & setVerbosity(int value) \
  { \
    _verbosity.setVerbosity(value); \
    return *this; \
  }

  private:
    int _verbosity;
  };

};

class UniqueFileVisitor
{
public:
  virtual bool visit(const std::string & absPath) = 0;
};

class UniqueFileScanner
{
public:
  UniqueFileScanner()
    : _visitor(NULL)
  {}

  UniqueFileScanner & setVisitor(UniqueFileVisitor * visitor)
  {
    _visitor = visitor;
    return *this;
  }

  DEFINE_SET_VERBOSITY_METHOD(UniqueFileScanner);

  bool scan(const std::string & inDir)
  {
    DIR * dirfp = opendir(inDir.c_str());

    if (!dirfp) {
      std::cerr << "ERROR: Failed to open directory: " << inDir << std::endl;
      return false;
    }

    struct dirent entry;
    struct dirent *result = NULL;
    int readdir_retval = 0;
    struct stat statbuf;
    std::string absPath;
    char realpathBuf[PATH_MAX];
    const char * realPath = NULL;
    while ((readdir_retval = readdir_r(dirfp, &entry, &result)) == 0 && result) {

      std::string basename = entry.d_name;

      // Skip directories we obviously should not traverse into:
      if (basename == "." || basename == ".." || basename == ".git")
        continue;

      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << std::endl;
      }

      // Fully-qualify the directory entry in preparation for calling stat:
      absPath = inDir;
      absPath += "/";
      absPath += basename;
      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << "absPath  " << absPath << std::endl;
      }

      // Identify the type of file it is:
      int status = stat(absPath.c_str(), &statbuf);
      if (status == 0) { // stat succeeded

        // Get the realPath for duplicate detection.
        realPath = realpath(absPath.c_str(), realpathBuf);
        // Warn about bad links:
        if (!realPath) {
          char strbuf[1024];
          const char * errstring = strerror_r(errno, strbuf, sizeof(strbuf));
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cerr << "WARNING: Failed resolve link: " << absPath << " : " << errstring << std::endl;
          }
          continue;
        }
        realPath = realPath;
        if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
          std::cout << "realPath " << realPath << std::endl;
        }

        // Avoid parsing the same file or directory twice (can happen via symbolic links):
        SetT::iterator iter = _seen.find(realPath);
        if(iter != _seen.end()) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping previously processed file or directory: " << realPath << std::endl;
          }
          continue;
        }
        _seen.insert(realPath);

        if ( S_ISDIR(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "directory absPath " << absPath << std::endl;
          }
          // recurse:
          if (!scan(absPath)) {
            return false;
          }
        } else if ( S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "parsable absPath " << absPath << std::endl;
          }
          if (!_visitor->visit(absPath))
            return false;
        } else {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping non-regular file: " << absPath << std::endl;
          }
          continue;
        }
      } else { // stat failed
        if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
          std::cerr << "WARNING: Failed to stat: " << absPath << std::endl;
        }
        continue;
      }

    }

    if (readdir_retval) {
      std::cerr << "ERROR: Failed to read from directory: " << inDir << std::endl;
      return false;
    }

    closedir(dirfp);
    return true;
  }

private:
  typedef std::set<std::string> SetT;
  SetT _seen;
  UniqueFileVisitor * _visitor; // not owned by this object.
  VerboseNS::VerbosityTracker _verbosity;
};

class OrgIDParser : public UniqueFileVisitor
{
public:
 OrgIDParser() {}

  virtual bool visit(const std::string & absPath)
  {

    // Only work on Org-mode files:
    static const char * orgExtension = ".org";
    std::size_t pos;
    if ( (pos = absPath.rfind(orgExtension)) != std::string::npos ) {
      if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
        std::cout << "Processing " << absPath << std::endl;
      }

      // Parse the file:
      return parse(absPath);

    }
    return true;
  }

  bool parse(const std::string & absPath)
  {
    std::ifstream stream(absPath.c_str(), std::ifstream::binary);
    if (!stream) {
      std::cerr << "ERROR: Failed to open: " << absPath << std::endl;
      return false;
    }

    // Get length of file:
    stream.seekg (0, stream.end);
    std::streampos length = stream.tellg();
    stream.seekg (0, stream.beg);

    // Allocate memory:
    std::string buffer(length, 0);

    // Read data as a block:
    stream.read(&(buffer[0]), length);

    stream.close();

    // Print content:
    // std::cout.write(&(buffer[0]), length);
    std::cout << "<<<" << buffer << ">>>" << std::endl;

    return true;
  }

  DEFINE_SET_VERBOSITY_METHOD(OrgIDParser);

private:
  VerboseNS::VerbosityTracker _verbosity;
};

int main(int argc, char *argv[], char *const envp[])
{
  int verbosity = VerboseNS::E_NONE;
  bool readingDirectories = false;
  typedef std::vector<std::string> DirectoryListT;
  DirectoryListT directories;
  for (int i = 0; i < argc; i++)
  {
    std::string arg = argv[i];
    if (arg.empty()) break;
    if (readingDirectories) {
      directories.push_back(arg);
    } else {
      if (arg == "--") {
        readingDirectories = true;
      } else if (arg == "-verbose") {
        verbosity |= VerboseNS::E_VERBOSE;
      } else if (arg == "-debug") {
        verbosity |= VerboseNS::E_DEBUG;
      }
    }
  }

  if (directories.empty()) {
    std::cerr << "ERROR: No directories specified." << std::endl;
    return 1;
  }

  // OrgIDParser will house the results:
  OrgIDParser parser;
  parser.setVerbosity(verbosity);

  // UniqueFileScanner scans for files and removes duplicates, visiting each
  // with the parser:
  UniqueFileScanner scanner;
  scanner
    .setVerbosity(verbosity)
    .setVisitor(&parser);
  for (DirectoryListT::iterator cur = directories.begin(); cur != directories.end(); ++cur)
  {
    int success = scanner.scan(*cur);
    if (!success) {
      return 1;
    }
  }
  // Write out the org id file:

  return 0;
} // end main

<|endoftext|>


<commit_before>// -*-mode: c++; indent-tabs-mode: nil; -*-

#include <iostream>
#include <fstream>

#include <sys/types.h> // opendir
#include <dirent.h>    // opendir

#include <sys/types.h> // stat
#include <sys/stat.h>  // stat
#include <unistd.h>    // stat

#include <limits.h>    // realpath
#include <stdlib.h>    // realpath

#include <string.h>    // strerror_r
#include <errno.h>     // errno

#include <set>
#include <vector>
#include <map>

#include <limits.h> // PATH_MAX http://stackoverflow.com/a/9449307/257924

bool realPathToString(const std::string & inPath, std::string & realPath, bool verbose)
{
  realPath.resize(PATH_MAX);
  // Get the realPath for duplicate detection.
  const char * tmp = realpath(inPath.c_str(), &(realPath[0]));
  // Warn about bad links:
  if (!tmp) {
    char strbuf[1024];
    const char * errstring = strerror_r(errno, strbuf, sizeof(strbuf));
    if (verbose) {
      std::cerr << "WARNING: Failed resolve: " << inPath << " : " << errstring << std::endl;
    }
    realPath = "";
    return false;
  }
  realPath.resize(strlen(&(realPath[0])));
  return true;
}

namespace VerboseNS {

  enum VerbosityLevel {
    E_NONE      = 0
    , E_VERBOSE = 1 << 0
    , E_DEBUG   = 1 << 1
  };

  class VerbosityTracker
  {
  public:

    VerbosityTracker() : _verbosity(E_NONE) {}

    bool isAtVerbosity(int level) { return (_verbosity & level) != 0; }

    void setVerbosity(int value)
    {
      _verbosity = value;
    }

#define DEFINE_SET_VERBOSITY_METHOD(TYPE)       \
  TYPE & setVerbosity(int value) \
  { \
    _verbosity.setVerbosity(value); \
    return *this; \
  }

  private:
    int _verbosity;
  };

};

class UniqueFileVisitor
{
public:
  virtual bool visit(const std::string & absPath) = 0;
};

class UniqueFileScanner
{
public:
  UniqueFileScanner()
    : _visitor(NULL)
  {}

  UniqueFileScanner & setVisitor(UniqueFileVisitor * visitor)
  {
    _visitor = visitor;
    return *this;
  }

  DEFINE_SET_VERBOSITY_METHOD(UniqueFileScanner);

  bool scan(const std::string & inDir)
  {
    DIR * dirfp = opendir(inDir.c_str());

    if (!dirfp) {
      std::cerr << "ERROR: Failed to open directory: " << inDir << std::endl;
      return false;
    }

    struct dirent entry;
    struct dirent *result = NULL;
    int readdir_retval = 0;
    struct stat statbuf;
    std::string absPath;
    std::string realPath;
    while ((readdir_retval = readdir_r(dirfp, &entry, &result)) == 0 && result) {

      std::string basename = entry.d_name;

      // Skip directories we obviously should not traverse into:
      if (basename == "." || basename == ".." || basename == ".git")
        continue;

      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << std::endl;
      }

      // Fully-qualify the directory entry in preparation for calling stat:
      absPath = inDir;
      absPath += "/";
      absPath += basename;
      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << "absPath  " << absPath << std::endl;
      }

      // Identify the type of file it is:
      int status = stat(absPath.c_str(), &statbuf);
      if (status == 0) { // stat succeeded

        // Get the realPath for duplicate detection.
        if (!realPathToString(absPath, realPath, _verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)))
          continue;

        if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
          std::cout << "realPath " << realPath << std::endl;
        }

        // Avoid parsing the same file or directory twice (can happen via symbolic links):
        SetT::iterator iter = _seen.find(realPath);
        if(iter != _seen.end()) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping previously processed file or directory: " << realPath << std::endl;
          }
          continue;
        }
        _seen.insert(realPath);

        if ( S_ISDIR(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "directory absPath " << absPath << std::endl;
          }
          // recurse:
          if (!scan(absPath)) {
            return false;
          }
        } else if ( S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "parsable absPath " << absPath << std::endl;
          }
          if (!_visitor->visit(absPath))
            return false;
        } else {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping non-regular file: " << absPath << std::endl;
          }
          continue;
        }
      } else { // stat failed
        if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
          std::cerr << "WARNING: Failed to stat: " << absPath << std::endl;
        }
        continue;
      }

    }

    if (readdir_retval) {
      std::cerr << "ERROR: Failed to read from directory: " << inDir << std::endl;
      return false;
    }

    closedir(dirfp);
    return true;
  }

private:
  typedef std::set<std::string> SetT;
  SetT _seen;
  UniqueFileVisitor * _visitor; // not owned by this object.
  VerboseNS::VerbosityTracker _verbosity;
};

class OrgIDParser : public UniqueFileVisitor
{
public:
 OrgIDParser() {}

  virtual bool visit(const std::string & absPath)
  {

    // Only work on Org-mode files:
    static const char * orgExtension = ".org";
    std::size_t pos;
    if ( (pos = absPath.rfind(orgExtension)) != std::string::npos ) {
      if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
        std::cout << "Processing " << absPath << std::endl;
      }

      // Parse the file:
      return parse(absPath);

    }
    return true;
  }

  bool parse(const std::string & absPath)
  {
    std::ifstream stream(absPath.c_str(), std::ifstream::binary);
    if (!stream) {
      std::cerr << "ERROR: Failed to open: " << absPath << std::endl;
      return false;
    }

    // Get length of file:
    stream.seekg (0, stream.end);
    std::streampos length = stream.tellg();
    stream.seekg (0, stream.beg);

    // Allocate memory:
    std::string buffer(length, 0);

    // Read data as a block:
    stream.read(&(buffer[0]), length);

    stream.close();

    // Print content:
    // std::cout.write(&(buffer[0]), length);
    // std::cout << "<<<" << buffer << ">>>" << std::endl;

     // :PROPERTIES:
     // :ID:       subdir_t-est1-note-2d73-dd0f5b698f14
     // :END:
    std::size_t propBegPos = 0;
    std::size_t propEndPos = std::string::npos;
    std::size_t idLabelBegPos = std::string::npos;
    std::size_t idValueBegPos = std::string::npos;
    std::size_t idValueEndPos = std::string::npos;
    for ( ; (propBegPos = buffer.find(":PROPERTIES:\n", propBegPos)) != std::string::npos; propBegPos++) {
      if ((propEndPos = buffer.find(":END:\n", propBegPos)) == std::string::npos) {
        std::cerr << "ERROR: Lacking :END: starting at position " << propBegPos << " in file " << absPath << std::endl;
        return false;
      }

      static const char * idLabel = ":ID:";
      if ((idLabelBegPos = buffer.find(idLabel, propBegPos)) == std::string::npos || idLabelBegPos > propEndPos) {
        // No id found within this current property list, so move on.
        continue;
      }

      if ((idValueBegPos = buffer.find_first_not_of(" \t", idLabelBegPos + sizeof(idLabel))) == std::string::npos || idValueBegPos > propEndPos) {
        std::cerr << "ERROR: ID lacks a value starting at position " << idLabelBegPos << " in file " << absPath << std::endl;
        return false;
      }

      if ((idValueEndPos = buffer.find_first_of(" \t\n", idValueBegPos)) == std::string::npos || idValueEndPos > propEndPos) {
        std::cerr << "ERROR: ID value premature termination at position " << idValueBegPos << " in file " << absPath << std::endl;
        return false;
      }

      std::string id = buffer.substr(idValueBegPos, idValueEndPos - idValueBegPos);

      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << "absPath " << absPath << " id " << id << std::endl;
      }

      IdSetT & ids = _map[absPath]; // Create a IdSetT if one does not exist
      if (ids.find(id) != ids.end()) {
        std::cerr << "ERROR: Duplicate ID value " << id << " at position " << idValueBegPos << " in file " << absPath << std::endl;
        return false;
      }
      ids.insert(id);

    }

    return true;
  }

  bool writeIdAlistFile(const std::string & alistPath)
  {
    std::ofstream stream(alistPath.c_str());
    if (!stream) {
      std::cerr << "ERROR: Cannot open " << alistPath << " for writing." << std::endl;
      return false;
    }

    bool first = true;
    stream << "(";
    for (FileToIdSetT::iterator cur = _map.begin(); cur != _map.end(); ++cur)
    {
      const std::string & absPath = cur->first;

      if (!first) {
        stream << std::endl << " ";
      }

      stream << "(\"" << absPath << "\"";
      IdSetT & ids = cur->second;

      for (IdSetT::iterator cur = ids.begin(); cur != ids.end(); ++cur)
      {
        stream << " \"" << *cur << "\"";
      }

      stream << ")";

      first = false;
    }
    stream << ")" << std::endl;

    return true;
  }

  DEFINE_SET_VERBOSITY_METHOD(OrgIDParser);

private:
  VerboseNS::VerbosityTracker _verbosity;
  typedef std::set<std::string> IdSetT;
  typedef std::map<std::string, IdSetT > FileToIdSetT;
  FileToIdSetT _map;
};

int main(int argc, char *argv[], char *const envp[])
{
  int verbosity = VerboseNS::E_NONE;
  bool readingDirectories = false;
  typedef std::vector<std::string> DirectoryListT;
  DirectoryListT directories;
  std::string idAlistPath;
  for (int i = 1; i < argc; i++)
  {
    std::string arg = argv[i];
    if (arg.empty()) break;
    if (readingDirectories) {
      // Get the realPath for things like ".":
      std::string realPath;
      if (!realPathToString(arg, realPath, true))
        continue;
      directories.push_back(arg);
    } else {
      if (arg == "--") {
        readingDirectories = true;
      } else if (arg == "-verbose") {
        verbosity |= VerboseNS::E_VERBOSE;
      } else if (arg == "-debug") {
        verbosity |= VerboseNS::E_DEBUG;
      } else if (arg == "-o") {
        if (i + 1 >= argc) {
          std::cerr << "ERROR: -o requires a value." << std::endl;
          return 1;
        }
        idAlistPath = argv[++i];
      } else {
        std::cerr << "ERROR: Unrecognized option " << arg << std::endl;
        return 1;
      }
    }
  }

  if (directories.empty()) {
    std::cerr << "ERROR: No directories specified." << std::endl;
    return 1;
  }

  if (idAlistPath.empty()) {
    std::cerr << "ERROR: No alistfile specified." << std::endl;
    return 1;
  }

  // OrgIDParser will house the results:
  OrgIDParser parser;
  parser.setVerbosity(verbosity);

  // UniqueFileScanner scans for files and removes duplicates, visiting each
  // with the parser:
  UniqueFileScanner scanner;
  scanner
    .setVerbosity(verbosity)
    .setVisitor(&parser);
  for (DirectoryListT::iterator cur = directories.begin(); cur != directories.end(); ++cur)
  {
    int success = scanner.scan(*cur);
    if (!success) {
      return 1;
    }
  }

  // Write out the alist file:
  parser.writeIdAlistFile(idAlistPath);

  return 0;
} // end main

<commit_msg>use realPath in the input directory list<commit_after>// -*-mode: c++; indent-tabs-mode: nil; -*-

#include <iostream>
#include <fstream>

#include <sys/types.h> // opendir
#include <dirent.h>    // opendir

#include <sys/types.h> // stat
#include <sys/stat.h>  // stat
#include <unistd.h>    // stat

#include <limits.h>    // realpath
#include <stdlib.h>    // realpath

#include <string.h>    // strerror_r
#include <errno.h>     // errno

#include <set>
#include <vector>
#include <map>

#include <limits.h> // PATH_MAX http://stackoverflow.com/a/9449307/257924

bool realPathToString(const std::string & inPath, std::string & realPath, bool verbose)
{
  realPath.resize(PATH_MAX);
  // Get the realPath for duplicate detection.
  const char * tmp = realpath(inPath.c_str(), &(realPath[0]));
  // Warn about bad links:
  if (!tmp) {
    char strbuf[1024];
    const char * errstring = strerror_r(errno, strbuf, sizeof(strbuf));
    if (verbose) {
      std::cerr << "WARNING: Failed resolve: " << inPath << " : " << errstring << std::endl;
    }
    realPath = "";
    return false;
  }
  realPath.resize(strlen(&(realPath[0])));
  return true;
}

namespace VerboseNS {

  enum VerbosityLevel {
    E_NONE      = 0
    , E_VERBOSE = 1 << 0
    , E_DEBUG   = 1 << 1
  };

  class VerbosityTracker
  {
  public:

    VerbosityTracker() : _verbosity(E_NONE) {}

    bool isAtVerbosity(int level) { return (_verbosity & level) != 0; }

    void setVerbosity(int value)
    {
      _verbosity = value;
    }

#define DEFINE_SET_VERBOSITY_METHOD(TYPE)       \
  TYPE & setVerbosity(int value) \
  { \
    _verbosity.setVerbosity(value); \
    return *this; \
  }

  private:
    int _verbosity;
  };

};

class UniqueFileVisitor
{
public:
  virtual bool visit(const std::string & absPath) = 0;
};

class UniqueFileScanner
{
public:
  UniqueFileScanner()
    : _visitor(NULL)
  {}

  UniqueFileScanner & setVisitor(UniqueFileVisitor * visitor)
  {
    _visitor = visitor;
    return *this;
  }

  DEFINE_SET_VERBOSITY_METHOD(UniqueFileScanner);

  bool scan(const std::string & inDir)
  {
    DIR * dirfp = opendir(inDir.c_str());

    if (!dirfp) {
      std::cerr << "ERROR: Failed to open directory: " << inDir << std::endl;
      return false;
    }

    struct dirent entry;
    struct dirent *result = NULL;
    int readdir_retval = 0;
    struct stat statbuf;
    std::string absPath;
    std::string realPath;
    while ((readdir_retval = readdir_r(dirfp, &entry, &result)) == 0 && result) {

      std::string basename = entry.d_name;

      // Skip directories we obviously should not traverse into:
      if (basename == "." || basename == ".." || basename == ".git")
        continue;

      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << std::endl;
      }

      // Fully-qualify the directory entry in preparation for calling stat:
      absPath = inDir;
      absPath += "/";
      absPath += basename;
      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << "absPath  " << absPath << std::endl;
      }

      // Identify the type of file it is:
      int status = stat(absPath.c_str(), &statbuf);
      if (status == 0) { // stat succeeded

        // Get the realPath for duplicate detection.
        if (!realPathToString(absPath, realPath, _verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)))
          continue;

        if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
          std::cout << "realPath " << realPath << std::endl;
        }

        // Avoid parsing the same file or directory twice (can happen via symbolic links):
        SetT::iterator iter = _seen.find(realPath);
        if(iter != _seen.end()) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping previously processed file or directory: " << realPath << std::endl;
          }
          continue;
        }
        _seen.insert(realPath);

        if ( S_ISDIR(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "directory absPath " << absPath << std::endl;
          }
          // recurse:
          if (!scan(absPath)) {
            return false;
          }
        } else if ( S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode) ) {
          if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
            std::cout << "parsable absPath " << absPath << std::endl;
          }
          if (!_visitor->visit(absPath))
            return false;
        } else {
          if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
            std::cout << "Skipping non-regular file: " << absPath << std::endl;
          }
          continue;
        }
      } else { // stat failed
        if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
          std::cerr << "WARNING: Failed to stat: " << absPath << std::endl;
        }
        continue;
      }

    }

    if (readdir_retval) {
      std::cerr << "ERROR: Failed to read from directory: " << inDir << std::endl;
      return false;
    }

    closedir(dirfp);
    return true;
  }

private:
  typedef std::set<std::string> SetT;
  SetT _seen;
  UniqueFileVisitor * _visitor; // not owned by this object.
  VerboseNS::VerbosityTracker _verbosity;
};

class OrgIDParser : public UniqueFileVisitor
{
public:
 OrgIDParser() {}

  virtual bool visit(const std::string & absPath)
  {

    // Only work on Org-mode files:
    static const char * orgExtension = ".org";
    std::size_t pos;
    if ( (pos = absPath.rfind(orgExtension)) != std::string::npos ) {
      if (_verbosity.isAtVerbosity(VerboseNS::E_VERBOSE)) {
        std::cout << "Processing " << absPath << std::endl;
      }

      // Parse the file:
      return parse(absPath);

    }
    return true;
  }

  bool parse(const std::string & absPath)
  {
    std::ifstream stream(absPath.c_str(), std::ifstream::binary);
    if (!stream) {
      std::cerr << "ERROR: Failed to open: " << absPath << std::endl;
      return false;
    }

    // Get length of file:
    stream.seekg (0, stream.end);
    std::streampos length = stream.tellg();
    stream.seekg (0, stream.beg);

    // Allocate memory:
    std::string buffer(length, 0);

    // Read data as a block:
    stream.read(&(buffer[0]), length);

    stream.close();

    // Print content:
    // std::cout.write(&(buffer[0]), length);
    // std::cout << "<<<" << buffer << ">>>" << std::endl;

     // :PROPERTIES:
     // :ID:       subdir_t-est1-note-2d73-dd0f5b698f14
     // :END:
    std::size_t propBegPos = 0;
    std::size_t propEndPos = std::string::npos;
    std::size_t idLabelBegPos = std::string::npos;
    std::size_t idValueBegPos = std::string::npos;
    std::size_t idValueEndPos = std::string::npos;
    for ( ; (propBegPos = buffer.find(":PROPERTIES:\n", propBegPos)) != std::string::npos; propBegPos++) {
      if ((propEndPos = buffer.find(":END:\n", propBegPos)) == std::string::npos) {
        std::cerr << "ERROR: Lacking :END: starting at position " << propBegPos << " in file " << absPath << std::endl;
        return false;
      }

      static const char * idLabel = ":ID:";
      if ((idLabelBegPos = buffer.find(idLabel, propBegPos)) == std::string::npos || idLabelBegPos > propEndPos) {
        // No id found within this current property list, so move on.
        continue;
      }

      if ((idValueBegPos = buffer.find_first_not_of(" \t", idLabelBegPos + sizeof(idLabel))) == std::string::npos || idValueBegPos > propEndPos) {
        std::cerr << "ERROR: ID lacks a value starting at position " << idLabelBegPos << " in file " << absPath << std::endl;
        return false;
      }

      if ((idValueEndPos = buffer.find_first_of(" \t\n", idValueBegPos)) == std::string::npos || idValueEndPos > propEndPos) {
        std::cerr << "ERROR: ID value premature termination at position " << idValueBegPos << " in file " << absPath << std::endl;
        return false;
      }

      std::string id = buffer.substr(idValueBegPos, idValueEndPos - idValueBegPos);

      if (_verbosity.isAtVerbosity(VerboseNS::E_DEBUG)) {
        std::cout << "absPath " << absPath << " id " << id << std::endl;
      }

      IdSetT & ids = _map[absPath]; // Create a IdSetT if one does not exist
      if (ids.find(id) != ids.end()) {
        std::cerr << "ERROR: Duplicate ID value " << id << " at position " << idValueBegPos << " in file " << absPath << std::endl;
        return false;
      }
      ids.insert(id);

    }

    return true;
  }

  bool writeIdAlistFile(const std::string & alistPath)
  {
    std::ofstream stream(alistPath.c_str());
    if (!stream) {
      std::cerr << "ERROR: Cannot open " << alistPath << " for writing." << std::endl;
      return false;
    }

    bool first = true;
    stream << "(";
    for (FileToIdSetT::iterator cur = _map.begin(); cur != _map.end(); ++cur)
    {
      const std::string & absPath = cur->first;

      if (!first) {
        stream << std::endl << " ";
      }

      stream << "(\"" << absPath << "\"";
      IdSetT & ids = cur->second;

      for (IdSetT::iterator cur = ids.begin(); cur != ids.end(); ++cur)
      {
        stream << " \"" << *cur << "\"";
      }

      stream << ")";

      first = false;
    }
    stream << ")" << std::endl;

    return true;
  }

  DEFINE_SET_VERBOSITY_METHOD(OrgIDParser);

private:
  VerboseNS::VerbosityTracker _verbosity;
  typedef std::set<std::string> IdSetT;
  typedef std::map<std::string, IdSetT > FileToIdSetT;
  FileToIdSetT _map;
};

int main(int argc, char *argv[], char *const envp[])
{
  int verbosity = VerboseNS::E_NONE;
  bool readingDirectories = false;
  typedef std::vector<std::string> DirectoryListT;
  DirectoryListT directories;
  std::string idAlistPath;
  for (int i = 1; i < argc; i++)
  {
    std::string arg = argv[i];
    if (arg.empty()) break;
    if (readingDirectories) {
      // Get the realPath for things like ".":
      std::string realPath;
      if (!realPathToString(arg, realPath, true))
        continue;
      directories.push_back(realPath);
    } else {
      if (arg == "--") {
        readingDirectories = true;
      } else if (arg == "-verbose") {
        verbosity |= VerboseNS::E_VERBOSE;
      } else if (arg == "-debug") {
        verbosity |= VerboseNS::E_DEBUG;
      } else if (arg == "-o") {
        if (i + 1 >= argc) {
          std::cerr << "ERROR: -o requires a value." << std::endl;
          return 1;
        }
        idAlistPath = argv[++i];
      } else {
        std::cerr << "ERROR: Unrecognized option " << arg << std::endl;
        return 1;
      }
    }
  }

  if (directories.empty()) {
    std::cerr << "ERROR: No directories specified." << std::endl;
    return 1;
  }

  if (idAlistPath.empty()) {
    std::cerr << "ERROR: No alistfile specified." << std::endl;
    return 1;
  }

  // OrgIDParser will house the results:
  OrgIDParser parser;
  parser.setVerbosity(verbosity);

  // UniqueFileScanner scans for files and removes duplicates, visiting each
  // with the parser:
  UniqueFileScanner scanner;
  scanner
    .setVerbosity(verbosity)
    .setVisitor(&parser);
  for (DirectoryListT::iterator cur = directories.begin(); cur != directories.end(); ++cur)
  {
    int success = scanner.scan(*cur);
    if (!success) {
      return 1;
    }
  }

  // Write out the alist file:
  parser.writeIdAlistFile(idAlistPath);

  return 0;
} // end main

<|endoftext|>


<commit_before><commit_msg>Related fdo#61272: Revert "wmf-mm-text-1.diff: Fix WMF rendering, n#417818"<commit_after><|endoftext|>


<commit_before>
#include "catch.hpp"
#include "CStringBuilder.hpp"

using namespace tcsb;

SCENARIO( "Create and use simple CStringBuilder", "[CStringBuilder]" ) {
    GIVEN( "A vector with some items" ) {
        const size_t bufferSize = 100;
        char buffer[bufferSize];

        CStringBuilder sb(buffer, bufferSize);

        REQUIRE(sb.size() == 0);
        REQUIRE(sb.bufferSize());

        WHEN("Add another string") {
            sb.add("ha!");

            THEN("the size and capacity change") {
                REQUIRE(sb.size() == 3);
            }

            THEN("ha! should be there and 0 terminated") {
                REQUIRE(sb.cStr() == std::string("ha!"));
                REQUIRE(sb.cStr()[3] == '\0');
            }
        }

        WHEN("Append by 0 digit int") {
            sb.add(0);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("0"));
                REQUIRE(sb.cStr()[1] == '\0');
            }
        }

        WHEN("Add many digits int is passed") {
            sb.add(-1234);

            THEN("it should be properly displayed") {

                REQUIRE(sb.cStr()[0] == '-');
                REQUIRE(sb.cStr()[1] == '1');
                REQUIRE(sb.cStr()[2] == '2');
                REQUIRE(sb.cStr()[3] == '3');
                REQUIRE(sb.cStr()[4] == '4');
                REQUIRE(sb.cStr()[5] == '\0');
            }
        }

        WHEN("Add int8_t") {
            sb.add((int8_t) -3);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-3"));
            }
        }
        WHEN("Add uint8_t") {
            sb.add((uint8_t) 250);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("250"));
            }
        }
        WHEN("Add int16_t") {
            sb.add((int16_t) -30000);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-30000"));
            }
        }
        WHEN("Add uint16_t") {
            sb.add((uint16_t) 60000);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("60000"));
            }
        }
        WHEN("Add int32_t") {
            sb.add((int32_t) -2147483600);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-2147483600"));
            }
        }
        WHEN("Add uint32_t") {
            sb.add((uint32_t) 4294967295U);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("4294967295"));
            }
        }

        WHEN("Add int64_t") {
            sb.add((int64_t) -9223372036854775800);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-9223372036854775800"));
            }
        }

        WHEN("Add uint64_t") {
            uint64_t value = 18446744073709551614U;
            sb.add(value);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("18446744073709551614"));
            }
        }

        WHEN("Add string and value") {
            uint64_t value = 18446744073709551614U;
            sb.add("haha! ", value);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("haha! 18446744073709551614"));
            }
        }

        WHEN("Add string as array and value") {
            uint64_t value = 18446744073709551614U;
            char haha[100]="haha! ";
            sb.add(haha, 100, value);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("haha! 18446744073709551614"));
            }
        }
    }
}

SCENARIO( "Insufficient buffer", "[CStringBuilder]" ) {

    GIVEN("A vector with some items") {
        const size_t bufferSize = 5;
        char buffer[bufferSize];
        CStringBuilder sb(buffer, bufferSize);

        WHEN("Add long string") {
            sb.add("123456789");

            THEN("It should be truncated") {
                REQUIRE(sb.cStr() == std::string("1234"));
                REQUIRE(sb.cStr()[4] == '\0');

            }
        }
        AND_WHEN("We add integer to it"){
            THEN("It should not fall over the edges") {
                REQUIRE_NOTHROW(sb.add(55));
            }
        }

        WHEN("Add long integer") {
            sb.add(123456789);

            THEN("It should be truncated") {
                //TODO REQUIRE(sb.cStr() == std::string("1234"));
                REQUIRE(sb.cStr()[4] == '\0');
            }
        }
    }
}

<commit_msg>CStringBuilder tests update<commit_after>
#include "catch.hpp"
#include "CStringBuilder.hpp"

using namespace tcsb;

SCENARIO( "Create and use simple CStringBuilder", "[CStringBuilder]" ) {
    GIVEN( "A vector with some items" ) {
        const size_t bufferSize = 100;
        char buffer[bufferSize];

        CStringBuilder sb(buffer, bufferSize);

        REQUIRE(sb.size() == 0);
        REQUIRE(sb.bufferSize());

        WHEN("Add another string") {
            sb.add("ha!");
            sb.add(" ");
            sb.add(5);

            THEN("the size and capacity change") {
                REQUIRE(sb.size() == 5);
            }

            THEN("ha! should be there and 0 terminated") {
                REQUIRE(sb.cStr() == std::string("ha! 5"));
                REQUIRE(sb.cStr()[5] == '\0');
            }
        }

        WHEN("Append by 0 digit int") {
            sb.add(0);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("0"));
                REQUIRE(sb.cStr()[1] == '\0');
            }
        }

        WHEN("Add many digits int is passed") {
            sb.add(-1234);

            THEN("it should be properly displayed") {

                REQUIRE(sb.cStr()[0] == '-');
                REQUIRE(sb.cStr()[1] == '1');
                REQUIRE(sb.cStr()[2] == '2');
                REQUIRE(sb.cStr()[3] == '3');
                REQUIRE(sb.cStr()[4] == '4');
                REQUIRE(sb.cStr()[5] == '\0');
            }
        }

        WHEN("Add int8_t") {
            sb.add((int8_t) -3);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-3"));
            }
        }
        WHEN("Add uint8_t") {
            sb.add((uint8_t) 250);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("250"));
            }
        }
        WHEN("Add int16_t") {
            sb.add((int16_t) -30000);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-30000"));
            }
        }
        WHEN("Add uint16_t") {
            sb.add((uint16_t) 60000);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("60000"));
            }
        }
        WHEN("Add int32_t") {
            sb.add((int32_t) -2147483600);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-2147483600"));
            }
        }
        WHEN("Add uint32_t") {
            sb.add((uint32_t) 4294967295U);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("4294967295"));
            }
        }

        WHEN("Add int64_t") {
            sb.add((int64_t) -9223372036854775800);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("-9223372036854775800"));
            }
        }

        WHEN("Add uint64_t") {
            uint64_t value = 18446744073709551614U;
            sb.add(value);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("18446744073709551614"));
            }
        }

        WHEN("Add string and value") {
            uint64_t value = 18446744073709551614U;
            sb.add("haha! ", value);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("haha! 18446744073709551614"));
            }
        }

        WHEN("Add string as array and value") {
            uint64_t value = 18446744073709551614U;
            char haha[100]="haha! ";
            sb.add(haha, 100, value);

            THEN("it should be properly displayed") {
                REQUIRE(sb.cStr() == std::string("haha! 18446744073709551614"));
            }
        }
    }
}

SCENARIO( "Insufficient buffer", "[CStringBuilder]" ) {

    GIVEN("A vector with some items") {
        const size_t bufferSize = 5;
        char buffer[bufferSize];
        CStringBuilder sb(buffer, bufferSize);

        WHEN("Add long string") {
            sb.add("123456789");

            THEN("It should be truncated") {
                REQUIRE(sb.cStr() == std::string("1234"));
                REQUIRE(sb.cStr()[4] == '\0');

            }
        }
        AND_WHEN("We add integer to it"){
            THEN("It should not fall over the edges") {
                REQUIRE_NOTHROW(sb.add(55));
            }
        }

        WHEN("Add long integer") {
            sb.add(123456789);

            THEN("It should be truncated") {
                //TODO REQUIRE(sb.cStr() == std::string("1234"));
                REQUIRE(sb.cStr()[4] == '\0');
            }
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>no message<commit_after><|endoftext|>