<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_CORE_HXX
   #error Please #include <abc/core.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals

namespace abc {

/** Indicates the level of UTF-8 string literals support:
•  2 - The UTF-8 string literal prefix (u8) is supported;
•  1 - The u8 prefix is not supported, but the compiler will generate valid UTF-8 string literals if
       the source file is UTF-8+BOM-encoded;
•  0 - UTF-8 string literals are not supported in any way.
*/
#define ABC_CXX_UTF8LIT 0

/** Indicates how char16_t is defined:
•  2 - char16_t is a native type, distinct from uint16_t and wchar_t;
•  1 - abc::char16_t is a typedef for native 16-bit wchar_t, distinct from uint16_t;
•  0 - abc::char16_t is a typedef for uint16_t.
*/
#define ABC_CXX_CHAR16 0

/** Indicates how char32_t is defined:
•  2 - char32_t is a native type, distinct from uint32_t and wchar_t;
•  1 - abc::char32_t is a typedef for native 32-bit wchar_t, distinct from uint32_t;
•  0 - abc::char32_t is a typedef for uint32_t.
*/
#define ABC_CXX_CHAR32 0

#if ABC_HOST_GCC >= 40400
   // char16_t is a native type, different than uint16_t.
   #undef ABC_CXX_CHAR16
   #define ABC_CXX_CHAR16 2
   // char32_t is a native type, different than uint32_t.
   #undef ABC_CXX_CHAR32
   #define ABC_CXX_CHAR32 2

   #if ABC_HOST_GCC >= 40500
      // UTF-8 string literals are supported.
      #undef ABC_CXX_UTF8LIT
      #define ABC_CXX_UTF8LIT 2
   #endif
#else //if ABC_HOST_GCC >= 40400
   #if ABC_HOST_MSC
      #if !defined(_WCHAR_T_DEFINED) || !defined(_NATIVE_WCHAR_T_DEFINED)
         #error Please compile with /Zc:wchar_t
      #endif

      // char16_t is not a native type, but we can typedef it as wchar_t.
      #undef ABC_CXX_CHAR16
      #define ABC_CXX_CHAR16 1
   #else
      // MSC16 will transcode non-wchar_t string literals into whatever single-byte encoding is
      // selected for the user running cl.exe; a solution has been provided in form of a hotfix
      // (<http://support.microsoft.com/kb/2284668/en-us>), but it no longer seems available, and it
      // was not ported to MSC17/VS2012, thought it seems it was finally built into MSC18/VS2013
      // (<http://connect.microsoft.com/VisualStudio/feedback/details/773186/pragma-execution-
      // character-set-utf-8-didnt-support-in-vc-2012>).
      //
      // Here we assume that no other compiler exhibits such a random behavior, and they will all
      // emit valid UTF-8 string literals it the source file is UTF-8+BOM-encoded.
      #undef ABC_CXX_UTF8LIT
      #define ABC_CXX_UTF8LIT 1

      // char32_t is not a native type, but we can typedef it as wchar_t.
      #undef ABC_CXX_CHAR32
      #define ABC_CXX_CHAR32 1
   #endif
#endif //if ABC_HOST_GCC >= 40400 … else
#if ABC_CXX_CHAR16 == 0 && ABC_CXX_CHAR32 == 0
   #error ABC_CXX_CHAR16 and/or ABC_CXX_CHAR32 must be > 0; please fix detection logic
#endif

/** UTF-8 character type. */
typedef char char8_t;

/** UTF-16 character type. */
#if ABC_CXX_CHAR16 == 1
   typedef wchar_t char16_t;
#elif ABC_CXX_CHAR16 == 0
   typedef uint16_t char16_t;
#endif

/** UTF-32 character type. */
#if ABC_CXX_CHAR32 == 1
   typedef wchar_t char32_t;
#elif ABC_CXX_CHAR32 == 0
   typedef uint32_t char32_t;
#endif

/** Defines an 8-bit character literal.

ch
   Character literal.
return
   8-bit character literal.
*/
#define U8CL(ch) ::abc::char8_t(ch)

/** Defines a UCS-16 character literal.

ch
   Character literal.
return
   UCS-16 character literal.
*/
#if ABC_CXX_CHAR16 == 2
   #define U16CL(ch) u ## ch
#elif ABC_CXX_CHAR16 == 1
   #define U16CL(ch) L ## ch
#elif ABC_CXX_CHAR16 == 0
   // No native type for char16_t, but we can at least use 32-bit wchar_t to store any Unicode
   // character correctly, and then truncate that to our typedef’ed char16_t.
   // TODO: make the truncation explicit (compiler warning?).
   #define U16CL(ch) ::abc::char16_t(L ## ch)
#endif

/** Defines a UTF-32/UCS-32 character literal. Code points outside the Basic Multilingual Plane are
not supported on all platforms.

ch
   Character literal.
return
   UTF-32/UCS-32 character literal.
*/
#if ABC_CXX_CHAR32 == 2
   #define U32CL(ch) U ## ch
#elif ABC_CXX_CHAR32 == 1
   #define U32CL(ch) L ## ch
#elif ABC_CXX_CHAR32 == 0
   // No native type for char32_t, but we can at least use 16-bit wchar_t to store all Unicode BMP
   // characters correctly, and then cast that to our typedef’ed char32_t.
   #define U32CL(ch) ::abc::char32_t(L ## ch)
#endif

/** Defines a UTF-8 string literal. On some platforms, this relies on the source files being encoded
in UTF-8.

s
   String literal.
return
   UTF-8 string literal.
*/
#if ABC_CXX_UTF8LIT == 2
   #define U8SL(s) u8 ## s
#elif ABC_CXX_UTF8LIT == 1
   // Rely on the source files being encoded in UTF-8.
   #define U8SL(s) s
#endif

/** Defines a UTF-16 string literal. Not supported on all platforms; check with #ifdef before using.

s
   String literal.
return
   UTF-16 string literal.
*/
#if ABC_CXX_CHAR16 == 2
   #define U16SL(s) u ## s
#elif ABC_CXX_CHAR16 == 1
   #define U16SL(s) L ## s
#endif

/** Defines a UTF-32/UCS-32 string literal. Not supported on all platforms; check with #ifdef before
using.

s
   String literal.
return
   UTF-32 string literal.
*/
#if ABC_CXX_CHAR32 == 2
   #define U32SL(s) U ## s
#elif ABC_CXX_CHAR32 == 1
   #define U32SL(s) L ## s
#endif

/** UTF-* encoding supported by the host. */
#if ABC_HOST_API_WIN32 && defined(UNICODE)
   #define ABC_HOST_UTF 16
#else
   #define ABC_HOST_UTF 8
#endif

/** Default UTF character type for the host. */
#if ABC_HOST_UTF == 8
   typedef char8_t char_t;
#elif ABC_HOST_UTF == 16
   typedef char16_t char_t;
#elif ABC_HOST_UTF == 32
   typedef char32_t char_t;
#endif

/** Defines a character literal of the default host character literal type.

ch
   Character literal.
return
   UCS character literal.
*/
#if ABC_HOST_UTF == 8
   #define CL(ch) U8CL(ch)
#elif ABC_HOST_UTF == 16
   #define CL(ch) U16CL(ch)
#elif ABC_HOST_UTF == 32
   #define CL(ch) U32CL(ch)
#endif

/** Defines a string literal of the default host string literal type.

s
   String literal.
return
   UTF string literal.
*/
#if ABC_HOST_UTF == 8
   #define SL(s) U8SL(s)
#elif ABC_HOST_UTF == 16
   #define SL(s) U16SL(s)
#elif ABC_HOST_UTF == 32
   #define SL(s) U32SL(s)
#endif

} //namespace abc

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

<commit_msg>Move all char types except char_t into :: namespace for consistency with C++11 char*_t<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_CORE_HXX
   #error Please #include <abc/core.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc globals

/** Indicates the level of UTF-8 string literals support:
•  2 - The UTF-8 string literal prefix (u8) is supported;
•  1 - The u8 prefix is not supported, but the compiler will generate valid UTF-8 string literals if
       the source file is UTF-8+BOM-encoded;
•  0 - UTF-8 string literals are not supported in any way.
*/
#define ABC_CXX_UTF8LIT 0

/** Indicates how char16_t is defined:
•  2 - char16_t is a native type, distinct from uint16_t and wchar_t;
•  1 - abc::char16_t is a typedef for native 16-bit wchar_t, distinct from uint16_t;
•  0 - abc::char16_t is a typedef for uint16_t.
*/
#define ABC_CXX_CHAR16 0

/** Indicates how char32_t is defined:
•  2 - char32_t is a native type, distinct from uint32_t and wchar_t;
•  1 - abc::char32_t is a typedef for native 32-bit wchar_t, distinct from uint32_t;
•  0 - abc::char32_t is a typedef for uint32_t.
*/
#define ABC_CXX_CHAR32 0

#if ABC_HOST_GCC >= 40400
   // char16_t is a native type, different than uint16_t.
   #undef ABC_CXX_CHAR16
   #define ABC_CXX_CHAR16 2
   // char32_t is a native type, different than uint32_t.
   #undef ABC_CXX_CHAR32
   #define ABC_CXX_CHAR32 2

   #if ABC_HOST_GCC >= 40500
      // UTF-8 string literals are supported.
      #undef ABC_CXX_UTF8LIT
      #define ABC_CXX_UTF8LIT 2
   #endif
#else //if ABC_HOST_GCC >= 40400
   #if ABC_HOST_MSC
      #if !defined(_WCHAR_T_DEFINED) || !defined(_NATIVE_WCHAR_T_DEFINED)
         #error Please compile with /Zc:wchar_t
      #endif

      // char16_t is not a native type, but we can typedef it as wchar_t.
      #undef ABC_CXX_CHAR16
      #define ABC_CXX_CHAR16 1
   #else
      // MSC16 will transcode non-wchar_t string literals into whatever single-byte encoding is
      // selected for the user running cl.exe; a solution has been provided in form of a hotfix
      // (<http://support.microsoft.com/kb/2284668/en-us>), but it no longer seems available, and it
      // was not ported to MSC17/VS2012, thought it seems it was finally built into MSC18/VS2013
      // (<http://connect.microsoft.com/VisualStudio/feedback/details/773186/pragma-execution-
      // character-set-utf-8-didnt-support-in-vc-2012>).
      //
      // Here we assume that no other compiler exhibits such a random behavior, and they will all
      // emit valid UTF-8 string literals it the source file is UTF-8+BOM-encoded.
      #undef ABC_CXX_UTF8LIT
      #define ABC_CXX_UTF8LIT 1

      // char32_t is not a native type, but we can typedef it as wchar_t.
      #undef ABC_CXX_CHAR32
      #define ABC_CXX_CHAR32 1
   #endif
#endif //if ABC_HOST_GCC >= 40400 … else
#if ABC_CXX_CHAR16 == 0 && ABC_CXX_CHAR32 == 0
   #error ABC_CXX_CHAR16 and/or ABC_CXX_CHAR32 must be > 0; please fix detection logic
#endif

/** UTF-8 character type. */
typedef char char8_t;

/** UTF-16 character type. */
#if ABC_CXX_CHAR16 == 1
   typedef wchar_t char16_t;
#elif ABC_CXX_CHAR16 == 0
   typedef uint16_t char16_t;
#endif

/** UTF-32 character type. */
#if ABC_CXX_CHAR32 == 1
   typedef wchar_t char32_t;
#elif ABC_CXX_CHAR32 == 0
   typedef uint32_t char32_t;
#endif

/** Defines an 8-bit character literal.

ch
   Character literal.
return
   8-bit character literal.
*/
#define U8CL(ch) ch

/** Defines a UCS-16 character literal.

ch
   Character literal.
return
   UCS-16 character literal.
*/
#if ABC_CXX_CHAR16 == 2
   #define U16CL(ch) u ## ch
#elif ABC_CXX_CHAR16 == 1
   #define U16CL(ch) L ## ch
#elif ABC_CXX_CHAR16 == 0
   // No native type for char16_t, but we can at least use 32-bit wchar_t to store any Unicode
   // character correctly, and then truncate that to our typedef’ed char16_t.
   // TODO: make the truncation explicit (compiler warning?).
   #define U16CL(ch) ::abc::char16_t(L ## ch)
#endif

/** Defines a UTF-32/UCS-32 character literal. Code points outside the Basic Multilingual Plane are
not supported on all platforms.

ch
   Character literal.
return
   UTF-32/UCS-32 character literal.
*/
#if ABC_CXX_CHAR32 == 2
   #define U32CL(ch) U ## ch
#elif ABC_CXX_CHAR32 == 1
   #define U32CL(ch) L ## ch
#elif ABC_CXX_CHAR32 == 0
   // No native type for char32_t, but we can at least use 16-bit wchar_t to store all Unicode BMP
   // characters correctly, and then cast that to our typedef’ed char32_t.
   #define U32CL(ch) ::abc::char32_t(L ## ch)
#endif

/** Defines a UTF-8 string literal. On some platforms, this relies on the source files being encoded
in UTF-8.

s
   String literal.
return
   UTF-8 string literal.
*/
#if ABC_CXX_UTF8LIT == 2
   #define U8SL(s) u8 ## s
#elif ABC_CXX_UTF8LIT == 1
   // Rely on the source files being encoded in UTF-8.
   #define U8SL(s) s
#endif

/** Defines a UTF-16 string literal. Not supported on all platforms; check with #ifdef before using.

s
   String literal.
return
   UTF-16 string literal.
*/
#if ABC_CXX_CHAR16 == 2
   #define U16SL(s) u ## s
#elif ABC_CXX_CHAR16 == 1
   #define U16SL(s) L ## s
#endif

/** Defines a UTF-32/UCS-32 string literal. Not supported on all platforms; check with #ifdef before
using.

s
   String literal.
return
   UTF-32 string literal.
*/
#if ABC_CXX_CHAR32 == 2
   #define U32SL(s) U ## s
#elif ABC_CXX_CHAR32 == 1
   #define U32SL(s) L ## s
#endif

/** UTF-* encoding supported by the host. */
#if ABC_HOST_API_WIN32 && defined(UNICODE)
   #define ABC_HOST_UTF 16
#else
   #define ABC_HOST_UTF 8
#endif

namespace abc {

/** Default UTF character type for the host. */
#if ABC_HOST_UTF == 8
   typedef char8_t char_t;
#elif ABC_HOST_UTF == 16
   typedef char16_t char_t;
#elif ABC_HOST_UTF == 32
   typedef char32_t char_t;
#endif

} //namespace abc

/** Defines a character literal of the default host character literal type.

ch
   Character literal.
return
   UCS character literal.
*/
#if ABC_HOST_UTF == 8
   #define CL(ch) U8CL(ch)
#elif ABC_HOST_UTF == 16
   #define CL(ch) U16CL(ch)
#elif ABC_HOST_UTF == 32
   #define CL(ch) U32CL(ch)
#endif

/** Defines a string literal of the default host string literal type.

s
   String literal.
return
   UTF string literal.
*/
#if ABC_HOST_UTF == 8
   #define SL(s) U8SL(s)
#elif ABC_HOST_UTF == 16
   #define SL(s) U16SL(s)
#elif ABC_HOST_UTF == 32
   #define SL(s) U32SL(s)
#endif

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

<|endoftext|>


<commit_before>#include "tests.h"
#include <cstdlib>
#include <chrono>
#include <memory>
#include <algorithm>
#include <unordered_set>
#ifdef _WIN32
    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    #include <conio.h> // _kbhit
#elif __ANDROID__
    #include <unistd.h> // usleep
    #include <android/log.h>
    #include <stdarg.h>
#else
    #include <unistd.h>
    #include <termios.h>
#endif

namespace rpp
{
    int test::asserts_failed;

    // there are initialization order issues with this global variable, so wrap it to guarantee initialization order
    static vector<test*>& all_tests() noexcept
    {
        static vector<test*> tests;
        return tests;
    }

    test::test(strview name, bool autorun) : name(name), auto_run(autorun)
    {
        all_tests().push_back(this);
    }

    test::~test()
    {
        if (!all_tests().empty())
        {
            auto it = find(all_tests().begin(), all_tests().end(), this);
            if (it != all_tests().end())
                all_tests().erase(it);
        }
    }

    void test::consolef(ConsoleColor color, const char* fmt, ...)
    {
        va_list ap;
        va_start(ap, fmt);
    #if _WIN32
        static HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
        static const int colormap[] = {
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // Default
            FOREGROUND_GREEN, // dark green
            FOREGROUND_RED | FOREGROUND_GREEN, // dark yellow
            FOREGROUND_RED, // dark red
        };
        if (color != Default) SetConsoleTextAttribute(console, colormap[color]);
        if (color == Red) vfprintf(stderr, fmt, ap);
        else              vfprintf(stdout, fmt, ap);
        if (color != Default) SetConsoleTextAttribute(console, colormap[Default]);
    #elif __ANDROID__
        int priority = 0;
        switch (color) {
            case Default: priority = ANDROID_LOG_DEBUG; break;
            case Green:   priority = ANDROID_LOG_INFO;  break;
            case Yellow:  priority = ANDROID_LOG_WARN;  break;
            case Red:     priority = ANDROID_LOG_ERROR; break;
        }
        __android_log_vprint(priority, "rpp", fmt, ap);
    #else // @todo Proper Linux & OSX implementations
        if (color == Red) vfprintf(stderr, fmt, ap);
        else              vfprintf(stdout, fmt, ap);
    #endif
    }

    void test::assert_failed(const char* file, int line, const char* fmt, ...)
    {
        const char* filename = file + int(strview{ file }.rfindany("\\/") - file) + 1;

        char message[8192];
        va_list ap; va_start(ap, fmt);
        vsnprintf(message, 8192, fmt, ap);

        ++asserts_failed;
        consolef(Red, "FAILURE %12s:%d    %s\n", filename, line, message);
    }

    void test::run_test(strview methodFilter)
    {
        char title[256];
        int len = methodFilter
            ? snprintf(title, sizeof(title), "--------  running '%s.%.*s'  --------", name.str, methodFilter.len, methodFilter.str)
            : snprintf(title, sizeof(title), "--------  running '%s'  --------", name.str);

        consolef(Yellow, "%s\n", title);
        run_init();

        if (methodFilter)
        {
            for (size_t i = 0u; i < test_count; ++i)
                if (test_funcs[i].name.find(methodFilter))
                    run_test(test_funcs[i]);
        }
        else
        {
            for (size_t i = 0u; i < test_count; ++i) {
                consolef(Yellow, "%s::%s\n", name.str, test_funcs[i].name.str);
                run_test(test_funcs[i]);
            }
        }

        run_cleanup();
        consolef(Yellow, "%s\n\n", (char*)memset(title, '-', (size_t)len)); // "-------------"
    }

    bool test::run_init()
    {
        try {
            init_test();
            return true;
        } catch (const std::exception& e) {
            consolef(Red, "Unhandled Exception in [%s]::TestInit(): %s\n", name.str, e.what());
            ++asserts_failed;
            return false;
        }
    }

    void test::run_cleanup()
    {
        try {
            cleanup_test();
        } catch (const std::exception& e) {
            consolef(Red, "Unhandled Exception in [%s]::TestCleanup(): %s\n", name.str, e.what());
            ++asserts_failed;
        }
    }

    void test::run_test(test_func& test)
    {
        try {
            (test.lambda.*test.func)();
        } catch (const std::exception& e) {
            consolef(Red, "Unhandled Exception in %s::%s: %s\n", name.str, test.name.str, e.what());
            ++asserts_failed;
        }
    }

    void test::sleep(int millis)
    {
        #if _WIN32
            Sleep(millis);
        #elif __ANDROID__
            usleep(useconds_t(millis) * 1000);
        #else
            usleep(millis * 1000);
        #endif
    }

#if !_WIN32 && !__ANDROID__ // Linux:
    static int _kbhit()
    {
        termios oldSettings; tcgetattr(STDIN_FILENO, &oldSettings);
        termios newSettings = oldSettings;
        newSettings.c_cc[VTIME] = 0;
        newSettings.c_cc[VMIN] = 0;
        newSettings.c_iflag &= ~(IXOFF);
        newSettings.c_lflag &= ~(ECHO | ICANON);
        tcsetattr(STDIN_FILENO, TCSANOW, &newSettings);

        char keycodes[16];
        int count = (int)::read(fileno(stdin), (void*)keycodes, 16);

        tcsetattr(STDIN_FILENO, TCSANOW, &oldSettings);

        return count == 0 ? 0 : keycodes[0];
    }
#endif

#if __ANDROID__
    static int _kbhit() { return 1; }
#endif

    static void pause(int millis = -1/*forever*/)
    {
        printf("\nPress any key to continue...\n");

        using namespace chrono;
        auto start = system_clock::now();
        while (!_kbhit())
        {
            if (millis != -1)
            {
                auto elapsed = duration_cast<milliseconds>(system_clock::now() - start);
                if (elapsed.count() >= millis)
                    break;
            }
            test::sleep(50);
        }
    }

    //TestImpl(test_test)
    //{
    //	Implement(test_test)
    //	{
    //		Assert(1 == 1);
    //	}
    //}
    //Instance;

    int test::run_tests(const char* testNamePattern)
    {
        return run_tests(&testNamePattern, 1);
    }

    int test::run_tests(const vector<string>& testNamePatterns)
    {
        vector<const char*> names;
        names.push_back("");
        for (const string& name : testNamePatterns) names.push_back(name.c_str());
        return run_tests((int)names.size(), (char**)names.data());
    }

    int test::run_tests(const char** testNamePatterns, int numPatterns)
    {
        vector<const char*> names;
        names.push_back("");
        names.insert(names.end(), testNamePatterns, testNamePatterns+numPatterns);
        return run_tests((int)names.size(), (char**)names.data());
    }

    int test::run_tests()
    {
        char empty[1] = "";
        char* argv[1] = { empty };
        return run_tests(1, argv);
    }

    int test::add_test_func(test_func func) // @note Because we can't dllexport std::vector
    {
        if (test_count == test_cap)
        {
            test_cap = test_funcs ? test_count * 2 : 8;
            auto* funcs = new test_func[test_cap];
            for (int i = 0; i < test_count; ++i) funcs[i] = move(test_funcs[i]);
            delete[] test_funcs;
            test_funcs = funcs;
        }
        test_funcs[test_count++] = move(func);
        return test_count - 1;
    }

    static void move_console_window()
    {
        // move console window to the other monitor to make test debugging more seamless
        // if debugger is attached with Visual Studio
    #if _WIN32 && _MSC_VER
        int numMonitors = 0;
        if (IsDebuggerPresent() && (numMonitors = GetSystemMetrics(SM_CMONITORS)) > 1)
        {
            vector<HMONITOR> mon;
            EnumDisplayMonitors(0, 0, [](HMONITOR monitor, HDC, RECT*, LPARAM data) {
                ((vector<HMONITOR>*)data)->push_back(monitor); return 1; }, (LPARAM)&mon);

            RECT consoleRect; GetWindowRect(GetConsoleWindow(), &consoleRect);
            HMONITOR consoleMon = MonitorFromRect(&consoleRect, MONITOR_DEFAULTTONEAREST);
            HMONITOR otherMon   = consoleMon != mon[0] ? mon[0] : mon[1];

            MONITORINFO consoleMI = { sizeof(MONITORINFO) };
            MONITORINFO otherMI   = { sizeof(MONITORINFO) };
            GetMonitorInfo(consoleMon, &consoleMI);
            GetMonitorInfo(otherMon, &otherMI);

            int x = consoleMI.rcMonitor.left > otherMI.rcMonitor.left // moveLeft ?
                ? otherMI.rcMonitor.right - (consoleRect.left - consoleMI.rcMonitor.left) - (consoleRect.right-consoleRect.left)
                : otherMI.rcMonitor.left  + (consoleRect.left - consoleMI.rcMonitor.left);
            int y = otherMI.rcMonitor.top + (consoleRect.top - consoleMI.rcMonitor.top);
            SetWindowPos(GetConsoleWindow(), 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
    #endif
    }

    int test::run_tests(int argc, char* argv[])
    {
        move_console_window();

        for (test* t : all_tests()) { // set the defaults
            if (!t->auto_run) t->test_enabled = false;
        }

        int numTest = 0;
        if (argc > 1)
        {
            // if arg is provided, we assume they are:
            // test_testname or testname or -test_testname or -testname
            // OR to run a specific test:  testname.specifictest
            unordered_set<strview> enabled, disabled;

            for (int iarg = 1; iarg < argc; ++iarg)
            {
                rpp::strview arg = argv[iarg];
                rpp::strview testName = arg.next('.');
                rpp::strview specific = arg.next('.');

                const bool enableTest = testName[0] != '-';
                if (!enableTest) testName.chomp_first();

                const bool exactMatch = testName.starts_with("test_");
                if (exactMatch) consolef(Yellow, "Filtering exact tests '%s'\n\n", argv[iarg]);
                else            consolef(Yellow, "Filtering substr tests '%s'\n\n", argv[iarg]);

                for (test* t : all_tests())
                {
                    if (( exactMatch && t->name == testName) ||
                        (!exactMatch && t->name.find(testName)))
                    {
                        t->test_specific = specific;
                        if (enableTest) enabled.insert(t->name);
                        else            disabled.insert(t->name);
                        break;
                    }
                }
            }

            if (disabled.size())
            {
                for (test* t : all_tests()) {
                    if (t->auto_run) { // only consider disabling auto_run tests
                        t->test_enabled = disabled.find(t->name) == disabled.end();
                        if (!t->test_enabled)
                            consolef(Red, "  Disabled %s\n", t->name.to_cstr());
                    }
                }
            }
            else if (enabled.size())
            {
                for (test* t : all_tests()) { // enable whatever was requested
                    t->test_enabled = enabled.find(t->name) != enabled.end();
                    if (t->test_enabled)
                        consolef(Green, "  Enabled %s\n", t->name.to_cstr());
                }
            }
        }
        else
        {
            consolef(Green, "Running all auto-run tests\n");
            for (test* t : all_tests())
                if (!t->auto_run && !t->test_enabled)
                    consolef(Yellow, "  Disabled NoAutoRun %s\n", t->name.to_cstr());
        }

        // run all the marked tests
        for (test* t : all_tests()) {
            if (t->test_enabled) {
                t->run_test(t->test_specific);
                ++numTest;
            }
        }

        if (test::asserts_failed)
        {
            consolef(Red, "\nWARNING: %d assertions failed!\n", test::asserts_failed);
            pause();
            return -1;
        }

        if (numTest > 0)
            consolef(Green, "\nSUCCESS: All test runs passed!\n");
        else
            consolef(Yellow, "\nNOTE: No tests were run! (out of %d)\n", (int)all_tests().size());

        #if _MSC_VER
            if (IsDebuggerPresent()) // only pause if we launched from Visual Studio
                pause();
        #endif
        return 0;
    }

} // namespace rpp

#if RPP_TESTS_DEFINE_MAIN
int main(int argc, char* argv[])
{
    return rpp::test::run_tests(argc, argv);
}
#endif
<commit_msg>Disable pausing on __APPLE__<commit_after>#include "tests.h"
#include <cstdlib>
#include <chrono>
#include <memory>
#include <algorithm>
#include <unordered_set>
#ifdef _WIN32
    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    #include <conio.h> // _kbhit
#elif __ANDROID__
    #include <unistd.h> // usleep
    #include <android/log.h>
    #include <stdarg.h>
#else
    #include <unistd.h>
    #include <termios.h>
#endif

namespace rpp
{
    int test::asserts_failed;

    // there are initialization order issues with this global variable, so wrap it to guarantee initialization order
    static vector<test*>& all_tests() noexcept
    {
        static vector<test*> tests;
        return tests;
    }

    test::test(strview name, bool autorun) : name(name), auto_run(autorun)
    {
        all_tests().push_back(this);
    }

    test::~test()
    {
        if (!all_tests().empty())
        {
            auto it = find(all_tests().begin(), all_tests().end(), this);
            if (it != all_tests().end())
                all_tests().erase(it);
        }
    }

    void test::consolef(ConsoleColor color, const char* fmt, ...)
    {
        va_list ap;
        va_start(ap, fmt);
    #if _WIN32
        static HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
        static const int colormap[] = {
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // Default
            FOREGROUND_GREEN, // dark green
            FOREGROUND_RED | FOREGROUND_GREEN, // dark yellow
            FOREGROUND_RED, // dark red
        };
        if (color != Default) SetConsoleTextAttribute(console, colormap[color]);
        if (color == Red) vfprintf(stderr, fmt, ap);
        else              vfprintf(stdout, fmt, ap);
        if (color != Default) SetConsoleTextAttribute(console, colormap[Default]);
    #elif __ANDROID__
        int priority = 0;
        switch (color) {
            case Default: priority = ANDROID_LOG_DEBUG; break;
            case Green:   priority = ANDROID_LOG_INFO;  break;
            case Yellow:  priority = ANDROID_LOG_WARN;  break;
            case Red:     priority = ANDROID_LOG_ERROR; break;
        }
        __android_log_vprint(priority, "rpp", fmt, ap);
    #else // @todo Proper Linux & OSX implementations
        if (color == Red) vfprintf(stderr, fmt, ap);
        else              vfprintf(stdout, fmt, ap);
    #endif
    }

    void test::assert_failed(const char* file, int line, const char* fmt, ...)
    {
        const char* filename = file + int(strview{ file }.rfindany("\\/") - file) + 1;

        char message[8192];
        va_list ap; va_start(ap, fmt);
        vsnprintf(message, 8192, fmt, ap);

        ++asserts_failed;
        consolef(Red, "FAILURE %12s:%d    %s\n", filename, line, message);
    }

    void test::run_test(strview methodFilter)
    {
        char title[256];
        int len = methodFilter
            ? snprintf(title, sizeof(title), "--------  running '%s.%.*s'  --------", name.str, methodFilter.len, methodFilter.str)
            : snprintf(title, sizeof(title), "--------  running '%s'  --------", name.str);

        consolef(Yellow, "%s\n", title);
        run_init();

        if (methodFilter)
        {
            for (size_t i = 0u; i < test_count; ++i)
                if (test_funcs[i].name.find(methodFilter))
                    run_test(test_funcs[i]);
        }
        else
        {
            for (size_t i = 0u; i < test_count; ++i) {
                consolef(Yellow, "%s::%s\n", name.str, test_funcs[i].name.str);
                run_test(test_funcs[i]);
            }
        }

        run_cleanup();
        consolef(Yellow, "%s\n\n", (char*)memset(title, '-', (size_t)len)); // "-------------"
    }

    bool test::run_init()
    {
        try {
            init_test();
            return true;
        } catch (const std::exception& e) {
            consolef(Red, "Unhandled Exception in [%s]::TestInit(): %s\n", name.str, e.what());
            ++asserts_failed;
            return false;
        }
    }

    void test::run_cleanup()
    {
        try {
            cleanup_test();
        } catch (const std::exception& e) {
            consolef(Red, "Unhandled Exception in [%s]::TestCleanup(): %s\n", name.str, e.what());
            ++asserts_failed;
        }
    }

    void test::run_test(test_func& test)
    {
        try {
            (test.lambda.*test.func)();
        } catch (const std::exception& e) {
            consolef(Red, "Unhandled Exception in %s::%s: %s\n", name.str, test.name.str, e.what());
            ++asserts_failed;
        }
    }

    void test::sleep(int millis)
    {
        #if _WIN32
            Sleep(millis);
        #elif __ANDROID__
            usleep(useconds_t(millis) * 1000);
        #else
            usleep(millis * 1000);
        #endif
    }

#if !_WIN32 && !__ANDROID__ && !__APPLE__ // Linux:
    static int _kbhit()
    {
        termios oldSettings; tcgetattr(STDIN_FILENO, &oldSettings);
        termios newSettings = oldSettings;
        newSettings.c_cc[VTIME] = 0;
        newSettings.c_cc[VMIN] = 0;
        newSettings.c_iflag &= ~(IXOFF);
        newSettings.c_lflag &= ~(ECHO | ICANON);
        tcsetattr(STDIN_FILENO, TCSANOW, &newSettings);

        char keycodes[16];
        int count = (int)::read(fileno(stdin), (void*)keycodes, 16);

        tcsetattr(STDIN_FILENO, TCSANOW, &oldSettings);

        return count == 0 ? 0 : keycodes[0];
    }
#endif

#if __ANDROID__ || __APPLE__
    static int _kbhit() { return 1; }
#endif

    static void pause(int millis = -1/*forever*/)
    {
        printf("\nPress any key to continue...\n");

        using namespace chrono;
        auto start = system_clock::now();
        while (!_kbhit())
        {
            if (millis != -1)
            {
                auto elapsed = duration_cast<milliseconds>(system_clock::now() - start);
                if (elapsed.count() >= millis)
                    break;
            }
            test::sleep(50);
        }
    }

    //TestImpl(test_test)
    //{
    //	Implement(test_test)
    //	{
    //		Assert(1 == 1);
    //	}
    //}
    //Instance;

    int test::run_tests(const char* testNamePattern)
    {
        return run_tests(&testNamePattern, 1);
    }

    int test::run_tests(const vector<string>& testNamePatterns)
    {
        vector<const char*> names;
        names.push_back("");
        for (const string& name : testNamePatterns) names.push_back(name.c_str());
        return run_tests((int)names.size(), (char**)names.data());
    }

    int test::run_tests(const char** testNamePatterns, int numPatterns)
    {
        vector<const char*> names;
        names.push_back("");
        names.insert(names.end(), testNamePatterns, testNamePatterns+numPatterns);
        return run_tests((int)names.size(), (char**)names.data());
    }

    int test::run_tests()
    {
        char empty[1] = "";
        char* argv[1] = { empty };
        return run_tests(1, argv);
    }

    int test::add_test_func(test_func func) // @note Because we can't dllexport std::vector
    {
        if (test_count == test_cap)
        {
            test_cap = test_funcs ? test_count * 2 : 8;
            auto* funcs = new test_func[test_cap];
            for (int i = 0; i < test_count; ++i) funcs[i] = move(test_funcs[i]);
            delete[] test_funcs;
            test_funcs = funcs;
        }
        test_funcs[test_count++] = move(func);
        return test_count - 1;
    }

    static void move_console_window()
    {
        // move console window to the other monitor to make test debugging more seamless
        // if debugger is attached with Visual Studio
    #if _WIN32 && _MSC_VER
        int numMonitors = 0;
        if (IsDebuggerPresent() && (numMonitors = GetSystemMetrics(SM_CMONITORS)) > 1)
        {
            vector<HMONITOR> mon;
            EnumDisplayMonitors(0, 0, [](HMONITOR monitor, HDC, RECT*, LPARAM data) {
                ((vector<HMONITOR>*)data)->push_back(monitor); return 1; }, (LPARAM)&mon);

            RECT consoleRect; GetWindowRect(GetConsoleWindow(), &consoleRect);
            HMONITOR consoleMon = MonitorFromRect(&consoleRect, MONITOR_DEFAULTTONEAREST);
            HMONITOR otherMon   = consoleMon != mon[0] ? mon[0] : mon[1];

            MONITORINFO consoleMI = { sizeof(MONITORINFO) };
            MONITORINFO otherMI   = { sizeof(MONITORINFO) };
            GetMonitorInfo(consoleMon, &consoleMI);
            GetMonitorInfo(otherMon, &otherMI);

            int x = consoleMI.rcMonitor.left > otherMI.rcMonitor.left // moveLeft ?
                ? otherMI.rcMonitor.right - (consoleRect.left - consoleMI.rcMonitor.left) - (consoleRect.right-consoleRect.left)
                : otherMI.rcMonitor.left  + (consoleRect.left - consoleMI.rcMonitor.left);
            int y = otherMI.rcMonitor.top + (consoleRect.top - consoleMI.rcMonitor.top);
            SetWindowPos(GetConsoleWindow(), 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
        }
    #endif
    }

    int test::run_tests(int argc, char* argv[])
    {
        move_console_window();

        for (test* t : all_tests()) { // set the defaults
            if (!t->auto_run) t->test_enabled = false;
        }

        int numTest = 0;
        if (argc > 1)
        {
            // if arg is provided, we assume they are:
            // test_testname or testname or -test_testname or -testname
            // OR to run a specific test:  testname.specifictest
            unordered_set<strview> enabled, disabled;

            for (int iarg = 1; iarg < argc; ++iarg)
            {
                rpp::strview arg = argv[iarg];
                rpp::strview testName = arg.next('.');
                rpp::strview specific = arg.next('.');

                const bool enableTest = testName[0] != '-';
                if (!enableTest) testName.chomp_first();

                const bool exactMatch = testName.starts_with("test_");
                if (exactMatch) consolef(Yellow, "Filtering exact tests '%s'\n\n", argv[iarg]);
                else            consolef(Yellow, "Filtering substr tests '%s'\n\n", argv[iarg]);

                for (test* t : all_tests())
                {
                    if (( exactMatch && t->name == testName) ||
                        (!exactMatch && t->name.find(testName)))
                    {
                        t->test_specific = specific;
                        if (enableTest) enabled.insert(t->name);
                        else            disabled.insert(t->name);
                        break;
                    }
                }
            }

            if (disabled.size())
            {
                for (test* t : all_tests()) {
                    if (t->auto_run) { // only consider disabling auto_run tests
                        t->test_enabled = disabled.find(t->name) == disabled.end();
                        if (!t->test_enabled)
                            consolef(Red, "  Disabled %s\n", t->name.to_cstr());
                    }
                }
            }
            else if (enabled.size())
            {
                for (test* t : all_tests()) { // enable whatever was requested
                    t->test_enabled = enabled.find(t->name) != enabled.end();
                    if (t->test_enabled)
                        consolef(Green, "  Enabled %s\n", t->name.to_cstr());
                }
            }
        }
        else
        {
            consolef(Green, "Running all auto-run tests\n");
            for (test* t : all_tests())
                if (!t->auto_run && !t->test_enabled)
                    consolef(Yellow, "  Disabled NoAutoRun %s\n", t->name.to_cstr());
        }

        // run all the marked tests
        for (test* t : all_tests()) {
            if (t->test_enabled) {
                t->run_test(t->test_specific);
                ++numTest;
            }
        }

        if (test::asserts_failed)
        {
            consolef(Red, "\nWARNING: %d assertions failed!\n", test::asserts_failed);
            #if _MSC_VER
                pause();
            #endif
            return -1;
        }

        if (numTest > 0)
            consolef(Green, "\nSUCCESS: All test runs passed!\n");
        else
            consolef(Yellow, "\nNOTE: No tests were run! (out of %d)\n", (int)all_tests().size());

        #if _MSC_VER
            if (IsDebuggerPresent()) // only pause if we launched from Visual Studio
                pause();
        #endif
        return 0;
    }

} // namespace rpp

#if RPP_TESTS_DEFINE_MAIN
int main(int argc, char* argv[])
{
    return rpp::test::run_tests(argc, argv);
}
#endif
<|endoftext|>


<commit_before>/// Causal Dynamical Triangulations in C++ using CGAL
///
/// Copyright © 2018 Adam Getchell
///
/// Geometric quantities of Manifold used by MoveAlgorithm.
///
/// @file  Geometry.hpp
/// @brief Data structures for geometry
/// @author Adam Getchell

#ifndef CDT_PLUSPLUS_GEOMETRY_HPP
#define CDT_PLUSPLUS_GEOMETRY_HPP

#include <S3Triangulation.hpp>
#include <algorithm>
#include <cstddef>
#include <gsl/gsl>

enum class Cell_type
{
  THREE_ONE = 31,
  TWO_TWO   = 22,
  ONE_THREE = 13
};

/// Geometry class template
/// @tparam dimension Dimensionality of geometry
template <std::size_t dimension>
struct Geometry;

/// 3D Geometry
template <>
struct Geometry<3>
{
  /// @brief Default ctor
  Geometry()
      : number_of_vertices{0}
      , number_of_edges{0}
      , number_of_faces{0}
      , number_of_cells{0}
  {}

  /// @brief Constructor with triangulation
  /// @param triangulation Triangulation for which Geometry is being
  /// calculated
  explicit Geometry(const std::unique_ptr<Delaunay3>& triangulation)
      : number_of_vertices{triangulation->number_of_vertices()}
      , number_of_edges{triangulation->number_of_finite_edges()}
      , number_of_faces{triangulation->number_of_finite_facets()}
      , number_of_cells{triangulation->number_of_finite_cells()}
      , cells{classify_cells(collect_cells(triangulation))}
      , edges{collect_edges(triangulation)}
      , vertices{collect_vertices(triangulation)}
      , three_one{filter_cells(cells, Cell_type::THREE_ONE)}
      , two_two{filter_cells(cells, Cell_type::TWO_TWO)}
      , one_three{filter_cells(cells, Cell_type::ONE_THREE)}
  {}

  /// @brief Collect all finite cells of the triangulation
  /// @tparam T Reference type of triangulation
  /// @param universe Reference to triangulation
  /// @return Vector of all the finite cells in the triangulation
  template <typename T>
  std::vector<Cell_handle> collect_cells(T& universe)
  {
    Expects(universe != nullptr);
    std::vector<Cell_handle> init_cells;
    init_cells.reserve(number_of_cells);
    Delaunay3::Finite_cells_iterator cit;
    for (cit = universe->finite_cells_begin();
         cit != universe->finite_cells_end(); ++cit)
    { init_cells.emplace_back(cit); }
    Ensures(init_cells.size() == universe->number_of_finite_cells());
    return init_cells;
  }

  std::vector<Cell_handle> classify_cells(std::vector<Cell_handle> cells)
  {
    Expects(!cells.empty());
    std::vector<Vertex_handle> cell_vertices;
    cell_vertices.reserve(4);
    std::vector<size_t> vertex_timevalues;
    vertex_timevalues.reserve(4);
    for (auto& c : cells)
    {
      std::cout << "Cell info was " << c->info() << '\n';
      for (size_t j = 0; j < 4; ++j)
      {
        cell_vertices.emplace_back(c->vertex(j));
        vertex_timevalues.emplace_back(c->vertex(j)->info());
        std::cout << "Cell vertex " << j << " has timevalue "
                  << c->vertex(j)->info() << '\n';
      }

      auto max_timevalue =
          std::max_element(vertex_timevalues.begin(), vertex_timevalues.end());
      auto max_timevalue_vertices =
          std::count_if(cell_vertices.begin(), cell_vertices.end(),
                        [max_timevalue](auto const& vertex) {
                          return vertex->info() == *max_timevalue;
                        });

      switch (max_timevalue_vertices)
      {
        case 1:
          c->info() = static_cast<size_t>(Cell_type::ONE_THREE);
          break;
        case 2:
          c->info() = static_cast<size_t>(Cell_type::TWO_TWO);
          break;
        case 3:
          c->info() = static_cast<size_t>(Cell_type::THREE_ONE);
          break;
        default:
          throw std::logic_error("Mis-classified cell.");
      }
      std::cout << "Max timevalue is " << *max_timevalue << '\n';
      std::cout << "There are " << max_timevalue_vertices
                << " vertices with max timeslice in the cell.\n";
      std::cout << "Cell info is now " << c->info() << '\n';
      std::cout << "Next cell:\n";
      cell_vertices.clear();
      vertex_timevalues.clear();
    }
    return cells;
  }

  /// @brief Filter simplices by Cell_type
  /// @param cells_v The vector of simplices to filter
  /// @param cell_t The Cell_type to filter by
  /// @return A vector of Cell_type simplices
  std::vector<Cell_handle> filter_cells(std::vector<Cell_handle> cells_v,
                                        const Cell_type          cell_t)
  {
    std::vector<Cell_handle> filtered_cells(cells_v.size());
    auto                     it =
        std::copy_if(cells_v.begin(), cells_v.end(), filtered_cells.begin(),
                     [&](auto const& cell) {
                       return cell->info() == static_cast<std::size_t>(cell_t);
                     });
    filtered_cells.resize(std::distance(filtered_cells.begin(), it));
    return filtered_cells;
  }

  /// @brief Collect all finite edges of the triangulation
  /// @tparam T Reference type of triangulation
  /// @param universe Reference to triangulation
  /// @return Vector of all the finite edges in the triangulation
  template <typename T>
  std::vector<Edge_handle> collect_edges(T& universe)
  {
    Expects(universe != nullptr);
    std::vector<Edge_handle> init_edges;
    init_edges.reserve(number_of_edges);
    Delaunay3::Finite_edges_iterator eit;
    for (eit = universe->finite_edges_begin();
         eit != universe->finite_edges_end(); ++eit)
    {
      Cell_handle ch = eit->first;
      Edge_handle thisEdge{ch, ch->index(ch->vertex(eit->second)),
                           ch->index(ch->vertex(eit->third))};
      init_edges.emplace_back(thisEdge);
    }
    Ensures(init_edges.size() == universe->number_of_finite_edges());
    return init_edges;
  }

  /// @brief Collect all finite vertices of the triangulation
  /// @tparam T Reference type of triangulation
  /// @param universe Reference to triangulation
  /// @return Vector of all finite vertices in the triangulation
  template <typename T>
  std::vector<Vertex_handle> collect_vertices(T& universe)
  {
    Expects(universe != nullptr);
    std::vector<Vertex_handle> init_vertices;
    init_vertices.reserve(number_of_vertices);
    Delaunay3::Finite_vertices_iterator fit;
    for (fit = universe->finite_vertices_begin();
         fit != universe->finite_vertices_end(); ++fit)
    { init_vertices.emplace_back(fit); }
    Ensures(init_vertices.size() == universe->number_of_vertices());
    return init_vertices;
  }

  std::size_t                number_of_vertices;
  std::size_t                number_of_edges;
  std::size_t                number_of_faces;
  std::size_t                number_of_cells;
  std::vector<Cell_handle>   cells;
  std::vector<Edge_handle>   edges;
  std::vector<Vertex_handle> vertices;
  std::vector<Cell_handle>   three_one;
  std::vector<Cell_handle>   two_two;
  std::vector<Cell_handle>   one_three;
  std::vector<Edge_handle>   timelike_edges;
  std::vector<Edge_handle>   spacelike_edges;
};

using Geometry3 = Geometry<3>;

#endif  // CDT_PLUSPLUS_GEOMETRY_HPP<commit_msg>Some best practices<commit_after>/// Causal Dynamical Triangulations in C++ using CGAL
///
/// Copyright © 2018 Adam Getchell
///
/// Geometric quantities of Manifold used by MoveAlgorithm.
///
/// @file  Geometry.hpp
/// @brief Data structures for geometry
/// @author Adam Getchell

#ifndef CDT_PLUSPLUS_GEOMETRY_HPP
#define CDT_PLUSPLUS_GEOMETRY_HPP

#include <S3Triangulation.hpp>
#include <algorithm>
#include <cstddef>
#include <gsl/gsl>

enum class Cell_type
{
  THREE_ONE = 31,
  TWO_TWO   = 22,
  ONE_THREE = 13
};

/// Geometry class template
/// @tparam dimension Dimensionality of geometry
template <std::size_t dimension>
struct Geometry;

/// 3D Geometry
template <>
struct Geometry<3>
{
  /// @brief Default ctor
  Geometry()
      : number_of_vertices{0}
      , number_of_edges{0}
      , number_of_faces{0}
      , number_of_cells{0}
  {}

  /// @brief Constructor with triangulation
  /// @param triangulation Triangulation for which Geometry is being
  /// calculated
  explicit Geometry(const std::unique_ptr<Delaunay3>& triangulation)
      : number_of_vertices{triangulation->number_of_vertices()}
      , number_of_edges{triangulation->number_of_finite_edges()}
      , number_of_faces{triangulation->number_of_finite_facets()}
      , number_of_cells{triangulation->number_of_finite_cells()}
      , cells{classify_cells(collect_cells(triangulation))}
      , edges{collect_edges(triangulation)}
      , vertices{collect_vertices(triangulation)}
      , three_one{filter_cells(cells, Cell_type::THREE_ONE)}
      , two_two{filter_cells(cells, Cell_type::TWO_TWO)}
      , one_three{filter_cells(cells, Cell_type::ONE_THREE)}
  {}

  /// @brief Collect all finite cells of the triangulation
  /// @tparam T Reference type of triangulation
  /// @param universe Reference to triangulation
  /// @return Vector of all the finite cells in the triangulation
  template <typename T>
  [[nodiscard]] auto collect_cells(T& universe) -> std::vector<Cell_handle>
  {
    Expects(universe != nullptr);
    std::vector<Cell_handle> init_cells;
    init_cells.reserve(number_of_cells);
    Delaunay3::Finite_cells_iterator cit;
    for (cit = universe->finite_cells_begin();
         cit != universe->finite_cells_end(); ++cit)
    { init_cells.emplace_back(cit); }
    Ensures(init_cells.size() == universe->number_of_finite_cells());
    return init_cells;
  }

  [[nodiscard]] auto classify_cells(std::vector<Cell_handle> cells)
      -> std::vector<Cell_handle>
  {
    Expects(!cells.empty());
    std::vector<Vertex_handle> cell_vertices;
    cell_vertices.reserve(4);
    std::vector<size_t> vertex_timevalues;
    vertex_timevalues.reserve(4);
    for (auto& c : cells)
    {
      std::cout << "Cell info was " << c->info() << '\n';
      for (size_t j = 0; j < 4; ++j)
      {
        cell_vertices.emplace_back(c->vertex(j));
        vertex_timevalues.emplace_back(c->vertex(j)->info());
        std::cout << "Cell vertex " << j << " has timevalue "
                  << c->vertex(j)->info() << '\n';
      }

      auto max_timevalue =
          std::max_element(vertex_timevalues.begin(), vertex_timevalues.end());
      auto max_timevalue_vertices =
          std::count_if(cell_vertices.begin(), cell_vertices.end(),
                        [max_timevalue](auto const& vertex) {
                          return vertex->info() == *max_timevalue;
                        });

      switch (max_timevalue_vertices)
      {
        case 1:
          c->info() = static_cast<size_t>(Cell_type::ONE_THREE);
          break;
        case 2:
          c->info() = static_cast<size_t>(Cell_type::TWO_TWO);
          break;
        case 3:
          c->info() = static_cast<size_t>(Cell_type::THREE_ONE);
          break;
        default:
          throw std::logic_error("Mis-classified cell.");
      }
      std::cout << "Max timevalue is " << *max_timevalue << '\n';
      std::cout << "There are " << max_timevalue_vertices
                << " vertices with max timeslice in the cell.\n";
      std::cout << "Cell info is now " << c->info() << '\n';
      std::cout << "Next cell:\n";
      cell_vertices.clear();
      vertex_timevalues.clear();
    }
    return cells;
  }

  /// @brief Filter simplices by Cell_type
  /// @param cells_v The vector of simplices to filter
  /// @param cell_t The Cell_type to filter by
  /// @return A vector of Cell_type simplices
  [[nodiscard]] auto filter_cells(std::vector<Cell_handle> cells_v,
                                  const Cell_type          cell_t)
      -> std::vector<Cell_handle>
  {
    std::vector<Cell_handle> filtered_cells(cells_v.size());
    auto                     it =
        std::copy_if(cells_v.begin(), cells_v.end(), filtered_cells.begin(),
                     [&](auto const& cell) {
                       return cell->info() == static_cast<std::size_t>(cell_t);
                     });
    filtered_cells.resize(std::distance(filtered_cells.begin(), it));
    return filtered_cells;
  }

  /// @brief Collect all finite edges of the triangulation
  /// @tparam T Reference type of triangulation
  /// @param universe Reference to triangulation
  /// @return Vector of all the finite edges in the triangulation
  template <typename T>
  [[nodiscard]] auto collect_edges(T& universe) -> std::vector<Edge_handle>
  {
    Expects(universe != nullptr);
    std::vector<Edge_handle> init_edges;
    init_edges.reserve(number_of_edges);
    Delaunay3::Finite_edges_iterator eit;
    for (eit = universe->finite_edges_begin();
         eit != universe->finite_edges_end(); ++eit)
    {
      Cell_handle ch = eit->first;
      Edge_handle thisEdge{ch, ch->index(ch->vertex(eit->second)),
                           ch->index(ch->vertex(eit->third))};
      init_edges.emplace_back(thisEdge);
    }
    Ensures(init_edges.size() == universe->number_of_finite_edges());
    return init_edges;
  }

  /// @brief Collect all finite vertices of the triangulation
  /// @tparam T Reference type of triangulation
  /// @param universe Reference to triangulation
  /// @return Vector of all finite vertices in the triangulation
  template <typename T>
  [[nodiscard]] auto collect_vertices(T& universe) -> std::vector<Vertex_handle>
  {
    Expects(universe != nullptr);
    std::vector<Vertex_handle> init_vertices;
    init_vertices.reserve(number_of_vertices);
    Delaunay3::Finite_vertices_iterator fit;
    for (fit = universe->finite_vertices_begin();
         fit != universe->finite_vertices_end(); ++fit)
    { init_vertices.emplace_back(fit); }
    Ensures(init_vertices.size() == universe->number_of_vertices());
    return init_vertices;
  }

  std::size_t                number_of_vertices;
  std::size_t                number_of_edges;
  std::size_t                number_of_faces;
  std::size_t                number_of_cells;
  std::vector<Cell_handle>   cells;
  std::vector<Edge_handle>   edges;
  std::vector<Vertex_handle> vertices;
  std::vector<Cell_handle>   three_one;
  std::vector<Cell_handle>   two_two;
  std::vector<Cell_handle>   one_three;
  std::vector<Edge_handle>   timelike_edges;
  std::vector<Edge_handle>   spacelike_edges;
};

using Geometry3 = Geometry<3>;

#endif  // CDT_PLUSPLUS_GEOMETRY_HPP<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include "AliTaskCDBconnect.h"

#include <TChain.h>
#include <TFile.h>
#include <TGeoGlobalMagField.h>
#include "TGeoManager.h"

#include "AliAnalysisManager.h"
#include "AliGeomManager.h"
#include "AliCDBManager.h"
#include "AliGRPManager.h"
#include "AliESDEvent.h"
#include "AliESDInputHandler.h"
#include "AliLog.h"

ClassImp(AliTaskCDBconnect)

//______________________________________________________________________________
AliTaskCDBconnect::AliTaskCDBconnect():
           AliAnalysisTask(),
           fRun(0),
           fRunChanged(kFALSE),
           fESDhandler(NULL),
           fESD(NULL),
           fGRPManager(NULL)
{
// Dummy constructor
}

//______________________________________________________________________________
AliTaskCDBconnect::AliTaskCDBconnect(const char* name):
           AliAnalysisTask(name, "ESD analysis tender car"),
           fRun(0),
           fRunChanged(kFALSE),
           fESDhandler(NULL),
           fESD(NULL),
           fGRPManager(NULL)
{
// Default constructor
  AliCDBManager *cdb = AliCDBManager::Instance();
  cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  cdb->SetRun(0);
  DefineInput (0, TChain::Class());
//  DefineOutput(0,  AliESDEvent::Class());
}

//______________________________________________________________________________
AliTaskCDBconnect::~AliTaskCDBconnect()
{
// Destructor
  if (fGRPManager) delete fGRPManager;
//  if (gGeoManager) delete gGeoManager;
}

//______________________________________________________________________________
void AliTaskCDBconnect::LocalInit()
{
// Init CDB locally if run number is defined.
}

//______________________________________________________________________________
void AliTaskCDBconnect::ConnectInputData(Option_t* /*option*/)
{
// Connect the input data, create CDB manager.
}

//______________________________________________________________________________
void AliTaskCDBconnect::InitGRP()
{
// Initialize geometry and mag. field
  if (!fGRPManager) {
  // magnetic field
    if (!TGeoGlobalMagField::Instance()->GetField()) {
      printf("AliCDBconnect: #### Loading field map...\n");
      fGRPManager = new AliGRPManager();
      if(!fGRPManager->ReadGRPEntry()) {
        AliError("Cannot get GRP entry");
      }
      if( !fGRPManager->SetMagField() ) {
        AliError("Problem with magnetic field setup");
      }
    }

    // geometry
    if (!gGeoManager) {
      printf("AliCDBconnect: #### Loading geometry...\n");
      AliGeomManager::LoadGeometry();
      if( !AliGeomManager::ApplyAlignObjsFromCDB("GRP ITS TPC") ) {
        AliError("Problem with align objects");
      }
    }
  }
}

//______________________________________________________________________________
void AliTaskCDBconnect::CreateOutputObjects()
{
// Init CDB locally if run number is defined.
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) AliFatal("No analysis manager");
  fESDhandler = dynamic_cast<AliESDInputHandler *>(mgr->GetInputEventHandler());

  if (!fESDhandler) {
     AliFatal("No ESD input event handler connected");
     return;
  }
  // Try to get event number before the first event is read (this has precedence
  // over existing fRun)
  Int_t run = mgr->GetRunFromPath();
  if (!run) {
     AliWarning("AliTaskCDBconnect: Could not set run from path");
     if (!fRun) {
        AliError("AliTaskCDBconnect: Run not set - no CDB connection");
        return;
     }
  }
  // Create CDB manager
  AliCDBManager *cdb = AliCDBManager::Instance();
  // If CDB is already locked, return
  if (cdb->GetLock()) return;
  // SetDefault storage. Specific storages must be set by TaskCDBconnectSupply::Init()
  //  cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  if (cdb->IsDefaultStorageSet()) {
     AliError("AliTaskCDBconnect: CDB default storage already set!");
  } else {
     cdb->SetDefaultStorage("alien://?Folder=/alice/data/2010/OCDB");
  }
  if (run && (run != fRun)) {
     fRunChanged = kTRUE;
     fRun = run;
  } else {
     fRunChanged = kFALSE;
  }
  // Set run
  printf("AliCDBconnect: #### Setting run to: %d\n", fRun);
  cdb->SetRun(fRun);
  // Initialize GRP manager only once
  if (fRun) InitGRP();
}

//______________________________________________________________________________
Bool_t AliTaskCDBconnect::Notify()
{
// Init CDB locally if run number is defined.
  CreateOutputObjects();
  return kTRUE;
}

//______________________________________________________________________________
void AliTaskCDBconnect::Exec(Option_t* /*option*/)
{
//
// Execute all supplied analysis of one event. Notify run change via RunChanged().
  fESD = fESDhandler->GetEvent();
  // Intercept when the run number changed
  if (fRun != fESD->GetRunNumber()) {
    fRunChanged = kTRUE;
    fRun = fESD->GetRunNumber();
    Warning("Exec", "Run number changed in ESDEvent to %d", fRun);
    AliCDBManager::Instance()->SetRun(fRun);
  }
//  PostData(0, fESD);
}

//______________________________________________________________________________
void AliTaskCDBconnect::Terminate(Option_t *)
{
// Initialize CDB also in Terminate
   CreateOutputObjects();
}
<commit_msg>Changed back to raw://<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include "AliTaskCDBconnect.h"

#include <TChain.h>
#include <TFile.h>
#include <TGeoGlobalMagField.h>
#include "TGeoManager.h"

#include "AliAnalysisManager.h"
#include "AliGeomManager.h"
#include "AliCDBManager.h"
#include "AliGRPManager.h"
#include "AliESDEvent.h"
#include "AliESDInputHandler.h"
#include "AliLog.h"

ClassImp(AliTaskCDBconnect)

//______________________________________________________________________________
AliTaskCDBconnect::AliTaskCDBconnect():
           AliAnalysisTask(),
           fRun(0),
           fRunChanged(kFALSE),
           fESDhandler(NULL),
           fESD(NULL),
           fGRPManager(NULL)
{
// Dummy constructor
}

//______________________________________________________________________________
AliTaskCDBconnect::AliTaskCDBconnect(const char* name):
           AliAnalysisTask(name, "ESD analysis tender car"),
           fRun(0),
           fRunChanged(kFALSE),
           fESDhandler(NULL),
           fESD(NULL),
           fGRPManager(NULL)
{
// Default constructor
  AliCDBManager *cdb = AliCDBManager::Instance();
  cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  cdb->SetRun(0);
  DefineInput (0, TChain::Class());
//  DefineOutput(0,  AliESDEvent::Class());
}

//______________________________________________________________________________
AliTaskCDBconnect::~AliTaskCDBconnect()
{
// Destructor
  if (fGRPManager) delete fGRPManager;
//  if (gGeoManager) delete gGeoManager;
}

//______________________________________________________________________________
void AliTaskCDBconnect::LocalInit()
{
// Init CDB locally if run number is defined.
}

//______________________________________________________________________________
void AliTaskCDBconnect::ConnectInputData(Option_t* /*option*/)
{
// Connect the input data, create CDB manager.
}

//______________________________________________________________________________
void AliTaskCDBconnect::InitGRP()
{
// Initialize geometry and mag. field
  if (!fGRPManager) {
  // magnetic field
    if (!TGeoGlobalMagField::Instance()->GetField()) {
      printf("AliCDBconnect: #### Loading field map...\n");
      fGRPManager = new AliGRPManager();
      if(!fGRPManager->ReadGRPEntry()) {
        AliError("Cannot get GRP entry");
      }
      if( !fGRPManager->SetMagField() ) {
        AliError("Problem with magnetic field setup");
      }
    }

    // geometry
    if (!gGeoManager) {
      printf("AliCDBconnect: #### Loading geometry...\n");
      AliGeomManager::LoadGeometry();
      if( !AliGeomManager::ApplyAlignObjsFromCDB("GRP ITS TPC") ) {
        AliError("Problem with align objects");
      }
    }
  }
}

//______________________________________________________________________________
void AliTaskCDBconnect::CreateOutputObjects()
{
// Init CDB locally if run number is defined.
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) AliFatal("No analysis manager");
  fESDhandler = dynamic_cast<AliESDInputHandler *>(mgr->GetInputEventHandler());

  if (!fESDhandler) {
     AliFatal("No ESD input event handler connected");
     return;
  }
  // Try to get event number before the first event is read (this has precedence
  // over existing fRun)
  Int_t run = mgr->GetRunFromPath();
  if (!run) {
     AliWarning("AliTaskCDBconnect: Could not set run from path");
     if (!fRun) {
        AliError("AliTaskCDBconnect: Run not set - no CDB connection");
        return;
     }
  }
  // Create CDB manager
  AliCDBManager *cdb = AliCDBManager::Instance();
  // If CDB is already locked, return
  if (cdb->GetLock()) return;
  // SetDefault storage. Specific storages must be set by TaskCDBconnectSupply::Init()
  //  cdb->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  if (cdb->IsDefaultStorageSet()) {
     AliError("AliTaskCDBconnect: CDB default storage already set!");
  } else {
     cdb->SetDefaultStorage("raw://");
  }
  if (run && (run != fRun)) {
     fRunChanged = kTRUE;
     fRun = run;
  } else {
     fRunChanged = kFALSE;
  }
  // Set run
  printf("AliCDBconnect: #### Setting run to: %d\n", fRun);
  cdb->SetRun(fRun);
  // Initialize GRP manager only once
  if (fRun) InitGRP();
}

//______________________________________________________________________________
Bool_t AliTaskCDBconnect::Notify()
{
// Init CDB locally if run number is defined.
  CreateOutputObjects();
  return kTRUE;
}

//______________________________________________________________________________
void AliTaskCDBconnect::Exec(Option_t* /*option*/)
{
//
// Execute all supplied analysis of one event. Notify run change via RunChanged().
  fESD = fESDhandler->GetEvent();
  // Intercept when the run number changed
  if (fRun != fESD->GetRunNumber()) {
    fRunChanged = kTRUE;
    fRun = fESD->GetRunNumber();
    Warning("Exec", "Run number changed in ESDEvent to %d", fRun);
    AliCDBManager::Instance()->SetRun(fRun);
  }
//  PostData(0, fESD);
}

//______________________________________________________________________________
void AliTaskCDBconnect::Terminate(Option_t *)
{
// Initialize CDB also in Terminate
   CreateOutputObjects();
}
<|endoftext|>


<commit_before>#include <stan/version.hpp>
#include <gtest/gtest.h>

TEST(Stan, macro) {
  EXPECT_EQ(2, STAN_MAJOR);
  EXPECT_EQ(22, STAN_MINOR);
  EXPECT_EQ(0, STAN_PATCH);
}

TEST(Stan, version) {
  EXPECT_EQ("2", stan::MAJOR_VERSION);
  EXPECT_EQ("22", stan::MINOR_VERSION);
  EXPECT_EQ("0", stan::PATCH_VERSION);
}
<commit_msg>Updated stan version test.<commit_after>#include <stan/version.hpp>
#include <gtest/gtest.h>

TEST(Stan, macro) {
  EXPECT_EQ(2, STAN_MAJOR);
  EXPECT_EQ(22, STAN_MINOR);
  EXPECT_EQ(1, STAN_PATCH);
}

TEST(Stan, version) {
  EXPECT_EQ("2", stan::MAJOR_VERSION);
  EXPECT_EQ("22", stan::MINOR_VERSION);
  EXPECT_EQ("1", stan::PATCH_VERSION);
}
<|endoftext|>


<commit_before>#include "dsa/message.h"
#include "gtest/gtest.h"

using namespace dsa;

class HandshakeF3MessageExt : public HandshakeF3Message {
 public:
  HandshakeF3MessageExt() : HandshakeF3Message() {}

  void update_static_header_ext() {
    HandshakeF3Message::update_static_header();
  }

  bool check_static_headers(uint8_t *expected_values, size_t size) {
    uint8_t buf[1024];
    static_headers.write(buf);

    return (memcmp(expected_values, buf, size) == 0);
  }
};

TEST(MessageTest, HandshakeF3__Constructor_01) {
  HandshakeF3MessageExt message;

  /*
  uint16_t session_id_length;
  std::string session_id;
  uint16_t path_length;
  std::string path;
  std::vector<uint8_t> other_auth;
  */

  message.session_id_length = 64;
  std::string session_id("session-id123456789012345678901234567890123456789012345678901234");
  message.session_id = session_id;

  message.path = 32;
  std::string path("path5678901234567890123456789012");
  message.path = path;

  uint8_t auth[] = "auth5678901234567890123456789012";
  message.other_auth = std::vector<uint8_t>(auth, auth + Message::AuthLength);

  message.update_static_header_ext();

  uint8_t buf[1024];
  message.write(buf);

  // 15 + 2 + 64 + 2 + 32 + 32 = 147
  uint8_t expected_values[147];

  uint32_t message_size = 147;
  uint16_t header_size = message_size;
  MessageType type = MessageType::Handshake2;
  uint32_t request_id = 0;
  uint32_t ack_id = 0;

  std::memcpy(&expected_values[StaticHeaders::MessageSizeOffset], &message_size,
              sizeof(uint32_t));
  std::memcpy(&expected_values[StaticHeaders::HeaderSizeOffset], &header_size,
              sizeof(uint16_t));
  std::memcpy(&expected_values[StaticHeaders::TypeOffset], &type,
              sizeof(uint8_t));
  std::memcpy(&expected_values[StaticHeaders::RequestIdOffset], &request_id,
              sizeof(request_id));
  std::memcpy(&expected_values[StaticHeaders::AckIdOffset], &ack_id,
              sizeof(ack_id));

  uint8_t SessionIdLengthOffset = StaticHeaders::TotalSize;
  uint8_t SessionIdOffset = SessionIdLengthOffset + sizeof(uint16_t);
  uint8_t PathLengthOffset = SessionIdOffset + message.session_id.size();
  uint8_t PathOffset = PathLengthOffset + sizeof(uint16_t);
  uint8_t AuthOffset = PathOffset + Message::AuthLength;

  std::memcpy(&expected_values[SessionIdLengthOffset], &message.session_id_length,  sizeof(message.session_id_length));
  std::memcpy(&expected_values[SessionIdOffset], message.session_id.data(), message.session_id.size());
  std::memcpy(&expected_values[PathLengthOffset], &message.path_length,  sizeof(message.path_length));
  std::memcpy(&expected_values[PathOffset], message.path.data(), message.path.size());
  std::memcpy(&expected_values[AuthOffset], message.other_auth.data(), Message::AuthLength);

//  EXPECT_EQ(0, memcmp(expected_values, buf, message_size));

}
<commit_msg>update handshake unittests<commit_after>#include "dsa/message.h"
#include "gtest/gtest.h"

using namespace dsa;

class HandshakeF3MessageExt : public HandshakeF3Message {
 public:
  HandshakeF3MessageExt() : HandshakeF3Message() {}

  void update_static_header_ext() {
    HandshakeF3Message::update_static_header();
  }

  bool check_static_headers(uint8_t *expected_values, size_t size) {
    uint8_t buf[1024];
    static_headers.write(buf);

    return (memcmp(expected_values, buf, size) == 0);
  }
};

TEST(MessageTest, HandshakeF3__Constructor_01) {
  HandshakeF3MessageExt message;

  /*
  uint16_t session_id_length;
  std::string session_id;
  uint16_t path_length;
  std::string path;
  std::vector<uint8_t> other_auth;
  */

  message.session_id_length = 64;
  std::string session_id("session-id123456789012345678901234567890123456789012345678901234");
  message.session_id = session_id;

  message.path_length = 32;
  std::string path("path5678901234567890123456789012");
  message.path = path;

  uint8_t auth[] = "auth5678901234567890123456789012";
  message.other_auth = std::vector<uint8_t>(auth, auth + Message::AuthLength);

  message.update_static_header_ext();

  uint8_t buf[1024];
  message.write(buf);

  // 15 + 2 + 64 + 2 + 32 + 32 = 147
  uint8_t expected_values[147];

  uint32_t message_size = 147;
  uint16_t header_size = message_size;
  MessageType type = MessageType::Handshake3;
  uint32_t request_id = 0;
  uint32_t ack_id = 0;

  std::memcpy(&expected_values[StaticHeaders::MessageSizeOffset], &message_size,
              sizeof(uint32_t));
  std::memcpy(&expected_values[StaticHeaders::HeaderSizeOffset], &header_size,
              sizeof(uint16_t));
  std::memcpy(&expected_values[StaticHeaders::TypeOffset], &type,
              sizeof(uint8_t));
  std::memcpy(&expected_values[StaticHeaders::RequestIdOffset], &request_id,
              sizeof(request_id));
  std::memcpy(&expected_values[StaticHeaders::AckIdOffset], &ack_id,
              sizeof(ack_id));

  uint8_t SessionIdLengthOffset = StaticHeaders::TotalSize;
  uint8_t SessionIdOffset = SessionIdLengthOffset + sizeof(uint16_t);
  uint8_t PathLengthOffset = SessionIdOffset + message.session_id.size();
  uint8_t PathOffset = PathLengthOffset + sizeof(uint16_t);
  uint8_t AuthOffset = PathOffset + message.path_length;

  std::memcpy(&expected_values[SessionIdLengthOffset], &message.session_id_length,  sizeof(message.session_id_length));
  std::memcpy(&expected_values[SessionIdOffset], message.session_id.data(), message.session_id.size());
  std::memcpy(&expected_values[PathLengthOffset], &message.path_length,  sizeof(message.path_length));
  std::memcpy(&expected_values[PathOffset], message.path.data(), message.path.size());
  std::memcpy(&expected_values[AuthOffset], message.other_auth.data(), Message::AuthLength);

//  EXPECT_EQ(0, memcmp(expected_values, buf, message_size));

}
<|endoftext|>


<commit_before>#pragma once

// This code comes from:
// https://github.com/google/protobuf/blob/master/src/google/protobuf/stubs/map_util.h
// and was adapted to Visual Studio 2013 and to the needs of this project.

// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// from google3/util/gtl/map_util.h
// Author: Anton Carver

#include "glog/logging.h"

namespace principia {
namespace base {

template <class Collection>
const typename Collection::value_type::second_type&
FindOrDie(const Collection& collection,
          const typename Collection::value_type::first_type& key) {
  typename Collection::const_iterator it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found: " << key;
  return it->second;
}

// Same as above, but returns a non-const reference.
template <class Collection>
typename Collection::value_type::second_type&
FindOrDie(Collection& collection,  // NOLINT
          const typename Collection::value_type::first_type& key) {
  typename Collection::iterator it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found: " << key;
  return it->second;
}

}  // namespace base
}  // namespace principia
<commit_msg>After egg's review.<commit_after>#pragma once

// This code comes from:
// https://github.com/google/protobuf/blob/master/src/google/protobuf/stubs/map_util.h
// and was adapted to Visual Studio 2013 and to the needs of this project.

// Protocol Buffers - Google's data interchange format
// Copyright 2014 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// from google3/util/gtl/map_util.h
// Author: Anton Carver

#include "glog/logging.h"

namespace principia {
namespace base {

template <class Collection>
const typename Collection::value_type::second_type&
FindOrDie(const Collection& collection,
          const typename Collection::value_type::first_type& key) {
  typename Collection::const_iterator it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found: " << key;
  return it->second;
}

// Same as above, but returns a non-const reference.
template <class Collection>
typename Collection::value_type::second_type&
FindOrDie(Collection& collection,  // NOLINT(runtime/references)
          const typename Collection::value_type::first_type& key) {
  typename Collection::iterator it = collection.find(key);
  CHECK(it != collection.end()) << "Map key not found: " << key;
  return it->second;
}

}  // namespace base
}  // namespace principia
<|endoftext|>