<commit_before>#include "mainwindow.h"
#include <QWebView>
#include <QtWidgets>
#include <QWebFrame>
#include <QDir>
#include <QApplication>
#include <QDebug>
#include <QWebPage>
#include <QObject>
#include <QWindow>
#include <QWebInspector>

/*
 *  Utility:
 *  ./exectuable pageAddress width height decoration (BOTTOM_MOST)
 *
 *   - pageAddress: the html file path or url
 *   - width:       integer that represent the width of the window
 *   - height:      integer that represent the height of the window
 *   - decoration:  if it is "UNDECORATED" the window will be undecorated (it will not have
 *                  borders and the window buttons
 *
 * */

QWebView *webView;
bool debugMode = false;

/*
 *  Javascript functions (Public API)
 * */
class JohnnysWebviewJavaScriptOperations : public QObject {
    Q_OBJECT
public:
    /*
     *  Close window
     *  $API.closeWindow();
     *
     **/
    Q_INVOKABLE void closeWindow () {

        if (debugMode) {
            qDebug() << "[INFO] Closing window.";
        }

        webView->close();
    }

    /*
     *  Resize
     *  $API.resize(width, height);
     *
     **/
    Q_INVOKABLE void resize (int width, int height) {

        if (debugMode) {
            qDebug() << "[INFO] Resizing window: width=" << width << "px; height=" << height << "px." ;
        }

        webView->resize(width, height);
    }

    /*
     *  Set window flags
     *  $API.setWindowFlags (type)
     *      - UNDECORATED
     *
     * */
    Q_INVOKABLE void setWindowFlags (QString type) {

        if (debugMode) {
            qDebug() << "[INFO] Setting window flag: " << type;
        }

        QStringList options;
        options << "UNDECORATED"
                << "BOTTOM_MOST"
                << "TOP_MOST"
                << "REMOVE_MINIMIZE"
                << "REMOVE_MAXIMIZE"
                << "REMOVE_CLOSE";

        switch (options.indexOf(type)) {
            case 0:
                webView->setWindowFlags(Qt::FramelessWindowHint | webView->windowFlags());
                webView->show();
                break;
            case 1:
                webView->setWindowFlags(Qt::WindowStaysOnBottomHint | webView->windowFlags());
                webView->show();
                break;
            case 2:
                webView->setWindowFlags(Qt::WindowStaysOnTopHint | webView->windowFlags());
                webView->show();
                break;
            case 3:
                webView->setWindowFlags(webView->windowFlags() & ~Qt::WindowMinimizeButtonHint);
                webView->show();
                break;
            case 4:
                webView->setWindowFlags(webView->windowFlags() & ~Qt::WindowMaximizeButtonHint);
                webView->show();
                break;
            case 5:
                webView->setWindowFlags(webView->windowFlags() & ~Qt::WindowCloseButtonHint);
                webView->show();
                break;
            // TODO Other cases
        }
    }

    /*
     *  Set window state
     *  $API.setWindowState (value)
     *      - MAXIMIZED
     *      - MINIMIZED
     *      - FULLSCREEN
     *      - ACTIVE
     * */
    Q_INVOKABLE void setWindowState (QString type) {

        if (debugMode) {
            qDebug() << "[INFO] Setting window state: " << type;
        }

        QStringList options;
        options << "MAXIMIZED" << "MINIMIZED" << "FULLSCREEN" << "ACTIVATE" << "RESTORED";

        switch (options.indexOf(type)) {
            case 0:
                webView->setWindowState(Qt::WindowMaximized);
                break;
            case 1:
                webView->setWindowState(Qt::WindowMinimized);
                break;
            case 2:
                webView->setWindowState(Qt::WindowFullScreen);
                break;
            case 3:
                webView->setWindowState(Qt::WindowActive);
                break;
            case 4:
                webView->setWindowState(Qt::WindowNoState);
                break;
        }
    }

    /*
     *  Get window size
     *  $API.getWindowSize ()
     * */
    Q_INVOKABLE QObject *getWindowSize () {

        if (debugMode) {
            qDebug() << "[INFO] Getting the window size.";
        }

        QObject *size = new QObject();
        QSize winSize = webView->size();

        size->setProperty("width", winSize.width());
        size->setProperty("height", winSize.height());

        return size;
    }

    /*
     *  Get screen size
     *  $API.getScreenSize ()
     *
     * */
    Q_INVOKABLE QObject *getScreenSize () {

        if (debugMode) {
            qDebug() << "[INFO] Getting screen size.";
        }

        QObject *size = new QObject();
        QSize screenSize = qApp->primaryScreen()->size();

        size->setProperty("width", screenSize.width());
        size->setProperty("height", screenSize.height());

        return size;
    }

    /*
     *  Set window position
     *  $API.setWindowPosition (left, top)
     * */
    Q_INVOKABLE void setWindowPosition (int left, int top) {

        if (debugMode) {
            qDebug() << "[INFO] Setting the window position: left=" << left << "px; top=" << top << "px.";
        }

        webView->move(left, top);
    }

    /*
     *  Get window position
     *  $API.getWindowPosition (left, top)
     * */
    Q_INVOKABLE QObject *getWindowPosition () {

        if (debugMode) {
            qDebug() << "[INFO] Getting the window position.";
        }

        QObject *position = new QObject();
        QPoint point = webView->pos();

        position->setProperty("left", point.x());
        position->setProperty("top", point.y());

        return position;
    }

    /*
     *  Get mouse position
     *  $API.getMousePosition()
     *
     * */
    Q_INVOKABLE QObject *getMousePosition () {

        if (debugMode) {
            qDebug() << "[INFO] Getting the mouse position.";
        }

        QObject *position = new QObject();
        QPoint point = QCursor::pos();

        position->setProperty("left", point.x());
        position->setProperty("top", point.y());

        return position;
    }

    /*
     *  Set mouse position
     *  $API.setMousePosition()
     *
     * */
    Q_INVOKABLE void setMousePosition (int x, int y) {

        if (debugMode) {
            qDebug() << "[INFO] Setting the mouse position: x=" << x << "px; y=" << y << "px.";
        }

        QCursor::setPos(x, y);
    }

    /*
     *  Creates a new window
     *  $API.newWindow(options);
     * */
    // TODO Is this really needed?
    // Q_INVOKABLE void newWindow () {
    //   QWindow newWindow = new QWindow();
    //    newWindow.show();
    // }

    /*
     *  Sets the title of the current window
     *  $API.setWindowTitle(newTitle)
     *
     * */
    Q_INVOKABLE void setWindowTitle (QString newTitle) {

        if (debugMode) {
            qDebug() << "[INFO] Setting the window title: " << newTitle;
        }

        webView->setWindowTitle(newTitle);
    }

    /*
     *  Writes content to file
     *  $API.writeFile (path, content);
     *
     * */
    Q_INVOKABLE void writeFile (QString path, QString content) {
        if (debugMode) {
            qDebug() << "[INFO] Writting to file: " << path;
        }

        QFile file(path);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            if (debugMode) {
                qDebug() << "[WARNING] Cannot write file.";
            }
            return;
        }

        QTextStream out(&file);
        out << content;
    }

    /*
     *  Returns the content content of a file
     *  $API.readFile (path);
     *
     * */
    Q_INVOKABLE QString readFile (QString path) {
        if (debugMode) {
            qDebug() << "[INFO] Reading from file: " << path;
        }

        QFile file(path);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            if (debugMode) {
                qDebug() << "[WARNING] Cannot open file.";
            }
            return "";
        }

        QString fileContent = "";
        QTextStream in(&file);

        in >> fileContent;

        return fileContent;
    }

    /*
     *  Debug
     *  $API.debug(message)
     *
     * */
    Q_INVOKABLE void debug (QString message) {

        if (debugMode) {
            qDebug() << "[INFO] Printing debug message: " << message;
        }

        qDebug() << message;
    }

    /*
     *  Insepct element
     *  $API.inspectElement()
     *
     * */
    Q_INVOKABLE void inspectElement () {

        if (debugMode) {
            qDebug() << "[INFO] Activating inspect element.";
        }

        webView->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);

        QWebInspector inspector;
        inspector.setPage(webView->page());
        inspector.setVisible(true);
    }

    /*
     *  Run bash commands
     *  $API.debug(command)
     *
     * */
    Q_INVOKABLE void runBash (QString command) {

        if (debugMode) {
            qDebug() << "[INFO] Running bash command: " << command;
        }

        system(qPrintable(command));
        // TODO return output (e.g for `ps aux`)
    }

    /*
     *  Enable/Disable debug mode
     *  $API.setDebugMode(true/false)
     *
     * */
    Q_INVOKABLE void setDebugMode (bool debug) {

        if (debugMode) {
            qDebug() << "[INFO] Setting debug mode: " << debug;
        }

        debugMode = debug;
    }

    /*
     *  Get debug mode
     *  $API.getDebugMode(true/false)
     *
     * */
    Q_INVOKABLE bool getDebugMode () {

        if (debugMode) {
            qDebug() << "[INFO] Getting debug mode.";
        }

        return debugMode;
    }
};

int main(int argc, char *argv[])
{

    QApplication app(argc, argv);

    // build the web view
    QWebView *view = new QWebView();

    webView = view;

    // get the html path
    QString HTML_PATH       = QString(argv[1]);

    // the path is NOT a web site url
    if (!HTML_PATH.startsWith("http"))
    {
        // get it from the local machine
        HTML_PATH = "file://" + QDir::current().absolutePath() + QDir::separator() + HTML_PATH;
    }

    // set window width and height
    int     WINDOW_WIDTH    = QString(argv[2]).toInt();
    int     WINDOW_HEIGHT   = QString(argv[3]).toInt();

    // handle "UNDECORATED" flag
    if (QString(argv[4]) == "UNDECORATED") {
        // set background transparent for webview
        QPalette pal = view->palette();
        pal.setBrush(QPalette::Base, Qt::transparent);
        view->page()->setPalette(pal);
        view->setAttribute(Qt::WA_TranslucentBackground);

        view->setWindowFlags(Qt::FramelessWindowHint | view->windowFlags());
    }

    QStringList appArgv = app.arguments();
    if (appArgv.contains("--debug")) {

        qDebug() << " * Debug mode.";
        debugMode = true;
        view->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);

        QWebInspector inspector;
        inspector.setPage(view->page());
        inspector.setVisible(true);
    }

    if (QString(argv[5]) == "BOTTOM_MOST") {
        view->setWindowFlags(Qt::WindowStaysOnBottomHint | view->windowFlags());
    } else if (QString(argv[5]) == "TOP_MOST") {
        view->setWindowFlags(Qt::WindowStaysOnTopHint    | view->windowFlags());
    }

    // add the public api functions
    view->page()->mainFrame()->addToJavaScriptWindowObject("$API", new JohnnysWebviewJavaScriptOperations);

    // resize the window
    view->resize(WINDOW_WIDTH, WINDOW_HEIGHT);

    // load that HTML file or website
    view->load(QUrl(HTML_PATH));

    // show the web view
    view->show();

    // if --exit was provided
    if (appArgv.contains("--exit")) {
        qDebug() << "Exiting...";
        QApplication::quit();
    }

    return app.exec();
}

#include "main.moc"
<commit_msg>Check if the provided path is not already absolute.<commit_after>#include "mainwindow.h"
#include <QWebView>
#include <QtWidgets>
#include <QWebFrame>
#include <QDir>
#include <QApplication>
#include <QDebug>
#include <QWebPage>
#include <QObject>
#include <QWindow>
#include <QWebInspector>

/*
 *  Utility:
 *  ./exectuable pageAddress width height decoration (BOTTOM_MOST)
 *
 *   - pageAddress: the html file path or url
 *   - width:       integer that represent the width of the window
 *   - height:      integer that represent the height of the window
 *   - decoration:  if it is "UNDECORATED" the window will be undecorated (it will not have
 *                  borders and the window buttons
 *
 * */

QWebView *webView;
bool debugMode = false;

/*
 *  Javascript functions (Public API)
 * */
class JohnnysWebviewJavaScriptOperations : public QObject {
    Q_OBJECT
public:
    /*
     *  Close window
     *  $API.closeWindow();
     *
     **/
    Q_INVOKABLE void closeWindow () {

        if (debugMode) {
            qDebug() << "[INFO] Closing window.";
        }

        webView->close();
    }

    /*
     *  Resize
     *  $API.resize(width, height);
     *
     **/
    Q_INVOKABLE void resize (int width, int height) {

        if (debugMode) {
            qDebug() << "[INFO] Resizing window: width=" << width << "px; height=" << height << "px." ;
        }

        webView->resize(width, height);
    }

    /*
     *  Set window flags
     *  $API.setWindowFlags (type)
     *      - UNDECORATED
     *
     * */
    Q_INVOKABLE void setWindowFlags (QString type) {

        if (debugMode) {
            qDebug() << "[INFO] Setting window flag: " << type;
        }

        QStringList options;
        options << "UNDECORATED"
                << "BOTTOM_MOST"
                << "TOP_MOST"
                << "REMOVE_MINIMIZE"
                << "REMOVE_MAXIMIZE"
                << "REMOVE_CLOSE";

        switch (options.indexOf(type)) {
            case 0:
                webView->setWindowFlags(Qt::FramelessWindowHint | webView->windowFlags());
                webView->show();
                break;
            case 1:
                webView->setWindowFlags(Qt::WindowStaysOnBottomHint | webView->windowFlags());
                webView->show();
                break;
            case 2:
                webView->setWindowFlags(Qt::WindowStaysOnTopHint | webView->windowFlags());
                webView->show();
                break;
            case 3:
                webView->setWindowFlags(webView->windowFlags() & ~Qt::WindowMinimizeButtonHint);
                webView->show();
                break;
            case 4:
                webView->setWindowFlags(webView->windowFlags() & ~Qt::WindowMaximizeButtonHint);
                webView->show();
                break;
            case 5:
                webView->setWindowFlags(webView->windowFlags() & ~Qt::WindowCloseButtonHint);
                webView->show();
                break;
            // TODO Other cases
        }
    }

    /*
     *  Set window state
     *  $API.setWindowState (value)
     *      - MAXIMIZED
     *      - MINIMIZED
     *      - FULLSCREEN
     *      - ACTIVE
     * */
    Q_INVOKABLE void setWindowState (QString type) {

        if (debugMode) {
            qDebug() << "[INFO] Setting window state: " << type;
        }

        QStringList options;
        options << "MAXIMIZED" << "MINIMIZED" << "FULLSCREEN" << "ACTIVATE" << "RESTORED";

        switch (options.indexOf(type)) {
            case 0:
                webView->setWindowState(Qt::WindowMaximized);
                break;
            case 1:
                webView->setWindowState(Qt::WindowMinimized);
                break;
            case 2:
                webView->setWindowState(Qt::WindowFullScreen);
                break;
            case 3:
                webView->setWindowState(Qt::WindowActive);
                break;
            case 4:
                webView->setWindowState(Qt::WindowNoState);
                break;
        }
    }

    /*
     *  Get window size
     *  $API.getWindowSize ()
     * */
    Q_INVOKABLE QObject *getWindowSize () {

        if (debugMode) {
            qDebug() << "[INFO] Getting the window size.";
        }

        QObject *size = new QObject();
        QSize winSize = webView->size();

        size->setProperty("width", winSize.width());
        size->setProperty("height", winSize.height());

        return size;
    }

    /*
     *  Get screen size
     *  $API.getScreenSize ()
     *
     * */
    Q_INVOKABLE QObject *getScreenSize () {

        if (debugMode) {
            qDebug() << "[INFO] Getting screen size.";
        }

        QObject *size = new QObject();
        QSize screenSize = qApp->primaryScreen()->size();

        size->setProperty("width", screenSize.width());
        size->setProperty("height", screenSize.height());

        return size;
    }

    /*
     *  Set window position
     *  $API.setWindowPosition (left, top)
     * */
    Q_INVOKABLE void setWindowPosition (int left, int top) {

        if (debugMode) {
            qDebug() << "[INFO] Setting the window position: left=" << left << "px; top=" << top << "px.";
        }

        webView->move(left, top);
    }

    /*
     *  Get window position
     *  $API.getWindowPosition (left, top)
     * */
    Q_INVOKABLE QObject *getWindowPosition () {

        if (debugMode) {
            qDebug() << "[INFO] Getting the window position.";
        }

        QObject *position = new QObject();
        QPoint point = webView->pos();

        position->setProperty("left", point.x());
        position->setProperty("top", point.y());

        return position;
    }

    /*
     *  Get mouse position
     *  $API.getMousePosition()
     *
     * */
    Q_INVOKABLE QObject *getMousePosition () {

        if (debugMode) {
            qDebug() << "[INFO] Getting the mouse position.";
        }

        QObject *position = new QObject();
        QPoint point = QCursor::pos();

        position->setProperty("left", point.x());
        position->setProperty("top", point.y());

        return position;
    }

    /*
     *  Set mouse position
     *  $API.setMousePosition()
     *
     * */
    Q_INVOKABLE void setMousePosition (int x, int y) {

        if (debugMode) {
            qDebug() << "[INFO] Setting the mouse position: x=" << x << "px; y=" << y << "px.";
        }

        QCursor::setPos(x, y);
    }

    /*
     *  Creates a new window
     *  $API.newWindow(options);
     * */
    // TODO Is this really needed?
    // Q_INVOKABLE void newWindow () {
    //   QWindow newWindow = new QWindow();
    //    newWindow.show();
    // }

    /*
     *  Sets the title of the current window
     *  $API.setWindowTitle(newTitle)
     *
     * */
    Q_INVOKABLE void setWindowTitle (QString newTitle) {

        if (debugMode) {
            qDebug() << "[INFO] Setting the window title: " << newTitle;
        }

        webView->setWindowTitle(newTitle);
    }

    /*
     *  Writes content to file
     *  $API.writeFile (path, content);
     *
     * */
    Q_INVOKABLE void writeFile (QString path, QString content) {
        if (debugMode) {
            qDebug() << "[INFO] Writting to file: " << path;
        }

        QFile file(path);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            if (debugMode) {
                qDebug() << "[WARNING] Cannot write file.";
            }
            return;
        }

        QTextStream out(&file);
        out << content;
    }

    /*
     *  Returns the content content of a file
     *  $API.readFile (path);
     *
     * */
    Q_INVOKABLE QString readFile (QString path) {
        if (debugMode) {
            qDebug() << "[INFO] Reading from file: " << path;
        }

        QFile file(path);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            if (debugMode) {
                qDebug() << "[WARNING] Cannot open file.";
            }
            return "";
        }

        QString fileContent = "";
        QTextStream in(&file);

        in >> fileContent;

        return fileContent;
    }

    /*
     *  Debug
     *  $API.debug(message)
     *
     * */
    Q_INVOKABLE void debug (QString message) {

        if (debugMode) {
            qDebug() << "[INFO] Printing debug message: " << message;
        }

        qDebug() << message;
    }

    /*
     *  Insepct element
     *  $API.inspectElement()
     *
     * */
    Q_INVOKABLE void inspectElement () {

        if (debugMode) {
            qDebug() << "[INFO] Activating inspect element.";
        }

        webView->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);

        QWebInspector inspector;
        inspector.setPage(webView->page());
        inspector.setVisible(true);
    }

    /*
     *  Run bash commands
     *  $API.debug(command)
     *
     * */
    Q_INVOKABLE void runBash (QString command) {

        if (debugMode) {
            qDebug() << "[INFO] Running bash command: " << command;
        }

        system(qPrintable(command));
        // TODO return output (e.g for `ps aux`)
    }

    /*
     *  Enable/Disable debug mode
     *  $API.setDebugMode(true/false)
     *
     * */
    Q_INVOKABLE void setDebugMode (bool debug) {

        if (debugMode) {
            qDebug() << "[INFO] Setting debug mode: " << debug;
        }

        debugMode = debug;
    }

    /*
     *  Get debug mode
     *  $API.getDebugMode(true/false)
     *
     * */
    Q_INVOKABLE bool getDebugMode () {

        if (debugMode) {
            qDebug() << "[INFO] Getting debug mode.";
        }

        return debugMode;
    }
};

int main(int argc, char *argv[])
{

    QApplication app(argc, argv);

    // build the web view
    QWebView *view = new QWebView();

    webView = view;

    // get the html path
    QString HTML_PATH       = QString(argv[1]);

    // the path is NOT a web site url
    if (!HTML_PATH.startsWith("http"))
    {
        // if it's NOT an absolute file path
        if (!HTML_PATH.startsWith("/")) {

            // get the absolute path from the local machine
            HTML_PATH = "file://" + QDir::current().absolutePath() + QDir::separator() + HTML_PATH;
        }
    }

    // set window width and height
    int     WINDOW_WIDTH    = QString(argv[2]).toInt();
    int     WINDOW_HEIGHT   = QString(argv[3]).toInt();

    // handle "UNDECORATED" flag
    if (QString(argv[4]) == "UNDECORATED") {
        // set background transparent for webview
        QPalette pal = view->palette();
        pal.setBrush(QPalette::Base, Qt::transparent);
        view->page()->setPalette(pal);
        view->setAttribute(Qt::WA_TranslucentBackground);

        view->setWindowFlags(Qt::FramelessWindowHint | view->windowFlags());
    }

    QStringList appArgv = app.arguments();
    if (appArgv.contains("--debug")) {

        qDebug() << " * Debug mode.";
        debugMode = true;
        view->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);

        QWebInspector inspector;
        inspector.setPage(view->page());
        inspector.setVisible(true);
    }

    if (QString(argv[5]) == "BOTTOM_MOST") {
        view->setWindowFlags(Qt::WindowStaysOnBottomHint | view->windowFlags());
    } else if (QString(argv[5]) == "TOP_MOST") {
        view->setWindowFlags(Qt::WindowStaysOnTopHint    | view->windowFlags());
    }

    // add the public api functions
    view->page()->mainFrame()->addToJavaScriptWindowObject("$API", new JohnnysWebviewJavaScriptOperations);

    // resize the window
    view->resize(WINDOW_WIDTH, WINDOW_HEIGHT);

    // load that HTML file or website
    view->load(QUrl(HTML_PATH));

    // show the web view
    view->show();

    // if --exit was provided
    if (appArgv.contains("--exit")) {
        qDebug() << "Exiting...";
        QApplication::quit();
    }

    return app.exec();
}

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


<commit_before>// Stress test recovery mode with many threads.
//
// RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t
//
// RUN: env ASAN_OPTIONS=halt_on_error=false %run %t 1 10 >1.txt 2>&1
// RUN: FileCheck %s < 1.txt
// RUN: [ $(wc -l < 1.txt) -gt 1 ]
//
// RUN: env ASAN_OPTIONS=halt_on_error=false %run %t 10 20 >10.txt 2>&1
// RUN: FileCheck %s < 10.txt
// This one is racy although very unlikely to fail:
// RUN: [ $(wc -l < 10.txt) -gt 1 ]
// Collisions are highly unlikely but still possible so we need the alternative:
// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
//
// REQUIRES: stable-runtime

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>

#include <sanitizer/asan_interface.h>

size_t nthreads = 10;
size_t niter = 10;

void random_delay(unsigned *seed) {
  *seed = 1664525 * *seed + 1013904223;
  struct timespec delay = { 0, (*seed % 1000) * 1000 };
  nanosleep(&delay, 0);
}

void *run(void *arg) {
  unsigned seed = (unsigned)(size_t)arg;

  volatile char tmp[2];
  __asan_poison_memory_region(&tmp, sizeof(tmp));

  for (size_t i = 0; i < niter; ++i) {
    random_delay(&seed);
    // Expect error collisions here
    // CHECK: AddressSanitizer: use-after-poison
    volatile int idx = 0;
    tmp[idx] = 0;
  }

  return 0;
}

int main(int argc, char **argv) {
  if (argc != 3) {
    fprintf(stderr, "Syntax: %s nthreads niter\n", argv[0]);
    exit(1);
  }

  nthreads = (size_t)strtoul(argv[1], 0, 0);
  niter = (size_t)strtoul(argv[2], 0, 0);

  pthread_t *tids = new pthread_t[nthreads];

  for (size_t i = 0; i < nthreads; ++i) {
    if (0 != pthread_create(&tids[i], 0, run, (void *)i)) {
      fprintf(stderr, "Failed to create thread\n");
      exit(1);
    }
  }

  for (size_t i = 0; i < nthreads; ++i) {
    if (0 != pthread_join(tids[i], 0)) {
      fprintf(stderr, "Failed to join thread\n");
      exit(1);
    }
  }

  // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
  // CHECK-NO-COLLISION: All threads terminated
  printf("All threads terminated\n");

  delete [] tids;

  return 0;
}
<commit_msg>[asan] Fix test to properly handle collisions.<commit_after>// Stress test recovery mode with many threads.
//
// RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t
//
// RUN: env ASAN_OPTIONS=halt_on_error=false %run %t 1 10 >1.txt 2>&1
// RUN: FileCheck %s < 1.txt
// RUN: [ $(wc -l < 1.txt) -eq 10 ]
// RUN: FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
//
// Collisions are unlikely but still possible so we need the ||.
// RUN: env ASAN_OPTIONS=halt_on_error=false %run %t 10 20 >10.txt 2>&1 || true
// This one is racy although _very_ unlikely to fail:
// RUN: FileCheck %s < 10.txt
// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
//
// REQUIRES: stable-runtime

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>

#include <sanitizer/asan_interface.h>

size_t nthreads = 10;
size_t niter = 10;

void random_delay(unsigned *seed) {
  *seed = 1664525 * *seed + 1013904223;
  struct timespec delay = { 0, (*seed % 1000) * 1000 };
  nanosleep(&delay, 0);
}

void *run(void *arg) {
  unsigned seed = (unsigned)(size_t)arg;

  volatile char tmp[2];
  __asan_poison_memory_region(&tmp, sizeof(tmp));

  for (size_t i = 0; i < niter; ++i) {
    random_delay(&seed);
    // Expect error collisions here
    // CHECK: ERROR: AddressSanitizer: use-after-poison
    volatile int idx = 0;
    tmp[idx] = 0;
  }

  return 0;
}

int main(int argc, char **argv) {
  if (argc != 3) {
    fprintf(stderr, "Syntax: %s nthreads niter\n", argv[0]);
    exit(1);
  }

  nthreads = (size_t)strtoul(argv[1], 0, 0);
  niter = (size_t)strtoul(argv[2], 0, 0);

  pthread_t *tids = new pthread_t[nthreads];

  for (size_t i = 0; i < nthreads; ++i) {
    if (0 != pthread_create(&tids[i], 0, run, (void *)i)) {
      fprintf(stderr, "Failed to create thread\n");
      exit(1);
    }
  }

  for (size_t i = 0; i < nthreads; ++i) {
    if (0 != pthread_join(tids[i], 0)) {
      fprintf(stderr, "Failed to join thread\n");
      exit(1);
    }
  }

  // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
  // CHECK-NO-COLLISION: All threads terminated
  printf("All threads terminated\n");

  delete [] tids;

  return 0;
}
<|endoftext|>


<commit_before>#include "broker_dslink_util.h"

using BrokerDsLinkTest = SetUpBase;

TEST_F(BrokerDsLinkTest, ClientRemoveTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", true, protocol());

  int downstream_listed = 0, clients_listed = 0;
  bool link1_connected = false, allow_all_set = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    // send set request
    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_TRUE(msg->get_status() == MessageStatus::OK ||
                      msg->get_status() == MessageStatus::CLOSED);
          allow_all_set = true;

          link_req->list("Downstream", [&, link_req](
                                           IncomingListCache &cache,
                                           const std::vector<string_> &str) {
            auto map = cache.get_map();
            downstream_listed++;
            if (downstream_listed == 1) {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") != map.end());

              link_req->list(
                  "Sys/Clients",
                  [&, link_req](IncomingListCache &cache,
                                const std::vector<string_> &str) {
                    auto map = cache.get_map();
                    bool test1_client = false;
                    string_ test2_id;
                    for (auto &items : map) {
                      if (items.first.substr(0, 5) == "Test1")
                        test1_client = true;
                      else if (items.first.substr(0, 5) == "Test2") {
                        test2_id = items.first;
                      }
                    }
                    clients_listed++;
                    if (clients_listed == 1) {
                      EXPECT_TRUE(test1_client && !test2_id.empty());
                      auto invoke_request = make_ref_<InvokeRequestMessage>();
                      invoke_request->set_target_path("Sys/Clients/" +
                                                      test2_id + "/Remove");

                      link_req->invoke(
                          [&](IncomingInvokeStream &stream,
                              ref_<const InvokeResponseMessage> &&msg) {
                            auto response = std::move(msg);
                            EXPECT_TRUE(response != nullptr);
                            stream.close();
                          },
                          copy_ref_(invoke_request));
                    } else {
                      EXPECT_TRUE(test1_client && test2_id.empty());
                      cache.close();
                    }
                  });

            } else {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") == map.end());
              cache.close();
            }
          });

        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) &&
            (clients_listed >= 2) && allow_all_set);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

TEST_F(BrokerDsLinkTest, ClientPathTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  int downstream_listed = 0;
  bool link1_connected = false, test_end = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    link_req->list(
        "Downstream", [&, link_req](IncomingListCache &cache,
                                    const std::vector<string_> &str) {
          auto map = cache.get_map();
          downstream_listed++;
          if (downstream_listed == 1) {
            EXPECT_TRUE(map.find("Test1") != map.end());

            link_req->list("Sys/Clients", [&, link_req](
                                              IncomingListCache &cache,
                                              const std::vector<string_> &str) {
              auto map = cache.get_map();
              string_ test1_id;
              for (auto &items : map) {
                if (items.first.substr(0, 5) == "Test1") {
                  test1_id = items.first;
                }
              }
              EXPECT_TRUE(!test1_id.empty());

              // change path
              auto set_request = make_ref_<SetRequestMessage>();
              set_request->set_value(Var("Downstream/Test_Changed"));
              set_request->set_target_path("Sys/Clients/" + test1_id + "/Path");
              link_req->set(
                  [&, link_req](IncomingSetStream &stream,
                                ref_<const SetResponseMessage> &&msg) {
                    EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);

                  },
                  std::move(set_request));
              cache.close();

            });

          } else {
            EXPECT_TRUE(map.find("Test1") == map.end());
            EXPECT_TRUE(map.find("Test_Changed") != map.end());
            cache.close();
            test_end = true;
          }
        });

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) && test_end);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

bool get_connected(const shared_ptr_<Connection> &connection) {
  if (!connection) {
    return false;
  } else {
    auto session = connection->session();
    if (!session) {
      return false;
    } else {
      return session->is_connected();
    }
  }
}

TEST_F(BrokerDsLinkTest, QuarantineTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", false, protocol());

  int downstream_listed = 0, quarantine_listed = 0;
  bool link1_connected = false, link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = get_connected(connection);
    EXPECT_TRUE(link1_connected);

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);

          // set request to change value
          auto set_request = make_ref_<SetRequestMessage>();
          set_request->set_value(Var(true));
          set_request->set_target_path("Sys/Quarantine/Enabled");

          // send set request
          link_req->set(
              [&, link_req](IncomingSetStream &stream,
                            ref_<const SetResponseMessage> &&msg) {
                EXPECT_EQ(msg->get_status(), MessageStatus::CLOSED);

                link_2->connect([&, link1_req = link_req ](
                    const shared_ptr_<Connection> connection2,
                    ref_<DsLinkRequester> link2_req) {
                  link2_connected = get_connected(connection2);
                  EXPECT_TRUE(link2_connected);
                  link1_req->list(
                      "Downstream",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        downstream_listed++;
                        if (downstream_listed == 1) {
                          EXPECT_TRUE(map.find("Test2") == map.end());
                        } else {
                          EXPECT_TRUE(map.find("Test2") != map.end());
                        }
                      });
                  link1_req->list(
                      "Sys/Quarantine",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        quarantine_listed++;
                        string_ test2_id;
                        for (auto &items : map) {
                          if (items.first.substr(0, 5) == "Test2") {
                            test2_id = items.first;
                          }
                        }
                        if (quarantine_listed == 1) {
                          EXPECT_TRUE(!test2_id.empty());
                          // invoke authorize
                          auto invoke_request =
                              make_ref_<InvokeRequestMessage>();
                          invoke_request->set_target_path(
                              "Sys/Quarantine/" + test2_id + "/Authorize");
                          invoke_request->set_value(
                              Var({{"Path", Var("Downstream/Test2")}}));

                          link1_req->invoke(
                              [&](IncomingInvokeStream &stream,
                                  ref_<const InvokeResponseMessage> &&msg) {
                                auto response = std::move(msg);
                                EXPECT_EQ(response->get_status(),
                                          MessageStatus::CLOSED);
                                EXPECT_TRUE(response != nullptr);
                                stream.close();
                              },
                              copy_ref_(invoke_request));
                        } else {
                          EXPECT_TRUE(test2_id.empty());
                        }
                      });

                });

              },
              std::move(set_request));
        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(3000, [&]() -> bool {
    return (link1_connected && link2_connected && (downstream_listed >= 2) &&
            (quarantine_listed >= 2));
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

TEST_F(BrokerDsLinkTest, IdenticalClientTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  bool link1_connected = false;
  bool link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected |= get_connected(connection);

    if (link1_connected) {
      link_2->connect([&](const shared_ptr_<Connection> connection,
                          ref_<DsLinkRequester> link_req) {
        link2_connected |= get_connected(connection);
      });
    }

  });
  WAIT_EXPECT_TRUE(
      1000, [&]() -> bool { return link1_connected && link2_connected; });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}<commit_msg>refactory for the new unit test<commit_after>#include "broker_dslink_util.h"

using BrokerDsLinkTest = SetUpBase;

TEST_F(BrokerDsLinkTest, ClientRemoveTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", true, protocol());

  int downstream_listed = 0, clients_listed = 0;
  bool link1_connected = false, allow_all_set = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    // send set request
    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_TRUE(msg->get_status() == Status::OK ||
                      msg->get_status() == Status::DONE);
          allow_all_set = true;

          link_req->list("Downstream", [&, link_req](
                                           IncomingListCache &cache,
                                           const std::vector<string_> &str) {
            auto map = cache.get_map();
            downstream_listed++;
            if (downstream_listed == 1) {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") != map.end());

              link_req->list(
                  "Sys/Clients",
                  [&, link_req](IncomingListCache &cache,
                                const std::vector<string_> &str) {
                    auto map = cache.get_map();
                    bool test1_client = false;
                    string_ test2_id;
                    for (auto &items : map) {
                      if (items.first.substr(0, 5) == "Test1")
                        test1_client = true;
                      else if (items.first.substr(0, 5) == "Test2") {
                        test2_id = items.first;
                      }
                    }
                    clients_listed++;
                    if (clients_listed == 1) {
                      EXPECT_TRUE(test1_client && !test2_id.empty());
                      auto invoke_request = make_ref_<InvokeRequestMessage>();
                      invoke_request->set_target_path("Sys/Clients/" +
                                                      test2_id + "/Remove");

                      link_req->invoke(
                          [&](IncomingInvokeStream &stream,
                              ref_<const InvokeResponseMessage> &&msg) {
                            auto response = std::move(msg);
                            EXPECT_TRUE(response != nullptr);
                            stream.close();
                          },
                          copy_ref_(invoke_request));
                    } else {
                      EXPECT_TRUE(test1_client && test2_id.empty());
                      cache.close();
                    }
                  });

            } else {
              EXPECT_TRUE(map.find("Test1") != map.end());
              EXPECT_TRUE(map.find("Test2") == map.end());
              cache.close();
            }
          });

        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) &&
            (clients_listed >= 2) && allow_all_set);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

TEST_F(BrokerDsLinkTest, ClientPathTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  int downstream_listed = 0;
  bool link1_connected = false, test_end = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = true;

    link_req->list(
        "Downstream", [&, link_req](IncomingListCache &cache,
                                    const std::vector<string_> &str) {
          auto map = cache.get_map();
          downstream_listed++;
          if (downstream_listed == 1) {
            EXPECT_TRUE(map.find("Test1") != map.end());

            link_req->list("Sys/Clients", [&, link_req](
                                              IncomingListCache &cache,
                                              const std::vector<string_> &str) {
              auto map = cache.get_map();
              string_ test1_id;
              for (auto &items : map) {
                if (items.first.substr(0, 5) == "Test1") {
                  test1_id = items.first;
                }
              }
              EXPECT_TRUE(!test1_id.empty());

              // change path
              auto set_request = make_ref_<SetRequestMessage>();
              set_request->set_value(Var("Downstream/Test_Changed"));
              set_request->set_target_path("Sys/Clients/" + test1_id + "/Path");
              link_req->set(
                  [&, link_req](IncomingSetStream &stream,
                                ref_<const SetResponseMessage> &&msg) {
                    EXPECT_EQ(msg->get_status(), Status::DONE);

                  },
                  std::move(set_request));
              cache.close();

            });

          } else {
            EXPECT_TRUE(map.find("Test1") == map.end());
            EXPECT_TRUE(map.find("Test_Changed") != map.end());
            cache.close();
            test_end = true;
          }
        });

  });
  WAIT_EXPECT_TRUE(1000, [&]() -> bool {
    return (link1_connected && (downstream_listed >= 2) && test_end);
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

bool get_connected(const shared_ptr_<Connection> &connection) {
  if (!connection) {
    return false;
  } else {
    auto session = connection->session();
    if (!session) {
      return false;
    } else {
      return session->is_connected();
    }
  }
}

TEST_F(BrokerDsLinkTest, QuarantineTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test2", false, protocol());

  int downstream_listed = 0, quarantine_listed = 0;
  bool link1_connected = false, link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected = get_connected(connection);
    EXPECT_TRUE(link1_connected);

    // set request to change value
    auto set_request = make_ref_<SetRequestMessage>();
    set_request->set_value(Var(false));
    set_request->set_target_path("Sys/Clients/Allow_All");

    link_req->set(
        [&, link_req](IncomingSetStream &stream,
                      ref_<const SetResponseMessage> &&msg) {
          EXPECT_EQ(msg->get_status(), Status::DONE);

          // set request to change value
          auto set_request = make_ref_<SetRequestMessage>();
          set_request->set_value(Var(true));
          set_request->set_target_path("Sys/Quarantine/Enabled");

          // send set request
          link_req->set(
              [&, link_req](IncomingSetStream &stream,
                            ref_<const SetResponseMessage> &&msg) {
                EXPECT_EQ(msg->get_status(), Status::DONE);

                link_2->connect([&, link1_req = link_req ](
                    const shared_ptr_<Connection> connection2,
                    ref_<DsLinkRequester> link2_req) {
                  link2_connected = get_connected(connection2);
                  EXPECT_TRUE(link2_connected);
                  link1_req->list(
                      "Downstream",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        downstream_listed++;
                        if (downstream_listed == 1) {
                          EXPECT_TRUE(map.find("Test2") == map.end());
                        } else {
                          EXPECT_TRUE(map.find("Test2") != map.end());
                        }
                      });
                  link1_req->list(
                      "Sys/Quarantine",
                      [&, link1_req](IncomingListCache &cache,
                                     const std::vector<string_> &str) {
                        auto map = cache.get_map();
                        quarantine_listed++;
                        string_ test2_id;
                        for (auto &items : map) {
                          if (items.first.substr(0, 5) == "Test2") {
                            test2_id = items.first;
                          }
                        }
                        if (quarantine_listed == 1) {
                          EXPECT_TRUE(!test2_id.empty());
                          // invoke authorize
                          auto invoke_request =
                              make_ref_<InvokeRequestMessage>();
                          invoke_request->set_target_path(
                              "Sys/Quarantine/" + test2_id + "/Authorize");
                          invoke_request->set_value(
                              Var({{"Path", Var("Downstream/Test2")}}));

                          link1_req->invoke(
                              [&](IncomingInvokeStream &stream,
                                  ref_<const InvokeResponseMessage> &&msg) {
                                auto response = std::move(msg);
                                EXPECT_EQ(response->get_status(),
                                          Status::DONE);
                                EXPECT_TRUE(response != nullptr);
                                stream.close();
                              },
                              copy_ref_(invoke_request));
                        } else {
                          EXPECT_TRUE(test2_id.empty());
                        }
                      });

                });

              },
              std::move(set_request));
        },
        std::move(set_request));

  });
  WAIT_EXPECT_TRUE(3000, [&]() -> bool {
    return (link1_connected && link2_connected && (downstream_listed >= 2) &&
            (quarantine_listed >= 2));
  });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}

TEST_F(BrokerDsLinkTest, IdenticalClientTest) {
  Storage::get_config_bucket().remove_all();

  // First Create Broker
  auto app = make_shared_<App>();
  auto broker = broker_dslink_test::create_broker(app);
  broker->run();

  int32_t port;

  switch (protocol()) {
    case dsa::ProtocolType::PROT_DSS:
      port = broker->get_active_secure_port();
      break;
    default:
      port = broker->get_active_server_port();
  }

  EXPECT_TRUE(port != 0);

  auto link_1 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());
  auto link_2 =
      broker_dslink_test::create_dslink(app, port, "Test1", false, protocol());

  bool link1_connected = false;
  bool link2_connected = false;
  link_1->connect([&](const shared_ptr_<Connection> connection,
                      ref_<DsLinkRequester> link_req) {
    link1_connected |= get_connected(connection);

    if (link1_connected) {
      link_2->connect([&](const shared_ptr_<Connection> connection,
                          ref_<DsLinkRequester> link_req) {
        link2_connected |= get_connected(connection);
      });
    }

  });
  WAIT_EXPECT_TRUE(
      1000, [&]() -> bool { return link1_connected && link2_connected; });

  link_1->strand->post([link_1]() { link_1->destroy(); });
  link_2->strand->post([link_2]() { link_2->destroy(); });
  broker->strand->post([broker]() { broker->destroy(); });
  app->close();

  WAIT_EXPECT_TRUE(1000, [&]() -> bool { return app->is_stopped(); });

  if (!app->is_stopped()) {
    app->force_stop();
  }
  app->wait();

  Storage::get_config_bucket().remove_all();
}<|endoftext|>


<commit_before>#include <ios>

#include "mcts_agent.hpp"

#define fmt boost::format

int main(int argc, char* argv[]) {
  unsigned time_budget = 300;
  State state;
  MCTSAgent agent(2);
  agent.set_state(state);
  while (!state.game_over()) {
    auto decision = agent.start_decision(time_budget);
    boost::optional<Move> move = decision.get();
    agent.advance_state(*move);
  }
}
<commit_msg>serialize after selfplay<commit_after>#include <ios>

#include "mcts_agent.hpp"

#define fmt boost::format

int main(int argc, char* argv[]) {
  boost::optional<std::string> path_to_storage;
  if (argc > 1)
    path_to_storage = std::string(argv[1]);

  unsigned time_budget = 300;
  State state;
  MCTSAgent agent(2);

  if (path_to_storage)
    agent.load_yourself(*path_to_storage);

  agent.set_state(state);
  while (!state.game_over()) {
    auto decision = agent.start_decision(time_budget);
    boost::optional<Move> move = decision.get();
    state.make_move(*move);
    agent.advance_state(*move);
  }

  if (path_to_storage)
    agent.save_yourself(*path_to_storage);
}
<|endoftext|>


<commit_before>#ifndef CPPURSES_WIDGET_WIDGET_SPINNER_HPP
#define CPPURSES_WIDGET_WIDGET_SPINNER_HPP
#include <cstddef>
#include <utility>

#include <cppurses/painter/glyph_string.hpp>
#include <cppurses/painter/painter.hpp>
#include <cppurses/system/animation_engine.hpp>
#include <cppurses/widget/widget.hpp>

namespace cppurses {

/// Single cell animated spinner.
class Spinner : public Widget {
   public:
    using Period_t = Animation_engine::Period_t;

   public:
    /// Each glyph in frames is a frame, offset is starting index into frames.
    Spinner(Glyph_string frames,
            Period_t period    = Period_t{100},
            std::size_t offset = 0)
        : index_{offset}, period_{period}, frames_{std::move(frames)}
    {
        height_policy.fixed(1);
        width_policy.fixed(1);
        this->start();
    }

    void set_frames(Glyph_string frames) { frames_ = std::move(frames); }

    void set_period(Period_t period)
    {
        if (started_) {
            this->stop();
            period_ = period;
            this->start();
        }
        else
            period_ = period;
    }

    void start()
    {
        if (started_)
            return;
        this->enable_animation(period_);
        started_ = true;
    }

    void stop()
    {
        this->disable_animation();
        started_ = false;
    }

   protected:
    auto paint_event() -> bool override
    {
        if (index_ < frames_.size())
            Painter{*this}.put(frames_[index_], 0, 0);
        return Widget::paint_event();
    }

    auto timer_event() -> bool override
    {
        ++index_;
        if (index_ >= frames_.size())
            index_ = 0;
        return Widget::timer_event();
    }

   private:
    std::size_t index_ = 0;
    bool started_      = false;
    Period_t period_;
    Glyph_string frames_;
};

/// Specific Spinners
struct Spinner_cycle : Spinner {
    Spinner_cycle(Period_t period = Period_t{100}) : Spinner{"⠁⠈⠐⠠⢀⡀⠄⠂", period}
    {}
};

struct Spinner_cycle_ccw : Spinner {
    Spinner_cycle_ccw(Period_t period = Period_t{100})
        : Spinner{"⠁⠂⠄⡀⢀⠠⠐⠈", period}
    {}
};

struct Spinner_falling : Spinner {
    Spinner_falling(Period_t period = Period_t{100})
        : Spinner{"⠁⠂⠄⡀⡈⡐⡠⣀⣁⣂⣄⣌⣔⣤⣥⣦⣮⣶⣷⣿", period}
    {}
};

struct Spinner_rising : Spinner {
    Spinner_rising(Period_t period = Period_t{100})
        : Spinner{"⡀⠄⠂⠁⢁⠡⠑⠉⡉⠍⠋⢋⠫⠛⡛⠟⢟⠿⡿⣿", period}
    {}
};

struct Spinner_fill : Spinner {
    Spinner_fill(Period_t period = Period_t{100}) : Spinner{"⡀⣀⣄⣤⣦⣶⣷⣿", period}
    {}
};

struct Spinner_top_fill : Spinner {
    Spinner_top_fill(Period_t period = Period_t{100})
        : Spinner{"⠁⠉⠋⠛⠟⠿⡿⣿", period}
    {}
};

struct Spinner_tail : Spinner {
    Spinner_tail(Period_t period = Period_t{100})
        : Spinner{"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", period}
    {}
};

struct Spinner_switch : Spinner {
    Spinner_switch(Period_t period = Period_t{100})
        : Spinner{"⢹⢺⢼⣸⣇⡧⡗⡏", period}
    {}
};

struct Spinner_chase : Spinner {
    Spinner_chase(Period_t period = Period_t{100}) : Spinner{"⢄⢂⢁⡁⡈⡐⡠", period}
    {}
};

struct Spinner_line : Spinner {
    Spinner_line(Period_t period = Period_t{100}) : Spinner{"-\\|/", period} {}
};

struct Spinner_block_cycle : Spinner {
    Spinner_block_cycle(Period_t period = Period_t{100})
        : Spinner{"▖▘▝▗", period}
    {}
};

struct Spinner_fade : Spinner {
    Spinner_fade(Period_t period = Period_t{100}, std::size_t offset = 0)
        : Spinner{" ░▒▓██▓▒░ ", period, offset}
    {}
};

struct Spinner_quarter_circles : Spinner {
    Spinner_quarter_circles(Period_t period = Period_t{100})
        : Spinner{"◜◝◞◟", period}
    {}
};

struct Spinner_triangles : Spinner {
    Spinner_triangles(Period_t period = Period_t{100}) : Spinner{"◤◥◢◣", period}
    {}
};

struct Spinner_empty_triangles : Spinner {
    Spinner_empty_triangles(Period_t period = Period_t{100})
        : Spinner{"◸◹◿◺", period}
    {}
};

struct Spinner_clock : Spinner {
    Spinner_clock(Period_t period = Period_t{100}) : Spinner{"◴◷◶◵", period} {}
};

struct Spinner_box : Spinner {
    Spinner_box(Period_t period = Period_t{100}) : Spinner{"▤▧▥▨", period} {}
};

struct Spinner_cross : Spinner {
    Spinner_cross(Period_t period = Period_t{100}) : Spinner{"┽╀┾╁", period} {}
};

struct Spinner_vertical_pass : Spinner {
   public:
    Spinner_vertical_pass(Period_t period = Period_t{100})
        : Spinner{first() + second() + " ", period}
    {}

   private:
    auto first() -> Glyph_string { return "▁▂▃▄▅▆▇█"; }
    auto second() -> Glyph_string
    {
        auto result = first();
        result.add_attributes(Attribute::Inverse);
        return result;
    }
};

struct Spinner_horizontal_pass : Spinner {
   public:
    Spinner_horizontal_pass(Period_t period = Period_t{100})
        : Spinner{first() + second() + " ", period}
    {}

   private:
    auto first() -> Glyph_string { return "▏▎▍▌▋▊▉█"; }
    auto second() -> Glyph_string
    {
        auto result = first();
        result.add_attributes(Attribute::Inverse);
        return result;
    }
};

struct Spinner_bump : Spinner {
    Spinner_bump(Period_t period = Period_t{100})
        : Spinner{" ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁", period}
    {}
};

}  // namespace cppurses
#endif  // CPPURSES_WIDGET_WIDGET_SPINNER_HPP
<commit_msg>Update Spinner widget class<commit_after>#ifndef CPPURSES_WIDGET_WIDGET_SPINNER_HPP
#define CPPURSES_WIDGET_WIDGET_SPINNER_HPP
#include <cstddef>
#include <utility>

#include <cppurses/painter/glyph_string.hpp>
#include <cppurses/painter/painter.hpp>
#include <cppurses/system/animation_engine.hpp>
#include <cppurses/widget/widget.hpp>

namespace cppurses {

/// Single cell animated spinner.
class Spinner : public Widget {
   public:
    using Period_t = Animation_engine::Period_t;

   public:
    /// Each glyph in frames is a frame, offset is starting index into frames.
    Spinner(Glyph_string frames,
            Period_t period    = Period_t{100},
            std::size_t width  = 1,
            std::size_t offset = 0)
        : frames_{std::move(frames)},
          period_{period},
          width_{width},
          index_{offset}
    {
        height_policy.fixed(1);
        width_policy.fixed(width_);
    }

    void set_frames(Glyph_string frames) { frames_ = std::move(frames); }

    void set_period(Period_t period)
    {
        if (started_) {
            this->stop();
            period_ = period;
            this->start();
        }
        else
            period_ = period;
    }

    void start()
    {
        if (started_)
            return;
        this->enable_animation(period_);
        started_ = true;
    }

    void stop()
    {
        this->disable_animation();
        started_ = false;
        this->update();
    }

   protected:
    auto paint_event() -> bool override
    {
        if (started_)
            for (auto x = 0uL; x < width_; ++x) {
                Painter{*this}.put(frames_[index_], x, 0);
            }
        return Widget::paint_event();
    }

    auto timer_event() -> bool override
    {
        ++index_;
        if (index_ >= frames_.size())
            index_ = 0;
        this->update();
        return Widget::timer_event();
    }

   private:
    bool started_ = false;
    Glyph_string frames_;
    Period_t period_;
    std::size_t width_;
    std::size_t index_;
};

/// Specific Spinners
struct Spinner_cycle : Spinner {
    Spinner_cycle(Period_t period    = Period_t{100},
                  std::size_t width  = 1uL,
                  std::size_t offset = 0uL)
        : Spinner{"⠁⠈⠐⠠⢀⡀⠄⠂", period, width, offset}
    {}
};

struct Spinner_cycle_ccw : Spinner {
    Spinner_cycle_ccw(Period_t period    = Period_t{100},
                      std::size_t width  = 1uL,
                      std::size_t offset = 0uL)
        : Spinner{"⠁⠂⠄⡀⢀⠠⠐⠈", period, width, offset}
    {}
};

struct Spinner_fall : Spinner {
    Spinner_fall(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{"⠁⠂⠄⡀⡈⡐⡠⣀⣁⣂⣄⣌⣔⣤⣥⣦⣮⣶⣷⣿", period, width, offset}
    {}
};

struct Spinner_fall_two : Spinner {
    Spinner_fall_two(Period_t period    = Period_t{100},
                     std::size_t width  = 1uL,
                     std::size_t offset = 0uL)
        : Spinner{" ⠁⠉⠋⠛⠟⠿⡿⣿⣿⣿⣿⣷⣶⣦⣤⣄⣀⡀ ", period, width, offset}
    {}
};

struct Spinner_fall_three : Spinner {
    Spinner_fall_three(Period_t period    = Period_t{100},
                       std::size_t width  = 1uL,
                       std::size_t offset = 0uL)
        : Spinner{"   ⠁⠂⠄⡀⡈⡐⡠⣀⣁⣂⣄⣌⣔⣤⣥⣦⣮⣶⣷⣿⣿⣿⣿⣿⣿⡿⠿⢟⠟⡛⠛⠫⢋⠋⠍⡉⠉⠑⠡⢁⠁⠂⠄⡀   ", period,
                  width, offset}
    {}
};

struct Spinner_rise : Spinner {
    Spinner_rise(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{"⡀⠄⠂⠁⢁⠡⠑⠉⡉⠍⠋⢋⠫⠛⡛⠟⢟⠿⡿⣿", period, width, offset}
    {}
};

struct Spinner_rise_two : Spinner {
    Spinner_rise_two(Period_t period    = Period_t{100},
                     std::size_t width  = 1uL,
                     std::size_t offset = 0uL)
        : Spinner{"    ⡀⣀⣄⣤⣦⣶⣷⣿⣿⣿⣿⡿⠿⠟⠛⠋⠉⠁    ", period, width, offset}
    {}
};

struct Spinner_rise_three : Spinner {
    Spinner_rise_three(Period_t period    = Period_t{100},
                       std::size_t width  = 1uL,
                       std::size_t offset = 0uL)
        : Spinner{"   ⡀⠄⠂⠁⢁⠡⠑⠉⡉⠍⠋⢋⠫⠛⡛⠟⢟⠿⡿⣿⣿⣿⣿⣿⣿⣷⣶⣮⣦⣥⣤⣔⣌⣄⣂⣁⣀⡠⡐⡈⡀⠄⠂⠁   ", period,
                  width, offset}
    {}
};

struct Spinner_fill : Spinner {
    Spinner_fill(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{"⡀⣀⣄⣤⣦⣶⣷⣿", period, width, offset}
    {}
};

struct Spinner_top_fill : Spinner {
    Spinner_top_fill(Period_t period    = Period_t{100},
                     std::size_t width  = 1uL,
                     std::size_t offset = 0uL)
        : Spinner{"⠁⠉⠋⠛⠟⠿⡿⣿", period, width, offset}
    {}
};

struct Spinner_tail : Spinner {
    Spinner_tail(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", period, width, offset}
    {}
};

struct Spinner_switch : Spinner {
    Spinner_switch(Period_t period    = Period_t{100},
                   std::size_t width  = 1uL,
                   std::size_t offset = 0uL)
        : Spinner{"⢹⢺⢼⣸⣇⡧⡗⡏", period, width, offset}
    {}
};

struct Spinner_chase : Spinner {
    Spinner_chase(Period_t period    = Period_t{100},
                  std::size_t width  = 1uL,
                  std::size_t offset = 0uL)
        : Spinner{"⢄⢂⢁⡁⡈⡐⡠", period, width, offset}
    {}
};

struct Spinner_line : Spinner {
    Spinner_line(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{"-\\|/", period, width, offset}
    {}
};

struct Spinner_block_cycle : Spinner {
    Spinner_block_cycle(Period_t period    = Period_t{100},
                        std::size_t width  = 1uL,
                        std::size_t offset = 0uL)
        : Spinner{"▖▘▝▗", period, width, offset}
    {}
};

struct Spinner_fade : Spinner {
    Spinner_fade(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{"         ░░▒▓▓██████████████████▓▓▒░░         ", period,
                  width, offset}
    {}
};

/// Best used with multiple spinners horizontally, each offset one from neighbor
struct Spinner_fade_trail : Spinner {
    Spinner_fade_trail(Period_t period    = Period_t{100},
                       std::size_t width  = 1uL,
                       std::size_t offset = 0uL)
        : Spinner{"⢀⢀⠠⠠⢀⢀⠠⠠⢀░░▒▓▓██████████████████▓▓▒░░⢀⢀⠠⠠⢀⢀⠠⠠⢀", period,
                  width, offset}
    {}
};

struct Spinner_quarter_circles : Spinner {
    Spinner_quarter_circles(Period_t period    = Period_t{100},
                            std::size_t width  = 1uL,
                            std::size_t offset = 0uL)
        : Spinner{"◜◝◞◟", period, width, offset}
    {}
};

struct Spinner_triangles : Spinner {
    Spinner_triangles(Period_t period    = Period_t{100},
                      std::size_t width  = 1uL,
                      std::size_t offset = 0uL)
        : Spinner{"◤◥◢◣", period, width, offset}
    {}
};

struct Spinner_empty_triangles : Spinner {
    Spinner_empty_triangles(Period_t period    = Period_t{100},
                            std::size_t width  = 1uL,
                            std::size_t offset = 0uL)
        : Spinner{"◸◹◿◺", period, width, offset}
    {}
};

struct Spinner_clock : Spinner {
    Spinner_clock(Period_t period    = Period_t{100},
                  std::size_t width  = 1uL,
                  std::size_t offset = 0uL)
        : Spinner{"◴◷◶◵", period, width, offset}
    {}
};

struct Spinner_box : Spinner {
    Spinner_box(Period_t period    = Period_t{100},
                std::size_t width  = 1uL,
                std::size_t offset = 0uL)
        : Spinner{"▤▧▥▨", period, width, offset}
    {}
};

struct Spinner_cross : Spinner {
    Spinner_cross(Period_t period    = Period_t{100},
                  std::size_t width  = 1uL,
                  std::size_t offset = 0uL)
        : Spinner{"┽╀┾╁", period, width, offset}
    {}
};

struct Spinner_vertical_pass : Spinner {
   public:
    Spinner_vertical_pass(Period_t period    = Period_t{100},
                          std::size_t width  = 1uL,
                          std::size_t offset = 0uL)
        : Spinner{first() + second() + " ", period, width, offset}
    {}

   private:
    auto first() -> Glyph_string { return "▁▂▃▄▅▆▇█"; }
    auto second() -> Glyph_string
    {
        auto result = first();
        result.add_attributes(Attribute::Inverse);
        return result;
    }
};

struct Spinner_horizontal_pass : Spinner {
   public:
    Spinner_horizontal_pass(Period_t period    = Period_t{100},
                            std::size_t width  = 1uL,
                            std::size_t offset = 0uL)
        : Spinner{first() + second() + " ", period, width, offset}
    {}

   private:
    auto first() -> Glyph_string { return "▏▎▍▌▋▊▉█"; }
    auto second() -> Glyph_string
    {
        auto result = first();
        result.add_attributes(Attribute::Inverse);
        return result;
    }
};

struct Spinner_bump : Spinner {
    Spinner_bump(Period_t period    = Period_t{100},
                 std::size_t width  = 1uL,
                 std::size_t offset = 0uL)
        : Spinner{" ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁", period, width, offset}
    {}
};

}  // namespace cppurses
#endif  // CPPURSES_WIDGET_WIDGET_SPINNER_HPP
<|endoftext|>


<commit_before>#include "main.h"
#include <iostream>
#include <string>
namespace util
{

	void buildInfo()
	{
		std::cout << "-[ Build date: " << __DATE__ << "\n DEBUG: ";

#ifdef DEBUG
		std::cout << "TRUE\n";
#ifdef LEXICAL_ANANALYSIS_DEBUG
		std::cout << "LEXICAL_ANANALYSIS_DEBUG ENABLED\n";
#endif
#ifdef STRUCTUAL_INTEGRITY_TEST
		std::cout << "STRUCTUAL_INTEGRITY_TEST ENABLED\n";
#endif
#ifdef SYNTAX_TREE_DEBUG_INFO
		std::cout << "SYNTAX_TREE_DEBUG_INFO ENABLED\n";
#endif
#else
		std::cout << "False\n";
#endif
		std::cout << "\n]\n";

	}

	void help()
	{
		std::cout << "\nProgram help page\n";
		std::cout << "General info[1]\nNumbers[2]\nOperators [3]\nFunctions [4]\nVariables[5]\nDebug[6]\nExit[7]\nselect topic> ";
		std::string input;
		std::getline(std::cin, input);
		if (input == "1")
		{
			std::cout << "\nThis program is only meant to showcase an concept of expression handling by using tree like data structures. It serves in its current state as an replacement for a calculator or other software as bugs an limited precisions exists.\n\n" << "The goal of the program is to develop an expression interpretor back end to be utilized in a more advance graphical application.In its current state the application will try to evaluate any expression entered and compute an answer using floating point mathematics.\n\n" << " The expression can contain functions, variables operators and of course values in form of numbers.See the other topics in the help menu for more info.";

			return;
		}
		else if (input == "2")
		{
			std::cout << "\nValues are any real number.\nvalues can be entered as 35 -2 or 2e10\n2e10 is equal to writing 2*10^10 but the first is evaluated faster.\n";
			return;
		}
		else if (input == "3")
		{
			std::cout << "\noperators are + -/ *^\nThey represent addition, subtraction, division, multiplication and raised to x.\nparentheses are also accepted to alter order of evaluation\n";
			return;
		}
		else if (input == "4")
		{
			std::cout << "\nfunctions are called using the syntax func(x)\nWere func is the name of the function and x is the expression to act upon.\nA list of functions can be generatet using the menu. The left column is the function name and the right their memory address.\n";
			return;
		}
		else if (input == "5")
		{
			std::cout << "\nAn variable is defined as an variable memory storage unity which is used to represent an number during an callcilation. The variable can is defined as an string or single character which can be both upper and lower case.\n\nX, PI,ans are all legal variables.\n\nNames which are the same as any loaded function is illegal\nNames are case sensitive \nX is not equal to x\nans is always stores the result of previous calculations\nPI is an example of an constant which can not be altered by the assignment operator.\n\nVariable are assigned a value using the assigment operator =.\nX=12 is an legal assigment so is x=(23+45)/2 but 13 =x is illegal as the assigment operator excpects the variable on the left hand side.\n";
			return;
		}
		else if (input == "6")
		{
			std::cout << "\nthe menu item build information of which debug systems are activated, to enable more or less information the program has to be recompiled as the settings depend upon preprocessor defintion in the main.h header.\n\nLEXICAL_ANANALYSIS_DEBUG:\nOutputs information about how the lexical analysis interprets the different characters in an string.\n\nSYNTAX_TREE_DEBUG_INFO:\nincreased debug messages about memory allocations and deallocations conducted by the tree object\n\nSTRUCTUAL_INTEGRITY_TEST:\nCheck the syntax tree before evaluation to ensure that all pointers are valid.Aborts program execution on failure \n";

		}
		else if (input == "7")
		{
			return;
		}
		else
		{
			std::cout << "Unkown input, try again\n";
			return help();
		}
	}
}<commit_msg>Corrected spelling in help text<commit_after>#include "main.h"
#include <iostream>
#include <string>
namespace util
{

	void buildInfo()
	{
		std::cout << "-[ Build date: " << __DATE__ << "\n DEBUG: ";

#ifdef DEBUG
		std::cout << "TRUE\n";
#ifdef LEXICAL_ANANALYSIS_DEBUG
		std::cout << "LEXICAL_ANANALYSIS_DEBUG ENABLED\n";
#endif
#ifdef STRUCTUAL_INTEGRITY_TEST
		std::cout << "STRUCTUAL_INTEGRITY_TEST ENABLED\n";
#endif
#ifdef SYNTAX_TREE_DEBUG_INFO
		std::cout << "SYNTAX_TREE_DEBUG_INFO ENABLED\n";
#endif
#else
		std::cout << "False\n";
#endif
		std::cout << "\n]\n";

	}

	void help()
	{
		std::cout << "\nProgram help page\n";
		std::cout << "General info[1]\nNumbers[2]\nOperators [3]\nFunctions [4]\nVariables[5]\nDebug[6]\nExit[7]\nselect topic> ";
		std::string input;
		std::getline(std::cin, input);
		if (input == "1")
		{
			std::cout << "\nThis program is only meant to showcase an concept of expression handling by using tree like data structures. It in its current state it doesn't serve as an replacement for a calculator or other software as bugs and precisions problems may exist.\n\n" << "The goal of the program is to develop an expression interpretor back end to be utilized in a more advance graphical application.In its current state the application will try to evaluate any expression entered and compute an answer using floating point mathematics.\n\n" << " The expression can contain functions, variables operators and of course values in form of numbers.See the other topics in the help menu for more info.";

			return;
		}
		else if (input == "2")
		{
			std::cout << "\nValues are any real number.\nvalues can be entered as 35, -2 or 2e10\n2e10 is equal to writing 2*10^10 but the first is evaluated faster.\n";
			return;
		}
		else if (input == "3")
		{
			std::cout << "\noperators are + -/ *^\nThey represent addition, subtraction, division, multiplication and raised to.\nparentheses are also accepted to alter order of evaluation\n";
			return;
		}
		else if (input == "4")
		{
			std::cout << "\nfunctions are called using the syntax func(x)\nWere func is the name of the function and x is the expression to act upon.\nA list of functions can be generatet using the menu. The left column is the function name and the right their memory address.\n";
			return;
		}
		else if (input == "5")
		{
			std::cout << "\nAn variable is defined as an variable memory storage unit which is used to represent an number during an calculation. The variable can is defined as an string or single character which can be both upper and lower case.\n\nX, PI,ans are all legal variables.\n\nNames which are the same as any loaded function is illegal as the interpreter will fail to distinguish these from functions\nNames are case sensitive \nX is not equal to x\nans always stores the result of previous calculations\nPI is an example of an constant variable which can not be altered by the assignment operator.\n\nVariable are assigned a value using the assigment operator =.\nX=12 is an legal assigment so is x=(23+45)/2 but 13 =x is illegal as the assigment operator excpects the variable on the left hand side.\n";
			return;
		}
		else if (input == "6")
		{
			std::cout << "\nthe menu item build information of which debug systems are activated, to enable more or less information the program has to be recompiled as the settings depend upon preprocessor defintion in the main.h header.\n\nLEXICAL_ANANALYSIS_DEBUG:\nOutputs information about how the lexical analysis interprets the different characters in an string.\n\nSYNTAX_TREE_DEBUG_INFO:\nincreased debug messages about memory allocations and deallocations conducted by the tree object\n\nSTRUCTUAL_INTEGRITY_TEST:\nCheck the syntax tree before evaluation to ensure that all pointers are valid.Aborts program execution on failure \n";

		}
		else if (input == "7")
		{
			return;
		}
		else
		{
			std::cout << "Unkown input, try again\n";
			return help();
		}
	}
}<|endoftext|>


<commit_before>// Copyright Joshua Boyce 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is part of HadesMem.
// <http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

#pragma once

#include <memory>
#include <iterator>

#include "hadesmem/detail/warning_disable_prefix.hpp"
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include "hadesmem/detail/warning_disable_suffix.hpp"

#include <windows.h>
#include <tlhelp32.h>

#include "hadesmem/module.hpp"

namespace hadesmem
{

class Process;

namespace detail
{
  struct ModuleIteratorImpl;
}

class ModuleIterator :
  public boost::iterator_facade<
    ModuleIterator,
    Module,
    boost::single_pass_traversal_tag
    >
{
public:
  ModuleIterator() BOOST_NOEXCEPT;

  ModuleIterator(Process const& process);

  ~ModuleIterator() BOOST_NOEXCEPT;

private:
  friend class boost::iterator_core_access;

  typedef boost::iterator_facade<
    ModuleIterator,
    Module,
    boost::single_pass_traversal_tag
    > ModuleIteratorFacade;

  ModuleIteratorFacade::reference dereference() const;

  void increment();

  bool equal(ModuleIterator const& other) const BOOST_NOEXCEPT;

  struct detail::ModuleIteratorImpl;
  std::shared_ptr<detail::ModuleIteratorImpl> impl_;
};

}
<commit_msg>* [module_iterator} Remove unnecessary forward decl.<commit_after>// Copyright Joshua Boyce 2010-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is part of HadesMem.
// <http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

#pragma once

#include <memory>
#include <iterator>

#include "hadesmem/detail/warning_disable_prefix.hpp"
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include "hadesmem/detail/warning_disable_suffix.hpp"

#include <windows.h>
#include <tlhelp32.h>

#include "hadesmem/module.hpp"

namespace hadesmem
{

class Process;

namespace detail
{
  struct ModuleIteratorImpl;
}

class ModuleIterator :
  public boost::iterator_facade<
    ModuleIterator,
    Module,
    boost::single_pass_traversal_tag
    >
{
public:
  ModuleIterator() BOOST_NOEXCEPT;

  ModuleIterator(Process const& process);

  ~ModuleIterator() BOOST_NOEXCEPT;

private:
  friend class boost::iterator_core_access;

  typedef boost::iterator_facade<
    ModuleIterator,
    Module,
    boost::single_pass_traversal_tag
    > ModuleIteratorFacade;

  ModuleIteratorFacade::reference dereference() const;

  void increment();

  bool equal(ModuleIterator const& other) const BOOST_NOEXCEPT;

  std::shared_ptr<detail::ModuleIteratorImpl> impl_;
};

}
<|endoftext|>