<commit_before>/* INCLUDE CONFIG */
/* General */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sqlite3.h>
#include <string>

#include "stringC11.h"

/* RCML */
#include "module.h"
#include "db_module.h"
#include "avg_choise_module.h"

/* GLOBALS CONFIG */
#define IID "RCT.AVG_choise_module_v101"
typedef unsigned int uint;

AvgChoiceModule::AvgChoiceModule() {
  mi = new ModuleInfo;
  mi->uid = IID;
  mi->mode = ModuleInfo::Modes::PROD;
  mi->version = BUILD_NUMBER;
  mi->digest = NULL;
}

const struct ModuleInfo &AvgChoiceModule::getModuleInfo() { return *mi; }

void AvgChoiceModule::prepare(colorPrintfModule_t *colorPrintf_p,
                              colorPrintfModuleVA_t *colorPrintfVA_p) {
  this->colorPrintf_p = colorPrintfVA_p;
}

void *AvgChoiceModule::writePC(unsigned int *buffer_length) {
  (*buffer_length) = 0;
  return NULL;
}

int AvgChoiceModule::init() {
  //connect to data base here
  int rc = sqlite3_open("stats.db", &db);
  if( rc ){
    colorPrintf(ConsoleColor(ConsoleColor::red),"Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return(1);
  }
  return 0;
}

void AvgChoiceModule::final() {
  //disconnect from data base here
  sqlite3_close(db);
}

int AvgChoiceModule::startProgram(int uniq_index) { return 0; }

const DBRobotData *AvgChoiceModule::makeChoice(const DBFunctionData** function_data, uint count_functions,
                                            const DBRobotData** robots_data, uint count_robots) {

string psqlText =
"select uid\n"
"  from robot_uids ru\n"
"  join\n"
"      (select fc.robot_id,\n"
"              avg(fc.end-fc.start) as avg_time\n"
"         from function_calls fc\n"
"        where exists(select 1\n"
"                       from functions f\n"
"                       join contexts c\n"
"                         on f.context_id = c.id\n"
"                      where f.id = fc.function_id\n"
"                        and ( %FUNCS_CLAUSE%\n"
"                             )\n"
"                     ) %ROBOTS_CLAUSE%\n"
"        group by fc.robot_id\n"
"        order by avg_time asc\n"
"        limit 1\n"
"       ) b\n"
"    on (ru.id = b.robot_id)\n";

string sTmp = "";
for (uint i = 0; i <= count_functions-1; i++) {
    if (i >= 1) {
        sTmp += "or ";
    }
     sTmp += "(f.name = '" + (string)(function_data[i] -> name) + "'\n"
             " and f.position = " + to_string(function_data[i] -> position) + "\n"
             " and c.hash = '" + (string)(function_data[i] -> context_hash) + "')\n";
}
sTmp = sTmp.substr(0, sTmp.length()-1);
psqlText.replace(psqlText.find("%FUNCS_CLAUSE%"),14,sTmp);

sTmp = (string)"";
if (count_robots) {
    bool havenulluid = false;
    for (uint i = 0; i <= count_robots - 1; i++) {
        if (   *robots_data[i] -> robot_uid == 0
            or *robots_data[i] -> robot_uid == NULL
            or (string)(robots_data[i] -> robot_uid) == (string)"") {
            havenulluid = true;
            break;
        } else {
          sTmp += (string)"'" + (string)(robots_data[i] -> robot_uid) + "',";
        }
    }
    if (not havenulluid) {
        string sTmp2 =
        "\n and exists (select 1 from robot_uids ru\n"
        "		where ru.id = fc.robot_id\n"
        "		and ru.uid in (%IN_CLAUSE%))\n";
        sTmp = sTmp.substr(0,sTmp.length()-1);
        sTmp2.replace(sTmp2.find("%IN_CLAUSE%"),11,sTmp);
        sTmp2 = sTmp2.substr(0, sTmp2.length()-1);
        psqlText.replace(psqlText.find("%ROBOTS_CLAUSE%"),15,sTmp2);
    } else {
      psqlText.replace(psqlText.find("%ROBOTS_CLAUSE%"),15,"");
    }
} else {
  psqlText.replace(psqlText.find("%ROBOTS_CLAUSE%"),15,"");
}
#ifdef IS_DEBUG
    colorPrintf(ConsoleColor(ConsoleColor::yellow),"SQL statement:\n%s\n\n", psqlText.c_str());
#endif

int nRow = 0;
int nCol = 0;
char *zErrMsg = 0;
char **pResSQL = 0;
if( sqlite3_get_table(db, psqlText.c_str(), &pResSQL, &nRow, &nCol, &zErrMsg) != SQLITE_OK ){
   colorPrintf(ConsoleColor(ConsoleColor::red),"SQL error:\n%s\n\n", zErrMsg);
   sqlite3_free(zErrMsg);
   return NULL;
}
#ifdef IS_DEBUG
    colorPrintf(ConsoleColor(ConsoleColor::yellow),"SQL result:\n%s\n\n", pResSQL[1]);
#endif

const DBRobotData *pRes = NULL;
if (nCol > 0) {
for (uint i = 0; i <= count_robots - 1; i++) {
    if ( (string)(robots_data[i] -> robot_uid) == (string)pResSQL[1]) {
        pRes = robots_data[i];
        }
    }
}

sqlite3_free_table(pResSQL);
#ifdef IS_DEBUG
    colorPrintf(ConsoleColor(ConsoleColor::yellow),"MakeChoice result:\n%s\n\n", pRes -> robot_uid);
#endif
return pRes;
}

int AvgChoiceModule::endProgram(int unique_index) { return 0; }

void AvgChoiceModule::destroy() {
  delete mi;
  delete this;
}

void AvgChoiceModule::colorPrintf(ConsoleColor colors, const char *mask, ...) {
  va_list args;
  va_start(args, mask);
  (*colorPrintf_p)(this, colors, mask, args);
  va_end(args);
}

PREFIX_FUNC_DLL unsigned short getDBModuleApiVersion() {
  return MODULE_API_VERSION;
};
PREFIX_FUNC_DLL DBModule *getDBModuleObject() {
  return new AvgChoiceModule();
}
<commit_msg>no message<commit_after>/* INCLUDE CONFIG */
/* General */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sqlite3.h>
#include <string>

#include "stringC11.h"

/* RCML */
#include "module.h"
#include "db_module.h"
#include "avg_choiсe_module.h"

/* GLOBALS CONFIG */
#define IID "RCT.AVG_choise_module_v101"
typedef unsigned int uint;

AvgChoiceModule::AvgChoiceModule() {
  mi = new ModuleInfo;
  mi->uid = IID;
  mi->mode = ModuleInfo::Modes::PROD;
  mi->version = BUILD_NUMBER;
  mi->digest = NULL;
}

const struct ModuleInfo &AvgChoiceModule::getModuleInfo() { return *mi; }

void AvgChoiceModule::prepare(colorPrintfModule_t *colorPrintf_p,
                              colorPrintfModuleVA_t *colorPrintfVA_p) {
  this->colorPrintf_p = colorPrintfVA_p;
}

void *AvgChoiceModule::writePC(unsigned int *buffer_length) {
  (*buffer_length) = 0;
  return NULL;
}

int AvgChoiceModule::init() {
  //connect to data base here
  int rc = sqlite3_open("stats.db", &db);
  if( rc ){
    colorPrintf(ConsoleColor(ConsoleColor::red),"Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return(1);
  }
  return 0;
}

void AvgChoiceModule::final() {
  //disconnect from data base here
  sqlite3_close(db);
}

int AvgChoiceModule::startProgram(int uniq_index) { return 0; }

const DBRobotData *AvgChoiceModule::makeChoice(const DBFunctionData** function_data, uint count_functions,
                                            const DBRobotData** robots_data, uint count_robots) {

string psqlText =
"select uid\n"
"  from robot_uids ru\n"
"  join\n"
"      (select fc.robot_id,\n"
"              avg(fc.end-fc.start) as avg_time\n"
"         from function_calls fc\n"
"        where exists(select 1\n"
"                       from functions f\n"
"                       join contexts c\n"
"                         on f.context_id = c.id\n"
"                      where f.id = fc.function_id\n"
"                        and ( %FUNCS_CLAUSE%\n"
"                             )\n"
"                     ) %ROBOTS_CLAUSE%\n"
"        group by fc.robot_id\n"
"        order by avg_time asc\n"
"        limit 1\n"
"       ) b\n"
"    on (ru.id = b.robot_id)\n";

string sTmp = "";
for (uint i = 0; i <= count_functions-1; i++) {
    if (i >= 1) {
        sTmp += "or ";
    }
     sTmp += "(f.name = '" + (string)(function_data[i] -> name) + "'\n"
             " and f.position = " + to_string(function_data[i] -> position) + "\n"
             " and c.hash = '" + (string)(function_data[i] -> context_hash) + "')\n";
}
sTmp = sTmp.substr(0, sTmp.length()-1);
psqlText.replace(psqlText.find("%FUNCS_CLAUSE%"),14,sTmp);

sTmp = (string)"";
if (count_robots) {
    bool havenulluid = false;
    for (uint i = 0; i <= count_robots - 1; i++) {
        if (   *robots_data[i] -> robot_uid == 0
            or *robots_data[i] -> robot_uid == NULL
            or (string)(robots_data[i] -> robot_uid) == (string)"") {
            havenulluid = true;
            break;
        } else {
          sTmp += (string)"'" + (string)(robots_data[i] -> robot_uid) + "',";
        }
    }
    if (not havenulluid) {
        string sTmp2 =
        "\n and exists (select 1 from robot_uids ru\n"
        "		where ru.id = fc.robot_id\n"
        "		and ru.uid in (%IN_CLAUSE%))\n";
        sTmp = sTmp.substr(0,sTmp.length()-1);
        sTmp2.replace(sTmp2.find("%IN_CLAUSE%"),11,sTmp);
        sTmp2 = sTmp2.substr(0, sTmp2.length()-1);
        psqlText.replace(psqlText.find("%ROBOTS_CLAUSE%"),15,sTmp2);
    } else {
      psqlText.replace(psqlText.find("%ROBOTS_CLAUSE%"),15,"");
    }
} else {
  psqlText.replace(psqlText.find("%ROBOTS_CLAUSE%"),15,"");
}
#ifdef IS_DEBUG
    colorPrintf(ConsoleColor(ConsoleColor::yellow),"SQL statement:\n%s\n\n", psqlText.c_str());
#endif

int nRow = 0;
int nCol = 0;
char *zErrMsg = 0;
char **pResSQL = 0;
if( sqlite3_get_table(db, psqlText.c_str(), &pResSQL, &nRow, &nCol, &zErrMsg) != SQLITE_OK ){
   colorPrintf(ConsoleColor(ConsoleColor::red),"SQL error:\n%s\n\n", zErrMsg);
   sqlite3_free(zErrMsg);
   return NULL;
}
#ifdef IS_DEBUG
    colorPrintf(ConsoleColor(ConsoleColor::yellow),"SQL result:\n%s\n\n", pResSQL[1]);
#endif

const DBRobotData *pRes = NULL;
if (nCol > 0) {
for (uint i = 0; i <= count_robots - 1; i++) {
    if ( (string)(robots_data[i] -> robot_uid) == (string)pResSQL[1]) {
        pRes = robots_data[i];
        }
    }
}

sqlite3_free_table(pResSQL);
#ifdef IS_DEBUG
    colorPrintf(ConsoleColor(ConsoleColor::yellow),"MakeChoice result:\n%s\n\n", pRes -> robot_uid);
#endif
return pRes;
}

int AvgChoiceModule::endProgram(int unique_index) { return 0; }

void AvgChoiceModule::destroy() {
  delete mi;
  delete this;
}

void AvgChoiceModule::colorPrintf(ConsoleColor colors, const char *mask, ...) {
  va_list args;
  va_start(args, mask);
  (*colorPrintf_p)(this, colors, mask, args);
  va_end(args);
}

PREFIX_FUNC_DLL unsigned short getDBModuleApiVersion() {
  return MODULE_API_VERSION;
};
PREFIX_FUNC_DLL DBModule *getDBModuleObject() {
  return new AvgChoiceModule();
}
<|endoftext|>


<commit_before>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include <QtGui/QApplication>
#include <QtGui/QMessageBox>
#include <QtOpenGL/QGLFormat>

#include "mainwindow.h"
#include <avogadro/io/cmlformat.h>

#ifdef Avogadro_ENABLE_RPC
#include "rpclistener.h"
#endif

int main(int argc, char *argv[])
{
  QCoreApplication::setOrganizationName("OpenChemistry");
  QCoreApplication::setOrganizationDomain("openchemistry.org");
  QCoreApplication::setApplicationName("Avogaro");

  QApplication app(argc, argv);

  if (!QGLFormat::hasOpenGL()) {
    QMessageBox::information(0, "Avogadro",
                             "This system does not support OpenGL!");
    return 1;
  }
  // Set up the default format for our GL contexts.
  QGLFormat defaultFormat = QGLFormat::defaultFormat();
  defaultFormat.setSampleBuffers(true);
  QGLFormat::setDefaultFormat(defaultFormat);

  QString fileName;
  bool disableSettings = false;
#ifdef QTTESTING
  QString testFile;
  bool testExit = true;
#endif
  QStringList args = QCoreApplication::arguments();
  for (QStringList::const_iterator it = args.constBegin() + 1;
       it != args.constEnd(); ++it) {
    if (*it == "--test-file" && it + 1 != args.constEnd()) {
#ifdef QTTESTING
      testFile = *(++it);
#else
      qWarning("Avogadro called with --test-file but testing is disabled.");
      return EXIT_FAILURE;
#endif
    }
    else if (*it == "--test-no-exit") {
#ifdef QTTESTING
      testExit = false;
#else
      qWarning("Avogadro called with --test-no-exit but testing is disabled.");
      return EXIT_FAILURE;
#endif
    }
    else if (*it == "--disable-settings") {
      disableSettings = true;
    }
    else if (it->startsWith("-")) {
      qWarning("Unknown command line option '%s'", qPrintable(*it));
      return EXIT_FAILURE;
    }
    else { // Assume it is a file name.
      fileName = *it;
    }
  }

  Avogadro::MainWindow *window = new Avogadro::MainWindow(fileName,
                                                          disableSettings);
#ifdef QTTESTING
  window->playTest(testFile, testExit);
#endif
  window->show();

#ifdef Avogadro_ENABLE_RPC
  // create rpc listener
  Avogadro::RpcListener listener;
  listener.start();
#endif

  return app.exec();
}
<commit_msg>Fix typo in QSettings application name.<commit_after>/******************************************************************************

  This source file is part of the Avogadro project.

  Copyright 2012 Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include <QtGui/QApplication>
#include <QtGui/QMessageBox>
#include <QtOpenGL/QGLFormat>

#include "mainwindow.h"
#include <avogadro/io/cmlformat.h>

#ifdef Avogadro_ENABLE_RPC
#include "rpclistener.h"
#endif

int main(int argc, char *argv[])
{
  QCoreApplication::setOrganizationName("OpenChemistry");
  QCoreApplication::setOrganizationDomain("openchemistry.org");
  QCoreApplication::setApplicationName("Avogadro");

  QApplication app(argc, argv);

  if (!QGLFormat::hasOpenGL()) {
    QMessageBox::information(0, "Avogadro",
                             "This system does not support OpenGL!");
    return 1;
  }
  // Set up the default format for our GL contexts.
  QGLFormat defaultFormat = QGLFormat::defaultFormat();
  defaultFormat.setSampleBuffers(true);
  QGLFormat::setDefaultFormat(defaultFormat);

  QString fileName;
  bool disableSettings = false;
#ifdef QTTESTING
  QString testFile;
  bool testExit = true;
#endif
  QStringList args = QCoreApplication::arguments();
  for (QStringList::const_iterator it = args.constBegin() + 1;
       it != args.constEnd(); ++it) {
    if (*it == "--test-file" && it + 1 != args.constEnd()) {
#ifdef QTTESTING
      testFile = *(++it);
#else
      qWarning("Avogadro called with --test-file but testing is disabled.");
      return EXIT_FAILURE;
#endif
    }
    else if (*it == "--test-no-exit") {
#ifdef QTTESTING
      testExit = false;
#else
      qWarning("Avogadro called with --test-no-exit but testing is disabled.");
      return EXIT_FAILURE;
#endif
    }
    else if (*it == "--disable-settings") {
      disableSettings = true;
    }
    else if (it->startsWith("-")) {
      qWarning("Unknown command line option '%s'", qPrintable(*it));
      return EXIT_FAILURE;
    }
    else { // Assume it is a file name.
      fileName = *it;
    }
  }

  Avogadro::MainWindow *window = new Avogadro::MainWindow(fileName,
                                                          disableSettings);
#ifdef QTTESTING
  window->playTest(testFile, testExit);
#endif
  window->show();

#ifdef Avogadro_ENABLE_RPC
  // create rpc listener
  Avogadro::RpcListener listener;
  listener.start();
#endif

  return app.exec();
}
<|endoftext|>


<commit_before>#include "Student.h"
#include "Database.h"

#include <sstream>
#include <string>

using namespace std;

Student::Student(string id, string firstName, string lastName, Database db)
    : id(id), firstName(firstName), lastName(lastName), db(db) {}

// Getters
string Student::getId() const { return id; }

string Student::getFirstName() const { return firstName; }

string Student::getLastName() const { return lastName; }

// Setters
void Student::setId(string a_id) { id = a_id; }

void Student::setFirstName(string a_firstName) { firstName = a_firstName; }

void Student::setLastName(string a_lastName) { lastName = a_lastName; }

// Database query commands
void Student::insert() {
  stringstream command;
  command << "INSERT INTO students VALUES (";
  command << "'" << getId() << "', ";
  command << "'" << getFirstName() << "', ";
  command << "'" << getLastName() << "'";
  command << ");";

  db.execute(command.str());
}

void Student::update() const {
  stringstream command;
  command << "UPDATE students SET ";
  command << "firstName = '" << getFirstName() << "', ";
  command << "lastName = '" << getLastName() << "' ";
  command << "WHERE id = '" << getId() << "'";
  command << ";";

  db.execute(command.str());
}

void Student::remove() const {
  stringstream command;
  command << "DELETE from students WHERE ";
  command << "id = '" << getId() << "'";
  command << ";";

  db.execute(command.str());
}
<commit_msg>Add static database query commands<commit_after>#include "Student.h"
#include "Database.h"

#include <sstream>
#include <string>

using namespace std;

Student::Student(string id, string firstName, string lastName, Database db)
    : id(id), firstName(firstName), lastName(lastName), db(db) {}

// Getters
string Student::getId() const { return id; }

string Student::getFirstName() const { return firstName; }

string Student::getLastName() const { return lastName; }

// Setters
void Student::setId(string a_id) { id = a_id; }

void Student::setFirstName(string a_firstName) { firstName = a_firstName; }

void Student::setLastName(string a_lastName) { lastName = a_lastName; }

// Database query commands
void Student::insert() {
  stringstream command;
  command << "INSERT INTO students VALUES (";
  command << "'" << getId() << "', ";
  command << "'" << getFirstName() << "', ";
  command << "'" << getLastName() << "'";
  command << ");";

  db.execute(command.str());
}

void Student::update() const {
  stringstream command;
  command << "UPDATE students SET ";
  command << "firstName = '" << getFirstName() << "', ";
  command << "lastName = '" << getLastName() << "' ";
  command << "WHERE id = '" << getId() << "'";
  command << ";";

  db.execute(command.str());
}

void Student::remove() const {
  stringstream command;
  command << "DELETE from students WHERE ";
  command << "id = '" << getId() << "'";
  command << ";";

  db.execute(command.str());
}

// Static database query commands
void Student::create(Database db) {
  string command = "CREATE TABLE IF NOT EXISTS students ("
                   "    id        TEXT (16) PRIMARY KEY"
                   "                        NOT NULL"
                   "                        UNIQUE,"
                   "    firstName TEXT (36) NOT NULL,"
                   "    lastName  TEXT (36) NOT NULL"
                   ");";

  db.execute(command);
}

map<string, Student *> Student::read(Database db) {
  map<string, Student *> data;
  vector<vector<string>> results;

  results = db.execute("SELECT * FROM students;");

  for (vector<string> row : results) {
    string id = row[0];

    data[id] = new Student(id, row[1], row[2], db);
  }

  return data;
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#define EIGEN_NO_STATIC_ASSERT

#include "main.h"

template<typename MatrixType> void adjoint(const MatrixType& m)
{
  /* this test covers the following files:
     Transpose.h Conjugate.h Dot.h
  */
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             mzero = MatrixType::Zero(rows, cols),
             identity = SquareMatrixType::Identity(rows, rows),
             square = SquareMatrixType::Random(rows, rows);
  VectorType v1 = VectorType::Random(rows),
             v2 = VectorType::Random(rows),
             v3 = VectorType::Random(rows),
             vzero = VectorType::Zero(rows);

  Scalar s1 = internal::random<Scalar>(),
         s2 = internal::random<Scalar>();

  // check basic compatibility of adjoint, transpose, conjugate
  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);

  // check multiplicative behavior
  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     internal::conj(s1) * m1.adjoint());

  // check basic properties of dot, norm, norm2
  typedef typename NumTraits<Scalar>::Real RealScalar;

  RealScalar ref = NumTraits<Scalar>::IsInteger ? 0 : std::max((s1 * v1 + s2 * v2).norm(),v3.norm());
  VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
  VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), ref));
  VERIFY_IS_APPROX(internal::conj(v1.dot(v2)),               v2.dot(v1));
  VERIFY_IS_APPROX(internal::real(v1.dot(v1)),                v1.squaredNorm());
  if(!NumTraits<Scalar>::IsInteger)
    VERIFY_IS_APPROX(v1.squaredNorm(),                v1.norm() * v1.norm());
  VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(vzero.dot(v1)),  static_cast<RealScalar>(1));

  // check compatibility of dot and adjoint

  ref = NumTraits<Scalar>::IsInteger ? 0 : std::max(std::max(v1.norm(),v2.norm()),std::max((square * v2).norm(),(square.adjoint() * v1).norm()));
  VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));

  // like in testBasicStuff, test operator() to check const-qualification
  Index r = internal::random<Index>(0, rows-1),
      c = internal::random<Index>(0, cols-1);
  VERIFY_IS_APPROX(m1.conjugate()(r,c), internal::conj(m1(r,c)));
  VERIFY_IS_APPROX(m1.adjoint()(c,r), internal::conj(m1(r,c)));

  if(!NumTraits<Scalar>::IsInteger)
  {
    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
    // normalized() in order to produce a consistent result.
    VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
  }

  // check inplace transpose
  m3 = m1;
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.transpose());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1);

  // check inplace adjoint
  m3 = m1;
  m3.adjointInPlace();
  VERIFY_IS_APPROX(m3,m1.adjoint());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.conjugate());

  // check mixed dot product
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  RealVectorType rv1 = RealVectorType::Random(rows);
  VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
  VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
}

void test_adjoint()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( adjoint(Matrix3d()) );
    CALL_SUBTEST_3( adjoint(Matrix4f()) );
    CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,50), internal::random<int>(1,50))) );
  }
  // test a large matrix only once
  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );

#ifdef EIGEN_TEST_PART_4
  {
    MatrixXcf a(10,10), b(10,10);
    VERIFY_RAISES_ASSERT(a = a.transpose());
    VERIFY_RAISES_ASSERT(a = a.transpose() + b);
    VERIFY_RAISES_ASSERT(a = b + a.transpose());
    VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
    VERIFY_RAISES_ASSERT(a = a.adjoint());
    VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
    VERIFY_RAISES_ASSERT(a = b + a.adjoint());

    // no assertion should be triggered for these cases:
    a.transpose() = a.transpose();
    a.transpose() += a.transpose();
    a.transpose() += a.transpose() + b;
    a.transpose() = a.adjoint();
    a.transpose() += a.adjoint();
    a.transpose() += a.adjoint() + b;
  }
#endif
}

<commit_msg>add test for normalize() and normalized()<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#define EIGEN_NO_STATIC_ASSERT

#include "main.h"

template<typename MatrixType> void adjoint(const MatrixType& m)
{
  /* this test covers the following files:
     Transpose.h Conjugate.h Dot.h
  */
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             mzero = MatrixType::Zero(rows, cols),
             identity = SquareMatrixType::Identity(rows, rows),
             square = SquareMatrixType::Random(rows, rows);
  VectorType v1 = VectorType::Random(rows),
             v2 = VectorType::Random(rows),
             v3 = VectorType::Random(rows),
             vzero = VectorType::Zero(rows);

  Scalar s1 = internal::random<Scalar>(),
         s2 = internal::random<Scalar>();

  // check basic compatibility of adjoint, transpose, conjugate
  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);

  // check multiplicative behavior
  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     internal::conj(s1) * m1.adjoint());

  // check basic properties of dot, norm, norm2
  typedef typename NumTraits<Scalar>::Real RealScalar;

  RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : std::max((s1 * v1 + s2 * v2).norm(),v3.norm());
  VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
  VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), ref));
  VERIFY_IS_APPROX(internal::conj(v1.dot(v2)),               v2.dot(v1));
  VERIFY_IS_APPROX(internal::real(v1.dot(v1)),                v1.squaredNorm());
  if(!NumTraits<Scalar>::IsInteger) {
    VERIFY_IS_APPROX(v1.squaredNorm(),                v1.norm() * v1.norm());
    // check normalized() and normalize()
    VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
    // normalize() returns a reference to *this
    v3 = v1;
    VERIFY_IS_APPROX(v1, v1.norm() * v3.normalize());
    VERIFY_IS_APPROX(v3, v1.normalized());
    VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
  }
  VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(vzero.dot(v1)),  static_cast<RealScalar>(1));

  // check compatibility of dot and adjoint

  ref = NumTraits<Scalar>::IsInteger ? 0 : std::max(std::max(v1.norm(),v2.norm()),std::max((square * v2).norm(),(square.adjoint() * v1).norm()));
  VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));

  // like in testBasicStuff, test operator() to check const-qualification
  Index r = internal::random<Index>(0, rows-1),
      c = internal::random<Index>(0, cols-1);
  VERIFY_IS_APPROX(m1.conjugate()(r,c), internal::conj(m1(r,c)));
  VERIFY_IS_APPROX(m1.adjoint()(c,r), internal::conj(m1(r,c)));

  if(!NumTraits<Scalar>::IsInteger)
  {
    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
    // normalized() in order to produce a consistent result.
    VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
  }

  // check inplace transpose
  m3 = m1;
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.transpose());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1);

  // check inplace adjoint
  m3 = m1;
  m3.adjointInPlace();
  VERIFY_IS_APPROX(m3,m1.adjoint());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.conjugate());

  // check mixed dot product
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  RealVectorType rv1 = RealVectorType::Random(rows);
  VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
  VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
}

void test_adjoint()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( adjoint(Matrix3d()) );
    CALL_SUBTEST_3( adjoint(Matrix4f()) );
    CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,50), internal::random<int>(1,50))) );
  }
  // test a large matrix only once
  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );

#ifdef EIGEN_TEST_PART_4
  {
    MatrixXcf a(10,10), b(10,10);
    VERIFY_RAISES_ASSERT(a = a.transpose());
    VERIFY_RAISES_ASSERT(a = a.transpose() + b);
    VERIFY_RAISES_ASSERT(a = b + a.transpose());
    VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
    VERIFY_RAISES_ASSERT(a = a.adjoint());
    VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
    VERIFY_RAISES_ASSERT(a = b + a.adjoint());

    // no assertion should be triggered for these cases:
    a.transpose() = a.transpose();
    a.transpose() += a.transpose();
    a.transpose() += a.transpose() + b;
    a.transpose() = a.adjoint();
    a.transpose() += a.adjoint();
    a.transpose() += a.adjoint() + b;
  }
#endif
}

<|endoftext|>


<commit_before>#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdexcept>
#include <map>
#include <fstream>
#include <xorg/gtest/xorg-gtest.h>
#include <linux/input.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#define XK_LATIN1
#include <X11/keysymdef.h>
#include <X11/XF86keysym.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

#include "input-driver-test.h"
#include "device-interface.h"
#include "helpers.h"

/**
 * Mouse driver test.
 */
class MouseDriverTest : public InputDriverTest,
                        public DeviceInterface {
public:
    /**
     * Initializes a standard mouse device with two wheels.
     */
    virtual void SetUp() {
        SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
        InputDriverTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single mouse CorePointer device based on
     * the evemu device.
     */
    virtual void SetUpConfigAndLog(const std::string &param) {
        server.SetOption("-logfile", "/tmp/Xorg-mouse-driver.log");
        server.SetOption("-config", "/tmp/mouse-driver.conf");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("mouse", "--device--",
                               "Option \"ZAxisMapping\" \"4 5 6 7\"\n"
                               "Option \"Protocol\" \"ImPS/2\"\n"
                               "Option \"CorePointer\" \"on\"\n");
        config.WriteConfig("/tmp/mouse-driver.conf");
    }
};

void scroll_wheel_event(::Display *display,
                        xorg::testing::evemu::Device *dev,
                        int axis, int value, unsigned int button) {

    dev->PlayOne(EV_REL, axis, value, 1);
    XSync(display, False);

    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(display, ButtonPress, -1, -1, 1000), true);

    XEvent btn;
    int nevents = 0;
    while(XPending(display)) {
        XNextEvent(display, &btn);

        ASSERT_EQ(btn.xbutton.type, ButtonPress);
        ASSERT_EQ(btn.xbutton.button, button);

        XNextEvent(display, &btn);
        ASSERT_EQ(btn.xbutton.type, ButtonRelease);
        ASSERT_EQ(btn.xbutton.button, button);

        nevents++;
    }

    ASSERT_EQ(nevents, abs(value));
}

TEST_F(MouseDriverTest, ScrollWheel)
{
    XSelectInput(Display(), DefaultRootWindow(Display()), ButtonPressMask | ButtonReleaseMask);
    XFlush(Display());
    XSync(Display(), False);

    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, 1, 4);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, 2, 4);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, 3, 4);

    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, -1, 5);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, -2, 5);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, -3, 5);

    /* Vertical scrolling only, it appears we can't send HScroll events */
}

TEST_F(MouseDriverTest, Move)
{
    XSelectInput(Display(), DefaultRootWindow(Display()), PointerMotionMask);
    XFlush(Display());
    XSync(Display(), False);

    dev->PlayOne(EV_REL, REL_X, -1, 1);

    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    int x, y;
    XEvent ev;
    XNextEvent(Display(), &ev);
    x = ev.xmotion.x_root;
    y = ev.xmotion.y_root;

    /* left */
    dev->PlayOne(EV_REL, REL_X, -1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_LT(ev.xmotion.x_root, x);
    ASSERT_EQ(ev.xmotion.y_root, y);
    x = ev.xmotion.x_root;

    /* right */
    dev->PlayOne(EV_REL, REL_X, 1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_GT(ev.xmotion.x_root, x);
    ASSERT_EQ(ev.xmotion.y_root, y);
    x = ev.xmotion.x_root;

    /* up */
    dev->PlayOne(EV_REL, REL_Y, -1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_EQ(ev.xmotion.x_root, x);
    ASSERT_LT(ev.xmotion.y_root, y);
    y = ev.xmotion.y_root;

    /* down */
    dev->PlayOne(EV_REL, REL_Y, 1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_EQ(ev.xmotion.x_root, x);
    ASSERT_GT(ev.xmotion.y_root, y);
    y = ev.xmotion.y_root;
}

TEST_F(MouseDriverTest, DevNode)
{
    Atom node_prop = XInternAtom(Display(), "Device Node", True);

    ASSERT_NE(node_prop, (Atom)None) << "This requires server 1.11";

    int deviceid = -1;
    ASSERT_EQ(FindInputDeviceByName(Display(), "--device--", &deviceid), 1) << "Failed to find device.";

    Atom type;
    int format;
    unsigned long nitems, bytes_after;
    char *data;
    XIGetProperty(Display(), deviceid, node_prop, 0, 100, False,
                  AnyPropertyType, &type, &format, &nitems, &bytes_after,
                  (unsigned char**)&data);
    ASSERT_EQ(type, XA_STRING);

    std::string devnode(data);
    ASSERT_EQ(devnode.compare("/dev/input/mice"), 0);

    XFree(data);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>input/mouse: add test for mouse driver button events<commit_after>#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdexcept>
#include <map>
#include <fstream>
#include <xorg/gtest/xorg-gtest.h>
#include <linux/input.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#define XK_LATIN1
#include <X11/keysymdef.h>
#include <X11/XF86keysym.h>
#include <X11/Xutil.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>

#include "input-driver-test.h"
#include "device-interface.h"
#include "helpers.h"

/**
 * Mouse driver test.
 */
class MouseDriverTest : public InputDriverTest,
                        public DeviceInterface {
public:
    /**
     * Initializes a standard mouse device with two wheels.
     */
    virtual void SetUp() {
        SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
        InputDriverTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single mouse CorePointer device based on
     * the evemu device.
     */
    virtual void SetUpConfigAndLog(const std::string &param) {
        server.SetOption("-logfile", "/tmp/Xorg-mouse-driver.log");
        server.SetOption("-config", "/tmp/mouse-driver.conf");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("mouse", "--device--",
                               "Option \"ZAxisMapping\" \"4 5 6 7\"\n"
                               "Option \"Protocol\" \"ImPS/2\"\n"
                               "Option \"CorePointer\" \"on\"\n");
        config.WriteConfig("/tmp/mouse-driver.conf");
    }
};

void scroll_wheel_event(::Display *display,
                        xorg::testing::evemu::Device *dev,
                        int axis, int value, unsigned int button) {

    dev->PlayOne(EV_REL, axis, value, 1);
    XSync(display, False);

    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(display, ButtonPress, -1, -1, 1000), true);

    XEvent btn;
    int nevents = 0;
    while(XPending(display)) {
        XNextEvent(display, &btn);

        ASSERT_EQ(btn.xbutton.type, ButtonPress);
        ASSERT_EQ(btn.xbutton.button, button);

        XNextEvent(display, &btn);
        ASSERT_EQ(btn.xbutton.type, ButtonRelease);
        ASSERT_EQ(btn.xbutton.button, button);

        nevents++;
    }

    ASSERT_EQ(nevents, abs(value));
}

TEST_F(MouseDriverTest, ScrollWheel)
{
    XSelectInput(Display(), DefaultRootWindow(Display()), ButtonPressMask | ButtonReleaseMask);
    XFlush(Display());
    XSync(Display(), False);

    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, 1, 4);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, 2, 4);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, 3, 4);

    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, -1, 5);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, -2, 5);
    scroll_wheel_event(Display(), dev.get(), REL_WHEEL, -3, 5);

    /* Vertical scrolling only, it appears we can't send HScroll events */
}

TEST_F(MouseDriverTest, Move)
{
    XSelectInput(Display(), DefaultRootWindow(Display()), PointerMotionMask);
    XFlush(Display());
    XSync(Display(), False);

    dev->PlayOne(EV_REL, REL_X, -1, 1);

    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    int x, y;
    XEvent ev;
    XNextEvent(Display(), &ev);
    x = ev.xmotion.x_root;
    y = ev.xmotion.y_root;

    /* left */
    dev->PlayOne(EV_REL, REL_X, -1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_LT(ev.xmotion.x_root, x);
    ASSERT_EQ(ev.xmotion.y_root, y);
    x = ev.xmotion.x_root;

    /* right */
    dev->PlayOne(EV_REL, REL_X, 1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_GT(ev.xmotion.x_root, x);
    ASSERT_EQ(ev.xmotion.y_root, y);
    x = ev.xmotion.x_root;

    /* up */
    dev->PlayOne(EV_REL, REL_Y, -1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_EQ(ev.xmotion.x_root, x);
    ASSERT_LT(ev.xmotion.y_root, y);
    y = ev.xmotion.y_root;

    /* down */
    dev->PlayOne(EV_REL, REL_Y, 1, 1);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), MotionNotify, -1, -1, 1000), true);

    XNextEvent(Display(), &ev);
    ASSERT_EQ(ev.xmotion.x_root, x);
    ASSERT_GT(ev.xmotion.y_root, y);
    y = ev.xmotion.y_root;
}

TEST_F(MouseDriverTest, BtnPress)
{
    XSelectInput(Display(), DefaultRootWindow(Display()), ButtonPressMask | ButtonReleaseMask);
    XSync(Display(), False);

    dev->PlayOne(EV_KEY, BTN_LEFT, 1, 1);

    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), ButtonPress, -1, -1, 1000), true);
    XEvent ev;
    XNextEvent(Display(), &ev);
    ASSERT_FALSE(XPending(Display()));
}

TEST_F(MouseDriverTest, BtnRelease)
{
    XSelectInput(Display(), DefaultRootWindow(Display()), ButtonReleaseMask);
    XSync(Display(), False);

    dev->PlayOne(EV_KEY, BTN_LEFT, 1, true);

    dev->PlayOne(EV_KEY, BTN_LEFT, 0, true);
    ASSERT_EQ(xorg::testing::XServer::WaitForEventOfType(Display(), ButtonRelease, -1, -1, 1000), true);
    XEvent ev;
    XNextEvent(Display(), &ev);

    ASSERT_FALSE(XPending(Display()));
}

TEST_F(MouseDriverTest, DevNode)
{
    Atom node_prop = XInternAtom(Display(), "Device Node", True);

    ASSERT_NE(node_prop, (Atom)None) << "This requires server 1.11";

    int deviceid = -1;
    ASSERT_EQ(FindInputDeviceByName(Display(), "--device--", &deviceid), 1) << "Failed to find device.";

    Atom type;
    int format;
    unsigned long nitems, bytes_after;
    char *data;
    XIGetProperty(Display(), deviceid, node_prop, 0, 100, False,
                  AnyPropertyType, &type, &format, &nitems, &bytes_after,
                  (unsigned char**)&data);
    ASSERT_EQ(type, XA_STRING);

    std::string devnode(data);
    ASSERT_EQ(devnode.compare("/dev/input/mice"), 0);

    XFree(data);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before><commit_msg>Documented internal namespace<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 HOLDER 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.
#include <iostream>
#include <Common/Colorful.hh>
#include <Lex/Lexer.hh>
#include <Object/StringObject.hh>
#include <Core/TadpoleVM.hh>
#include <Compiler/Parser.hh>

namespace Tadpole::Compiler {

GlobalParser::GlobalParser(Core::TadpoleVM& vm, Lex::Lexer& lex) noexcept
  : vm_(vm), lex_(lex) {
}

void GlobalParser::iter_objects(Object::ObjectVisitor&& visitor) {
  // TODO:
}

Object::FunctionObject* GlobalParser::compile() {
  // TODO:
  return nullptr;
}

const ParseRule& GlobalParser::get_rule(Lex::TokenKind kind) const noexcept {
  static const ParseRule _rules[] = {
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(LPAREN, "(")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(RPAREN, ")")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(LBRACE, "{")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(RBRACE, "}")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(COMMA, ",")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(MINUS, "-")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(PLUS, "+")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(SEMI, ";")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(SLASH, "/")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(STAR, "*")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(EQ, "=")

    {nullptr, nullptr, Precedence::NONE}, // TOKEN(IDENTIFIER, "Identifier")
    {nullptr, nullptr, Precedence::NONE}, // TOKEN(NUMERIC, "Numeric")
    {nullptr, nullptr, Precedence::NONE}, // TOKEN(STRING, "String")

    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(FALSE, "false")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(FN, "fn")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(NIL, "nil")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(TRUE, "true")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(VAR, "var")

    {nullptr, nullptr, Precedence::NONE}, // TOKEN(EOF, "Eof")
    {nullptr, nullptr, Precedence::NONE}, // TOKEN(ERR, "Error")
  };

  return _rules[Common::as_type<int>(kind)];
}

void GlobalParser::error_at(const Lex::Token& tok, const str_t& msg) noexcept {
  if (panic_mode_)
    return;
  panic_mode_ = true;

  std::cerr
    << Common::Colorful::fg::red
    << "SyntaxError:" << std::endl
    << "  [LINE: " << tok.lineno() << "] ERROR ";
  if (tok.kind() == Lex::TokenKind::TK_EOF)
    std::cerr << "at end ";
  else if (tok.kind() == Lex::TokenKind::TK_ERR)
    TADPOLE_UNUSED(0);
  else
    std::cerr << "at `" << tok.literal() << "` ";
  std::cerr << ": " << msg << Common::Colorful::reset << std::endl;
}

void GlobalParser::advance() {
  prev_ = curr_;

  for (;;) {
    curr_ = lex_.next_token();
    if (!check(Lex::TokenKind::TK_ERR))
      break;

    error_at_current(curr_.as_string());
  }
}

void GlobalParser::consume(Lex::TokenKind kind, const str_t& msg) {
  if (check(kind))
    advance();
  else
    error_at_current(msg);
}

bool GlobalParser::match(Lex::TokenKind kind) {
  if (check(kind)) {
    advance();
    return true;
  }
  return false;
}

void GlobalParser::init_compiler(FunctionCompiler* compiler, int scope_depth, FunctionType fn_type) {
  Object::StringObject* fn_name{};
  if (fn_type == FunctionType::FUNCTION)
    fn_name = Object::StringObject::create(prev_.as_string());

  compiler->set_compiler(
      curr_compiler_,
      Object::FunctionObject::create(fn_name),
      fn_type,
      scope_depth);
  curr_compiler_ = compiler;

  curr_compiler_->append_local({Lex::Token::make(""), curr_compiler_->scope_depth(), false});
}

Object::FunctionObject* GlobalParser::finish_compiler() {
  emit_return();

  Object::FunctionObject* fn = curr_compiler_->fn();
#if defined(_TADPOLE_DEBUG_VM)
  if (!had_error_)
    curr_chunk()->dis(fn->name_asstr());
#endif

  curr_compiler_ = curr_compiler_->enclosing();
  return fn;
}

void GlobalParser::enter_scope() {
  curr_compiler_->enter_scope();
}

void GlobalParser::leave_scope() {
  curr_compiler_->leave_scope([this](const LocalVar& var) {
        emit_byte(var.is_upvalue ? Core::Code::CLOSE_UPVALUE : Core::Code::POP);
      });
}

u8_t GlobalParser::identifier_constant(const Lex::Token& name) noexcept {
  return curr_chunk()->add_constant(Object::StringObject::create(name.as_string()));
}

u8_t GlobalParser::parse_variable(const str_t& msg) {
  consume(Lex::TokenKind::TK_IDENTIFIER, msg);

  curr_compiler_->declare_localvar(prev_, [this](const str_t& m) { error(m); });
  if (curr_compiler_->scope_depth() > 0)
    return 0;
  return identifier_constant(prev_);
}

}
<commit_msg>:construction: chore(parser-mark-initialized): implementation of marking initialized for parser<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// 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 ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 HOLDER 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.
#include <iostream>
#include <Common/Colorful.hh>
#include <Lex/Lexer.hh>
#include <Object/StringObject.hh>
#include <Core/TadpoleVM.hh>
#include <Compiler/Parser.hh>

namespace Tadpole::Compiler {

GlobalParser::GlobalParser(Core::TadpoleVM& vm, Lex::Lexer& lex) noexcept
  : vm_(vm), lex_(lex) {
}

void GlobalParser::iter_objects(Object::ObjectVisitor&& visitor) {
  // TODO:
}

Object::FunctionObject* GlobalParser::compile() {
  // TODO:
  return nullptr;
}

const ParseRule& GlobalParser::get_rule(Lex::TokenKind kind) const noexcept {
  static const ParseRule _rules[] = {
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(LPAREN, "(")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(RPAREN, ")")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(LBRACE, "{")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(RBRACE, "}")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(COMMA, ",")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(MINUS, "-")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(PLUS, "+")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(SEMI, ";")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(SLASH, "/")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(STAR, "*")
    {nullptr, nullptr, Precedence::NONE}, // PUNCTUATOR(EQ, "=")

    {nullptr, nullptr, Precedence::NONE}, // TOKEN(IDENTIFIER, "Identifier")
    {nullptr, nullptr, Precedence::NONE}, // TOKEN(NUMERIC, "Numeric")
    {nullptr, nullptr, Precedence::NONE}, // TOKEN(STRING, "String")

    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(FALSE, "false")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(FN, "fn")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(NIL, "nil")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(TRUE, "true")
    {nullptr, nullptr, Precedence::NONE}, // KEYWORD(VAR, "var")

    {nullptr, nullptr, Precedence::NONE}, // TOKEN(EOF, "Eof")
    {nullptr, nullptr, Precedence::NONE}, // TOKEN(ERR, "Error")
  };

  return _rules[Common::as_type<int>(kind)];
}

void GlobalParser::error_at(const Lex::Token& tok, const str_t& msg) noexcept {
  if (panic_mode_)
    return;
  panic_mode_ = true;

  std::cerr
    << Common::Colorful::fg::red
    << "SyntaxError:" << std::endl
    << "  [LINE: " << tok.lineno() << "] ERROR ";
  if (tok.kind() == Lex::TokenKind::TK_EOF)
    std::cerr << "at end ";
  else if (tok.kind() == Lex::TokenKind::TK_ERR)
    TADPOLE_UNUSED(0);
  else
    std::cerr << "at `" << tok.literal() << "` ";
  std::cerr << ": " << msg << Common::Colorful::reset << std::endl;
}

void GlobalParser::advance() {
  prev_ = curr_;

  for (;;) {
    curr_ = lex_.next_token();
    if (!check(Lex::TokenKind::TK_ERR))
      break;

    error_at_current(curr_.as_string());
  }
}

void GlobalParser::consume(Lex::TokenKind kind, const str_t& msg) {
  if (check(kind))
    advance();
  else
    error_at_current(msg);
}

bool GlobalParser::match(Lex::TokenKind kind) {
  if (check(kind)) {
    advance();
    return true;
  }
  return false;
}

void GlobalParser::init_compiler(FunctionCompiler* compiler, int scope_depth, FunctionType fn_type) {
  Object::StringObject* fn_name{};
  if (fn_type == FunctionType::FUNCTION)
    fn_name = Object::StringObject::create(prev_.as_string());

  compiler->set_compiler(
      curr_compiler_,
      Object::FunctionObject::create(fn_name),
      fn_type,
      scope_depth);
  curr_compiler_ = compiler;

  curr_compiler_->append_local({Lex::Token::make(""), curr_compiler_->scope_depth(), false});
}

Object::FunctionObject* GlobalParser::finish_compiler() {
  emit_return();

  Object::FunctionObject* fn = curr_compiler_->fn();
#if defined(_TADPOLE_DEBUG_VM)
  if (!had_error_)
    curr_chunk()->dis(fn->name_asstr());
#endif

  curr_compiler_ = curr_compiler_->enclosing();
  return fn;
}

void GlobalParser::enter_scope() {
  curr_compiler_->enter_scope();
}

void GlobalParser::leave_scope() {
  curr_compiler_->leave_scope([this](const LocalVar& var) {
        emit_byte(var.is_upvalue ? Core::Code::CLOSE_UPVALUE : Core::Code::POP);
      });
}

u8_t GlobalParser::identifier_constant(const Lex::Token& name) noexcept {
  return curr_chunk()->add_constant(Object::StringObject::create(name.as_string()));
}

u8_t GlobalParser::parse_variable(const str_t& msg) {
  consume(Lex::TokenKind::TK_IDENTIFIER, msg);

  curr_compiler_->declare_localvar(prev_, [this](const str_t& m) { error(m); });
  if (curr_compiler_->scope_depth() > 0)
    return 0;
  return identifier_constant(prev_);
}

void GlobalParser::mark_initialized() {
  if (curr_compiler_->scope_depth() == 0)
    return;
  curr_compiler_->peek_local().depth = curr_compiler_->scope_depth();
}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <stdexcept>

#include "matrix.h"

#define ERROR_SUCCESS                               0
#define ERROR_FAILURE                              -1

void _assert(bool a)
{
    if (!a) throw std::runtime_error("Assertion failed.");
}

void test_matrix1()
{
    CooMatrix m(5);
    m.add(1, 3, 3.5);
    m.add(2, 3, 4.5);
    m.add(3, 4, 1.5);
    m.add(4, 2, 1.5);
    m.add(2, 3, 1);
    m.print();

    printf("----\n");
    // convert from COO
    CSRMatrix n1(&m);
    n1.print();
    CSCMatrix n2(&m);
    n2.print();
    // convert CSR <-> CSC
    CSRMatrix n3(&n2);
    n3.print();
    CSCMatrix n4(&n1);
    n4.print();
}

void test_matrix2()
{
    CooMatrix m(5);
    m.add(1, 3, 3.5);
    m.add(2, 3, 4.5);
    m.add(3, 4, 1.5);
    m.add(4, 2, 1.5);
    m.add(2, 3, 1);
    m.print();

    Matrix *_m = &m;

    printf("----\n");
    // convert from COO
    CSRMatrix n1(_m);
    n1.print();
    CSCMatrix n2(_m);
    n2.print();

    _m = &n2;
    // convert CSR <-> CSC
    CSRMatrix n3(_m);
    n3.print();
    _m = &n1;
    CSCMatrix n4(_m);
    n4.print();
}

void test_matrix3()
{
    CooMatrix m(5, true);
    m.add(1, 3, 3.5);
    m.add(2, 3, 4.5);
    m.add(3, 4, 1.5);
    m.add(4, 2, 1.5);
    m.add(2, 3, 1);
    m.print();

    printf("----\n");
    // convert from COO
    CSRMatrix n1(&m);
    n1.print();
    CSCMatrix n2(&m);
    n2.print();
    // convert CSR <-> CSC
    CSRMatrix n3(&n2);
    n3.print();
    CSCMatrix n4(&n1);
    n4.print();
}

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

        test_matrix2();

        test_matrix3();

        return ERROR_SUCCESS;
    } catch(std::exception const &ex) {
        std::cout << "Exception raised: " << ex.what() << "\n";
        return ERROR_FAILURE;
    } catch(...) {
        std::cout << "Exception raised." << "\n";
        return ERROR_FAILURE;
    }
}
<commit_msg>call the right method<commit_after>#include <iostream>
#include <stdexcept>

#include "matrix.h"

#define ERROR_SUCCESS                               0
#define ERROR_FAILURE                              -1

void _assert(bool a)
{
    if (!a) throw std::runtime_error("Assertion failed.");
}

void test_matrix1()
{
    CooMatrix m(5);
    m.add(1, 3, 3.5);
    m.add(2, 3, 4.5);
    m.add(3, 4, 1.5);
    m.add(4, 2, 1.5);
    m.add(2, 3, 1);
    m.print();

    printf("----\n");
    // convert from COO
    CSRMatrix n1(&m);
    n1.print();
    CSCMatrix n2(&m);
    n2.print();
    // convert CSR <-> CSC
    CSRMatrix n3(&n2);
    n3.print();
    CSCMatrix n4(&n1);
    n4.print();
}

void test_matrix2()
{
    CooMatrix m(5);
    m.add(1, 3, 3.5);
    m.add(2, 3, 4.5);
    m.add(3, 4, 1.5);
    m.add(4, 2, 1.5);
    m.add(2, 3, 1);
    m.print();

    Matrix *_m = &m;

    printf("----\n");
    // convert from COO
    CSRMatrix n1(_m);
    n1.print();
    CSCMatrix n2(_m);
    n2.print();

    _m = &n2;
    // convert CSR <-> CSC
    CSRMatrix n3(_m);
    n3.print();
    _m = &n1;
    CSCMatrix n4(_m);
    n4.print();
}

void test_matrix3()
{
    CooMatrix m(5, true);
    m.add(1, 3, cplx(3.5));
    m.add(2, 3, cplx(4.5));
    m.add(3, 4, cplx(1.5));
    m.add(4, 2, cplx(1.5));
    m.add(2, 3, cplx(1));
    m.print();

    printf("----\n");
    // convert from COO
    CSRMatrix n1(&m);
    n1.print();
    CSCMatrix n2(&m);
    n2.print();
    // convert CSR <-> CSC
    CSRMatrix n3(&n2);
    n3.print();
    CSCMatrix n4(&n1);
    n4.print();
}

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

        test_matrix2();

        test_matrix3();

        return ERROR_SUCCESS;
    } catch(std::exception const &ex) {
        std::cout << "Exception raised: " << ex.what() << "\n";
        return ERROR_FAILURE;
    } catch(...) {
        std::cout << "Exception raised." << "\n";
        return ERROR_FAILURE;
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/index.hpp"

#define SUITE index
#include "test.hpp"

#include "vast/concept/parseable/to.hpp"
#include "vast/concept/parseable/vast/expression.hpp"
#include "vast/concept/printable/std/chrono.hpp"
#include "vast/concept/printable/to_string.hpp"
#include "vast/detail/spawn_generator_source.hpp"
#include "vast/event.hpp"
#include "vast/ids.hpp"
#include "vast/query_options.hpp"

#include "fixtures/actor_system_and_events.hpp"

using caf::after;
using std::chrono_literals::operator""s;

using namespace vast;
using namespace std::chrono;

namespace {

static constexpr size_t partition_size = 100;

static constexpr size_t in_mem_partitions = 8;

static constexpr size_t taste_count = 4;

static constexpr size_t num_collectors = 1;

const timestamp epoch;

using interval = system::partition_index::interval;

auto int_generator(int mod = std::numeric_limits<int>::max()) {
  int i = 0;
  return [i, mod]() mutable {
    auto result = event::make(i % mod, integer_type{}, i);
    result.timestamp(epoch + std::chrono::seconds(i));
    ++i;
    return result;
  };
}

struct fixture : fixtures::deterministic_actor_system_and_events {
  fixture() {
    directory /= "index";
    index = self->spawn(system::index, directory / "index", partition_size,
                        in_mem_partitions, taste_count, num_collectors);
  }

  ~fixture() {
    anon_send_exit(index, caf::exit_reason::user_shutdown);
  }

  // Returns the state of the `index`.
  system::index_state& state() {
    return deref<caf::stateful_actor<system::index_state>>(index).state;
  }

  auto partition_intervals() {
    std::vector<interval> result;
    for (auto& kvp : state().part_index.partitions())
      result.emplace_back(kvp.second.range);
    std::sort(result.begin(), result.end(),
              [](auto& x, auto& y) { return x.from < y.from; });
    return result;
  }

  // Handle to the INDEX actor.
  caf::actor index;
};

} // namespace <anonymous>

FIXTURE_SCOPE(index_tests, fixture)

TEST(ingestion) {
  MESSAGE("ingest 1000 integers");
  auto src = detail::spawn_generator_source(sys, index, 1000, int_generator());
  run_exhaustively();
  MESSAGE("verify partition index");
  REQUIRE_EQUAL(state().part_index.size(), 10u);
  auto intervals = partition_intervals();
  CHECK_EQUAL(intervals[0], interval(epoch, epoch + 99s));
  CHECK_EQUAL(intervals[1], interval(epoch + 100s, epoch + 199s));
  CHECK_EQUAL(intervals[2], interval(epoch + 200s, epoch + 299s));
  CHECK_EQUAL(intervals[3], interval(epoch + 300s, epoch + 399s));
  CHECK_EQUAL(intervals[4], interval(epoch + 400s, epoch + 499s));
  CHECK_EQUAL(intervals[5], interval(epoch + 500s, epoch + 599s));
  CHECK_EQUAL(intervals[6], interval(epoch + 600s, epoch + 699s));
  CHECK_EQUAL(intervals[7], interval(epoch + 700s, epoch + 799s));
  CHECK_EQUAL(intervals[8], interval(epoch + 800s, epoch + 899s));
  CHECK_EQUAL(intervals[9], interval(epoch + 900s, epoch + 999s));
}

TEST(one-shot integer query result) {
  MESSAGE("fill first " << taste_count << " partitions");
  auto src = detail::spawn_generator_source(sys, index,
                                            partition_size * taste_count,
                                            int_generator(2));
  run_exhaustively();
  MESSAGE("query half of the values");
  self->send(index, unbox(to<expression>(":int == 1")));
  run_exhaustively();
  self->receive(
    [&](uuid& query_id, size_t hits, size_t scheduled) {
      CHECK_EQUAL(query_id, uuid::nil());
      CHECK_EQUAL(hits, taste_count);
      CHECK_EQUAL(scheduled, taste_count);
    },
    after(0s) >> [&] { FAIL("INDEX did not respond to query"); });
  ids expected_result;
  for (size_t i = 0; i < (partition_size * taste_count) / 2; ++i) {
    expected_result.append_bit(false);
    expected_result.append_bit(true);
  }
  ids result;
  for (size_t i = 0; i < taste_count; ++i)
    self->receive(
      [&](ids& sub_result) {
        CHECK_EQUAL(rank<1>(sub_result), partition_size / 2);
        result |= sub_result;
      },
      after(0s) >> [&] { FAIL("missing sub result " << i); });
  CHECK_EQUAL(result, expected_result);
}

TEST(iterable integer query result) {
  MESSAGE("fill first " << (taste_count * 3) << " partitions");
  auto src = detail::spawn_generator_source(sys, index,
                                            partition_size * taste_count * 3,
                                            int_generator(2));
  run_exhaustively();
  MESSAGE("query half of the values");
  self->send(index, unbox(to<expression>(":int == 1")));
  run_exhaustively();
  uuid qid;
  self->receive(
    [&](uuid& query_id, size_t hits, size_t scheduled) {
      qid = query_id;
      CHECK_NOT_EQUAL(query_id, uuid::nil());
      CHECK_EQUAL(hits, taste_count * 3);
      CHECK_EQUAL(scheduled, taste_count);
    },
    after(0s) >> [&] { FAIL("INDEX did not respond to query"); });
  ids expected_result;
  for (size_t i = 0; i < (partition_size * taste_count * 3) / 2; ++i) {
    expected_result.append_bit(false);
    expected_result.append_bit(true);
  }
  MESSAGE("collect immediate results");
  ids result;
  for (size_t i = 0; i < taste_count; ++i)
    self->receive(
      [&](ids& sub_result) {
        CHECK_EQUAL(rank<1>(sub_result), partition_size / 2);
        result |= sub_result;
      },
      after(0s) >> [&] { FAIL("missing sub result " << i); });
  MESSAGE("collect remaining results");
  for (size_t j = 2; j > 0; --j) {
    CHECK_EQUAL(state().pending[qid].partitions.size(), taste_count * j);
    self->send(index, qid, taste_count);
    run_exhaustively();
    for (size_t i = 0; i < taste_count; ++i)
      self->receive(
        [&](ids& sub_result) {
          CHECK_EQUAL(rank<1>(sub_result), partition_size / 2);
          result |= sub_result;
        },
        after(0s) >> [&] { FAIL("missing sub result " << i); });
  }
  CHECK_EQUAL(result, expected_result);
}

FIXTURE_SCOPE_END()
<commit_msg>Refactor INDEX unit test<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include "vast/system/index.hpp"

#define SUITE index
#include "test.hpp"

#include "vast/concept/parseable/to.hpp"
#include "vast/concept/parseable/vast/expression.hpp"
#include "vast/concept/printable/std/chrono.hpp"
#include "vast/concept/printable/to_string.hpp"
#include "vast/detail/spawn_generator_source.hpp"
#include "vast/event.hpp"
#include "vast/ids.hpp"
#include "vast/query_options.hpp"

#include "fixtures/actor_system_and_events.hpp"

using caf::after;
using std::chrono_literals::operator""s;

using namespace vast;
using namespace std::chrono;

namespace {

static constexpr size_t partition_size = 100;

static constexpr size_t in_mem_partitions = 8;

static constexpr size_t taste_count = 4;

static constexpr size_t num_collectors = 1;

const timestamp epoch;

using interval = system::partition_index::interval;

auto int_generator(int mod = std::numeric_limits<int>::max()) {
  int i = 0;
  return [i, mod]() mutable {
    auto result = event::make(i % mod, integer_type{}, i);
    result.timestamp(epoch + std::chrono::seconds(i));
    ++i;
    return result;
  };
}

struct fixture : fixtures::deterministic_actor_system_and_events {
  fixture() {
    directory /= "index";
    index = self->spawn(system::index, directory / "index", partition_size,
                        in_mem_partitions, taste_count, num_collectors);
  }

  ~fixture() {
    anon_send_exit(index, caf::exit_reason::user_shutdown);
  }

  // Returns the state of the `index`.
  system::index_state& state() {
    return deref<caf::stateful_actor<system::index_state>>(index).state;
  }

  auto partition_intervals() {
    std::vector<interval> result;
    for (auto& kvp : state().part_index.partitions())
      result.emplace_back(kvp.second.range);
    std::sort(result.begin(), result.end(),
              [](auto& x, auto& y) { return x.from < y.from; });
    return result;
  }

  auto receive_query_id() {
    std::tuple<uuid, size_t, size_t> result;
    self->receive(
      [&](uuid& query_id, size_t hits, size_t scheduled) {
        result = std::tie(query_id, hits, scheduled);
      },
      after(0s) >> [&] { FAIL("INDEX did not respond to query"); });
    return result;
  }

  ids receive_result(const uuid& query_id, size_t hits, size_t scheduled) {
    ids result;
    size_t collected = 0;
    auto fetch = [&](size_t chunk) {
      for (size_t i = 0; i < chunk; ++i)
        self->receive(
          [&](ids& sub_result) {
            ++collected;
            result |= sub_result;
          },
          after(0s) >> [&] {
            FAIL("missing sub result #" << (i + 1) << " in partition #"
                                        << (collected + 1));
          }
        );
    };
    fetch(scheduled);
    while (collected < hits) {
      auto chunk = std::min(hits - collected, taste_count);
      self->send(index, query_id, chunk);
      run_exhaustively();
      fetch(chunk);
    }
    return result;
  }

  // Handle to the INDEX actor.
  caf::actor index;
};

} // namespace <anonymous>

FIXTURE_SCOPE(index_tests, fixture)

TEST(ingestion) {
  MESSAGE("ingest 1000 integers");
  auto src = detail::spawn_generator_source(sys, index, 1000, int_generator());
  run_exhaustively();
  MESSAGE("verify partition index");
  REQUIRE_EQUAL(state().part_index.size(), 10u);
  auto intervals = partition_intervals();
  CHECK_EQUAL(intervals[0], interval(epoch, epoch + 99s));
  CHECK_EQUAL(intervals[1], interval(epoch + 100s, epoch + 199s));
  CHECK_EQUAL(intervals[2], interval(epoch + 200s, epoch + 299s));
  CHECK_EQUAL(intervals[3], interval(epoch + 300s, epoch + 399s));
  CHECK_EQUAL(intervals[4], interval(epoch + 400s, epoch + 499s));
  CHECK_EQUAL(intervals[5], interval(epoch + 500s, epoch + 599s));
  CHECK_EQUAL(intervals[6], interval(epoch + 600s, epoch + 699s));
  CHECK_EQUAL(intervals[7], interval(epoch + 700s, epoch + 799s));
  CHECK_EQUAL(intervals[8], interval(epoch + 800s, epoch + 899s));
  CHECK_EQUAL(intervals[9], interval(epoch + 900s, epoch + 999s));
}

TEST(one-shot integer query result) {
  MESSAGE("fill first " << taste_count << " partitions");
  auto src = detail::spawn_generator_source(sys, index,
                                            partition_size * taste_count,
                                            int_generator(2));
  run_exhaustively();
  MESSAGE("query half of the values");
  self->send(index, unbox(to<expression>(":int == 1")));
  run_exhaustively();
  auto [query_id, hits, scheduled] = receive_query_id();
  CHECK_EQUAL(query_id, uuid::nil());
  CHECK_EQUAL(hits, taste_count);
  CHECK_EQUAL(scheduled, taste_count);
  ids expected_result;
  for (size_t i = 0; i < (partition_size * taste_count) / 2; ++i) {
    expected_result.append_bit(false);
    expected_result.append_bit(true);
  }
  auto result = receive_result(query_id, hits, scheduled);
  CHECK_EQUAL(result, expected_result);
}

TEST(iterable integer query result) {
  MESSAGE("fill first " << (taste_count * 3) << " partitions");
  auto src = detail::spawn_generator_source(sys, index,
                                            partition_size * taste_count * 3,
                                            int_generator(2));
  run_exhaustively();
  MESSAGE("query half of the values");
  self->send(index, unbox(to<expression>(":int == 1")));
  run_exhaustively();
  auto [query_id, hits, scheduled] = receive_query_id();
  CHECK_NOT_EQUAL(query_id, uuid::nil());
  CHECK_EQUAL(hits, taste_count * 3);
  CHECK_EQUAL(scheduled, taste_count);
  ids expected_result;
  for (size_t i = 0; i < (partition_size * taste_count * 3) / 2; ++i) {
    expected_result.append_bit(false);
    expected_result.append_bit(true);
  }
  MESSAGE("collect results");
  auto result = receive_result(query_id, hits, scheduled);
  CHECK_EQUAL(result, expected_result);
}

FIXTURE_SCOPE_END()
<|endoftext|>


<commit_before>#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <xorg/gtest/xorg-gtest.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XInput.h>

#include "input-driver-test.h"
#include "device-interface.h"
#include "helpers.h"

/**
 * Evdev driver test for keyboard devices. Takes a string as parameter,
 * which is later used for the XkbLayout option.
 */
class PointerGrabTest : public InputDriverTest,
                        public DeviceInterface {
public:
    /**
     * Initializes a standard mouse device.
     */
    virtual void SetUp() {
        SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
        InputDriverTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single evdev CoreKeyboard device based on
     * the evemu device. The input from GetParam() is used as XkbLayout.
     */
    virtual void SetUpConfigAndLog(const std::string &param) {
        server.SetOption("-logfile", "/tmp/Xorg-pointer-grab-test.log");
        server.SetOption("-config", "/tmp/pointer-grab-test.conf");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("evdev", "--device--",
                               "Option \"CorePointer\" \"on\"\n"
                               "Option \"Device\" \"" + dev->GetDeviceNode() + "\"");
        /* add default keyboard device to avoid server adding our device again */
        config.AddInputSection("kbd", "kbd-device",
                               "Option \"CoreKeyboardj\" \"on\"\n");
        config.WriteConfig("/tmp/pointer-grab-test.conf");
    }

    virtual int RegisterXI2(int major, int minor)
    {
        return InputDriverTest::RegisterXI2(2, 1);
    }

};

TEST_F(PointerGrabTest, ImplicitGrabRawEvents)
{
    SCOPED_TRACE("\n"
                 "TESTCASE: this test registers for XI_ButtonPress on a \n"
                 "window and expects raw events to arrive while the \n"
                 "implicit grab is active.");

    ASSERT_GE(RegisterXI2(2, 1), 1) << "This test requires XI 2.1+";

    ::Display *dpy = Display();

    Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
                                     DisplayWidth(dpy, DefaultScreen(dpy)),
                                     DisplayHeight(dpy, DefaultScreen(dpy)),
                                     0, 0,
                                     WhitePixel(dpy, DefaultScreen(dpy)));
    XSelectInput(dpy, win, ExposureMask);
    XMapWindow(dpy, win);
    XFlush(dpy);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           Expose,
                                                           -1, -1, 1000));

    XIEventMask mask;

    mask.deviceid = XIAllMasterDevices;
    mask.mask_len = XIMaskLen(XI_RawMotion);
    mask.mask = new unsigned char[mask.mask_len];
    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_ButtonPress);
    XISelectEvents(dpy, win, &mask, 1);

    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_RawButtonPress);
    XISetMask(mask.mask, XI_RawMotion);
    XISelectEvents(dpy, DefaultRootWindow(dpy), &mask, 1);

    delete mask.mask;

    XSync(dpy, False);

    /* Move pointer, make sure we receive raw events */
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XEvent ev;
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));

    /* Now press button, make sure sure we still get raw events */
    dev->PlayOne(EV_KEY, BTN_LEFT, 1, true);

    /* raw button events come before normal button events */
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawButtonPress,
                                                           1000));
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_ButtonPress,
                                                           1000));
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));
}

TEST_F(PointerGrabTest, GrabDisabledDevices)
{
    SCOPED_TRACE("Grabbing a disabled device must not segfault the server.\n"
                 "https://bugs.freedesktop.org/show_bug.cgi?id=54934");

    Atom prop = XInternAtom(Display(), "Device Enabled", True);
    ASSERT_NE(prop, (Atom)None);

    int deviceid;
    ASSERT_EQ(FindInputDeviceByName(Display(), "--device--", &deviceid), 1);

    unsigned char data = 0;
    XIChangeProperty(Display(), deviceid, prop, XA_INTEGER, 8,
            PropModeReplace, &data, 1);
    XFlush(Display());

    XDevice *xdev = XOpenDevice(Display(), deviceid);
    ASSERT_TRUE(xdev != NULL);

    XGrabDevice(Display(), xdev, DefaultRootWindow(Display()), True,
            0, NULL, GrabModeAsync, GrabModeAsync, CurrentTime);
    XSync(Display(), False);
    ASSERT_EQ(server.GetState(), xorg::testing::Process::RUNNING);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>server/grab: fix typo in Option CoreKeyboard<commit_after>#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <xorg/gtest/xorg-gtest.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XInput.h>

#include "input-driver-test.h"
#include "device-interface.h"
#include "helpers.h"

/**
 * Evdev driver test for keyboard devices. Takes a string as parameter,
 * which is later used for the XkbLayout option.
 */
class PointerGrabTest : public InputDriverTest,
                        public DeviceInterface {
public:
    /**
     * Initializes a standard mouse device.
     */
    virtual void SetUp() {
        SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
        InputDriverTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single evdev CoreKeyboard device based on
     * the evemu device. The input from GetParam() is used as XkbLayout.
     */
    virtual void SetUpConfigAndLog(const std::string &param) {
        server.SetOption("-logfile", "/tmp/Xorg-pointer-grab-test.log");
        server.SetOption("-config", "/tmp/pointer-grab-test.conf");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("evdev", "--device--",
                               "Option \"CorePointer\" \"on\"\n"
                               "Option \"Device\" \"" + dev->GetDeviceNode() + "\"");
        /* add default keyboard device to avoid server adding our device again */
        config.AddInputSection("kbd", "kbd-device",
                               "Option \"CoreKeyboard\" \"on\"\n");
        config.WriteConfig("/tmp/pointer-grab-test.conf");
    }

    virtual int RegisterXI2(int major, int minor)
    {
        return InputDriverTest::RegisterXI2(2, 1);
    }

};

TEST_F(PointerGrabTest, ImplicitGrabRawEvents)
{
    SCOPED_TRACE("\n"
                 "TESTCASE: this test registers for XI_ButtonPress on a \n"
                 "window and expects raw events to arrive while the \n"
                 "implicit grab is active.");

    ASSERT_GE(RegisterXI2(2, 1), 1) << "This test requires XI 2.1+";

    ::Display *dpy = Display();

    Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
                                     DisplayWidth(dpy, DefaultScreen(dpy)),
                                     DisplayHeight(dpy, DefaultScreen(dpy)),
                                     0, 0,
                                     WhitePixel(dpy, DefaultScreen(dpy)));
    XSelectInput(dpy, win, ExposureMask);
    XMapWindow(dpy, win);
    XFlush(dpy);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           Expose,
                                                           -1, -1, 1000));

    XIEventMask mask;

    mask.deviceid = XIAllMasterDevices;
    mask.mask_len = XIMaskLen(XI_RawMotion);
    mask.mask = new unsigned char[mask.mask_len];
    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_ButtonPress);
    XISelectEvents(dpy, win, &mask, 1);

    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_RawButtonPress);
    XISetMask(mask.mask, XI_RawMotion);
    XISelectEvents(dpy, DefaultRootWindow(dpy), &mask, 1);

    delete mask.mask;

    XSync(dpy, False);

    /* Move pointer, make sure we receive raw events */
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XEvent ev;
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));

    /* Now press button, make sure sure we still get raw events */
    dev->PlayOne(EV_KEY, BTN_LEFT, 1, true);

    /* raw button events come before normal button events */
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawButtonPress,
                                                           1000));
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_ButtonPress,
                                                           1000));
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));
}

TEST_F(PointerGrabTest, GrabDisabledDevices)
{
    SCOPED_TRACE("Grabbing a disabled device must not segfault the server.\n"
                 "https://bugs.freedesktop.org/show_bug.cgi?id=54934");

    Atom prop = XInternAtom(Display(), "Device Enabled", True);
    ASSERT_NE(prop, (Atom)None);

    int deviceid;
    ASSERT_EQ(FindInputDeviceByName(Display(), "--device--", &deviceid), 1);

    unsigned char data = 0;
    XIChangeProperty(Display(), deviceid, prop, XA_INTEGER, 8,
            PropModeReplace, &data, 1);
    XFlush(Display());

    XDevice *xdev = XOpenDevice(Display(), deviceid);
    ASSERT_TRUE(xdev != NULL);

    XGrabDevice(Display(), xdev, DefaultRootWindow(Display()), True,
            0, NULL, GrabModeAsync, GrabModeAsync, CurrentTime);
    XSync(Display(), False);
    ASSERT_EQ(server.GetState(), xorg::testing::Process::RUNNING);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <xorg/gtest/xorg-gtest.h>

#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>

#include "input-driver-test.h"
#include "device-interface.h"
#include "helpers.h"

/**
 * Evdev driver test for keyboard devices. Takes a string as parameter,
 * which is later used for the XkbLayout option.
 */
class PointerGrabTest : public InputDriverTest,
                        public DeviceInterface {
public:
    /**
     * Initializes a standard mouse device.
     */
    virtual void SetUp() {
        SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
        InputDriverTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single evdev CoreKeyboard device based on
     * the evemu device. The input from GetParam() is used as XkbLayout.
     */
    virtual void SetUpConfigAndLog(const std::string &param) {
        server.SetOption("-logfile", "/tmp/Xorg-pointer-grab-test.log");
        server.SetOption("-config", "/tmp/pointer-grab-test.conf");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("evdev", "--device--",
                               "Option \"CorePointer\" \"on\"\n"
                               "Option \"Device\" \"" + dev->GetDeviceNode() + "\"");
        /* add default keyboard device to avoid server adding our device again */
        config.AddInputSection("kbd", "kbd-device",
                               "Option \"CoreKeyboardj\" \"on\"\n");
        config.WriteConfig("/tmp/pointer-grab-test.conf");
    }

    virtual int RegisterXI2(int major, int minor)
    {
        return InputDriverTest::RegisterXI2(2, 1);
    }

};

TEST_F(PointerGrabTest, ImplicitGrabRawEvents)
{
    SCOPED_TRACE("\n"
                 "TESTCASE: this test registers for XI_ButtonPress on a \n"
                 "window and expects raw events to arrive while the \n"
                 "implicit grab is active.");

    ASSERT_GE(RegisterXI2(2, 1), 1) << "This test requires XI 2.1+";

    ::Display *dpy = Display();

    Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
                                     DisplayWidth(dpy, DefaultScreen(dpy)),
                                     DisplayHeight(dpy, DefaultScreen(dpy)),
                                     0, 0,
                                     WhitePixel(dpy, DefaultScreen(dpy)));
    XSelectInput(dpy, win, ExposureMask);
    XMapWindow(dpy, win);
    XFlush(dpy);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           Expose,
                                                           -1, -1, 1000));

    XIEventMask mask;

    mask.deviceid = XIAllMasterDevices;
    mask.mask_len = XIMaskLen(XI_RawMotion);
    mask.mask = new unsigned char[mask.mask_len];
    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_ButtonPress);
    XISelectEvents(dpy, win, &mask, 1);

    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_RawButtonPress);
    XISetMask(mask.mask, XI_RawMotion);
    XISelectEvents(dpy, DefaultRootWindow(dpy), &mask, 1);

    delete mask.mask;

    XSync(dpy, False);

    /* Move pointer, make sure we receive raw events */
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XEvent ev;
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));

    /* Now press button, make sure sure we still get raw events */
    dev->PlayOne(EV_KEY, BTN_LEFT, 1, true);

    /* raw button events come before normal button events */
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawButtonPress,
                                                           1000));
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_ButtonPress,
                                                           1000));
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>server/grab: add test case for crash on disabled device grab (#54934)<commit_after>#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <xorg/gtest/xorg-gtest.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XInput.h>

#include "input-driver-test.h"
#include "device-interface.h"
#include "helpers.h"

/**
 * Evdev driver test for keyboard devices. Takes a string as parameter,
 * which is later used for the XkbLayout option.
 */
class PointerGrabTest : public InputDriverTest,
                        public DeviceInterface {
public:
    /**
     * Initializes a standard mouse device.
     */
    virtual void SetUp() {
        SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
        InputDriverTest::SetUp();
    }

    /**
     * Sets up an xorg.conf for a single evdev CoreKeyboard device based on
     * the evemu device. The input from GetParam() is used as XkbLayout.
     */
    virtual void SetUpConfigAndLog(const std::string &param) {
        server.SetOption("-logfile", "/tmp/Xorg-pointer-grab-test.log");
        server.SetOption("-config", "/tmp/pointer-grab-test.conf");

        config.AddDefaultScreenWithDriver();
        config.AddInputSection("evdev", "--device--",
                               "Option \"CorePointer\" \"on\"\n"
                               "Option \"Device\" \"" + dev->GetDeviceNode() + "\"");
        /* add default keyboard device to avoid server adding our device again */
        config.AddInputSection("kbd", "kbd-device",
                               "Option \"CoreKeyboardj\" \"on\"\n");
        config.WriteConfig("/tmp/pointer-grab-test.conf");
    }

    virtual int RegisterXI2(int major, int minor)
    {
        return InputDriverTest::RegisterXI2(2, 1);
    }

};

TEST_F(PointerGrabTest, ImplicitGrabRawEvents)
{
    SCOPED_TRACE("\n"
                 "TESTCASE: this test registers for XI_ButtonPress on a \n"
                 "window and expects raw events to arrive while the \n"
                 "implicit grab is active.");

    ASSERT_GE(RegisterXI2(2, 1), 1) << "This test requires XI 2.1+";

    ::Display *dpy = Display();

    Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
                                     DisplayWidth(dpy, DefaultScreen(dpy)),
                                     DisplayHeight(dpy, DefaultScreen(dpy)),
                                     0, 0,
                                     WhitePixel(dpy, DefaultScreen(dpy)));
    XSelectInput(dpy, win, ExposureMask);
    XMapWindow(dpy, win);
    XFlush(dpy);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           Expose,
                                                           -1, -1, 1000));

    XIEventMask mask;

    mask.deviceid = XIAllMasterDevices;
    mask.mask_len = XIMaskLen(XI_RawMotion);
    mask.mask = new unsigned char[mask.mask_len];
    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_ButtonPress);
    XISelectEvents(dpy, win, &mask, 1);

    memset(mask.mask, 0, sizeof(mask.mask));
    XISetMask(mask.mask, XI_RawButtonPress);
    XISetMask(mask.mask, XI_RawMotion);
    XISelectEvents(dpy, DefaultRootWindow(dpy), &mask, 1);

    delete mask.mask;

    XSync(dpy, False);

    /* Move pointer, make sure we receive raw events */
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XEvent ev;
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));

    /* Now press button, make sure sure we still get raw events */
    dev->PlayOne(EV_KEY, BTN_LEFT, 1, true);

    /* raw button events come before normal button events */
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawButtonPress,
                                                           1000));
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_ButtonPress,
                                                           1000));
    dev->PlayOne(EV_REL, REL_X, -1, true);
    ASSERT_TRUE(xorg::testing::XServer::WaitForEventOfType(Display(),
                                                           GenericEvent,
                                                           xi2_opcode,
                                                           XI_RawMotion,
                                                           1000));
    XNextEvent(dpy, &ev);
    ASSERT_FALSE(XPending(dpy));
}

TEST_F(PointerGrabTest, GrabDisabledDevices)
{
    SCOPED_TRACE("Grabbing a disabled device must not segfault the server.\n"
                 "https://bugs.freedesktop.org/show_bug.cgi?id=54934");

    pid_t pid = fork();
    if (pid == 0) {
        Atom prop = XInternAtom(Display(), "Device Enabled", True);
        ASSERT_NE(prop, (Atom)None);

        int deviceid;
        ASSERT_EQ(FindInputDeviceByName(Display(), "--device--", &deviceid), 1);

        unsigned char data = 0;
        XIChangeProperty(Display(), deviceid, prop, XA_INTEGER, 8,
                PropModeReplace, &data, 1);
        XFlush(Display());

        XDevice *xdev = XOpenDevice(Display(), deviceid);
        ASSERT_TRUE(xdev != NULL);

        XGrabDevice(Display(), xdev, DefaultRootWindow(Display()), True,
                0, NULL, GrabModeAsync, GrabModeAsync, CurrentTime);
        XSync(Display(), False);
        ASSERT_EQ(server.GetState(), xorg::testing::Process::RUNNING);
        return;
    }

    int status;
    waitpid(pid, &status, 0);
    ASSERT_TRUE(WIFEXITED(status));
    ASSERT_EQ(WEXITSTATUS(status), 0);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>