<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "libmesh/diff_solver.h"
#include "libmesh/diff_system.h"
#include "libmesh/time_solver.h"
#include "libmesh/unsteady_solver.h"
#include "libmesh/dirichlet_boundaries.h"
#include "libmesh/dof_map.h"

namespace libMesh
{

DifferentiableSystem::DifferentiableSystem(EquationSystems & es,
                                           const std::string & name_in,
                                           const unsigned int number_in) :
  Parent      (es, name_in, number_in),
  time_solver (),
  deltat(1.),
  print_solution_norms(false),
  print_solutions(false),
  print_residual_norms(false),
  print_residuals(false),
  print_jacobian_norms(false),
  print_jacobians(false),
  print_element_solutions(false),
  print_element_residuals(false),
  print_element_jacobians(false),
  _diff_physics(this),
  diff_qoi(this)
{
}

DifferentiableSystem::~DifferentiableSystem ()
{
  // If we had an attached Physics object, delete it.
  if (this->_diff_physics != this)
    delete this->_diff_physics;

  // If we had an attached QoI object, delete it.
  if (this->diff_qoi != this)
    delete this->diff_qoi;
}

void DifferentiableSystem::clear ()
{
  // If we had an attached Physics object, delete it.
  if (this->_diff_physics != this)
    {
      delete this->_diff_physics;
      this->_diff_physics = this;
    }
  // If we had no attached Physics object, clear our own Physics data
  else
    this->clear_physics();

  // If we had an attached QoI object, delete it.
  if (this->diff_qoi != this)
    {
      delete this->diff_qoi;
      this->diff_qoi = this;
    }
  // If we had no attached QoI object, clear our own QoI data
  else
    this->clear_qoi();

  use_fixed_solution = false;
}

void DifferentiableSystem::reinit ()
{
  Parent::reinit();

  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);

  time_solver->reinit();
}

void DifferentiableSystem::init_data ()
{
  // If it isn't a separate initialized-upon-attachment object, do any
  // initialization our physics needs.
  if (this->_diff_physics == this)
    this->init_physics(*this);

  // Do any initialization our solvers need
  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);

  // Now check for second order variables and add their velocities to the System.
  if( !time_solver->is_steady() )
    {
      const UnsteadySolver & unsteady_solver =
        cast_ref<const UnsteadySolver &>(*(time_solver.get()));

      if( unsteady_solver.time_order() == 1 )
        this->add_second_order_dot_vars();
    }

  time_solver->init();

  // Next initialize ImplicitSystem data
  Parent::init_data();

  time_solver->init_data();
}

UniquePtr<DiffContext> DifferentiableSystem::build_context ()
{
  DiffContext * context = new DiffContext(*this);
  context->set_deltat_pointer( &this->deltat );
  return UniquePtr<DiffContext>(context);
}

void DifferentiableSystem::assemble ()
{
  this->assembly(true, true);
}

void DifferentiableSystem::solve ()
{
  // Get the time solver object associated with the system, and tell it that
  // we are not solving the adjoint problem
  this->get_time_solver().set_is_adjoint(false);

  libmesh_assert_equal_to (&(time_solver->system()), this);
  time_solver->solve();
}

std::pair<unsigned int, Real> DifferentiableSystem::adjoint_solve (const QoISet & qoi_indices)
{
  // Get the time solver object associated with the system, and tell it that
  // we are solving the adjoint problem
  this->get_time_solver().set_is_adjoint(true);

  return this->ImplicitSystem::adjoint_solve(qoi_indices);
}

LinearSolver<Number> * DifferentiableSystem::get_linear_solver() const
{
  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);
  return this->time_solver->linear_solver().get();
}

std::pair<unsigned int, Real> DifferentiableSystem::get_linear_solve_parameters() const
{
  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);
  return std::make_pair(this->time_solver->diff_solver()->max_linear_iterations,
                        this->time_solver->diff_solver()->relative_residual_tolerance);
}

void DifferentiableSystem::release_linear_solver(LinearSolver<Number> *) const
{
}

void DifferentiableSystem::add_second_order_dot_vars()
{
  const std::set<unsigned int> & second_order_vars = this->get_second_order_vars();
  if( !second_order_vars.empty() )
    {
      for( std::set<unsigned int>::const_iterator var_it = second_order_vars.begin();
           var_it != second_order_vars.end(); ++var_it )
        {
          const Variable & var = this->variable(*var_it);
          std::string new_var_name = std::string("dot_")+var.name();

          unsigned int v_var_idx;

          if( var.active_subdomains().empty() )
            v_var_idx = this->add_variable( new_var_name, var.type() );
          else
            v_var_idx = this->add_variable( new_var_name, var.type(), &var.active_subdomains() );

          _second_order_dot_vars.insert( std::pair<unsigned int,unsigned int>(*var_it,v_var_idx) );

          // The new velocities are time evolving variables of first order
          this->time_evolving( v_var_idx, 1 );

          // And if there are any boundary conditions set on the second order
          // variable, we also need to set it on its velocity variable.
          this->add_dot_var_dirichlet_bcs( *var_it, v_var_idx );
        }
    }
}

void DifferentiableSystem::add_dot_var_dirichlet_bcs( unsigned int var_idx,
                                                      unsigned int dot_var_idx )
{
  // We're assuming that there could be a lot more variables than
  // boundary conditions, so we search each of the boundary conditions
  // for this variable rather than looping over boundary conditions
  // in a separate loop and searching through all the variables.
  const DirichletBoundaries * all_dbcs =
    this->get_dof_map().get_dirichlet_boundaries();

  if( all_dbcs )
    {
      // We need to cache the DBCs to be added so that we add them
      // after looping over the existing DBCs. Otherwise, we're polluting
      // the thing we're looping over.
      std::vector<DirichletBoundary*> new_dbcs;

      DirichletBoundaries::const_iterator dbc_it = all_dbcs->begin();
      for( ; dbc_it != all_dbcs->end(); ++dbc_it )
        {
          libmesh_assert(*dbc_it);
          DirichletBoundary & dbc = *(*dbc_it);

          // Look for second order variable in the current
          // DirichletBoundary object
          std::vector<unsigned int>::const_iterator dbc_var_it =
            std::find( dbc.variables.begin(), dbc.variables.end(), var_idx );

          // If we found it, then we also need to add it's corresponding
          // "dot" variable to a DirichletBoundary
          std::vector<unsigned int> vars_to_add;
          if( dbc_var_it != dbc.variables.end() )
            vars_to_add.push_back(dot_var_idx);

          if( !vars_to_add.empty() )
            {
              DirichletBoundary * new_dbc;

              if( dbc.f )
                {
                  if( dbc.g )
                    new_dbc = new DirichletBoundary(dbc.b,
                                                    vars_to_add,
                                                    dbc.f.get(),
                                                    dbc.g.get());

                  else
                    new_dbc = new DirichletBoundary(dbc.b,
                                                    vars_to_add,
                                                    dbc.f.get());
                }
              else if( dbc.f_fem )
                {
                  if( dbc.g_fem )
                    new_dbc = new DirichletBoundary(dbc.b,
                                                    vars_to_add,
                                                    *this,
                                                    dbc.f_fem.get(),
                                                    dbc.g_fem.get());

                  else
                    new_dbc = new DirichletBoundary(dbc.b,
                                                    vars_to_add,
                                                    *this,
                                                    dbc.f_fem.get());
                }
              else
                libmesh_error_msg("Could not find valid boundary function!");

              new_dbcs.push_back(new_dbc);
            }
        }

      // Now add the new DBCs for the "dot" vars to the DofMap
      std::vector<DirichletBoundary*>::iterator new_dbc_it =
        new_dbcs.begin();

      for( ; new_dbc_it != new_dbcs.end(); ++new_dbc_it )
        {
          const DirichletBoundary & dbc = *(*new_dbc_it);
          this->get_dof_map().add_dirichlet_boundary(dbc);
          delete *new_dbc_it;
        }

    } // if(all_dbcs)
}

unsigned int DifferentiableSystem::get_second_order_dot_var( unsigned int var ) const
{
  // For SteadySolver or SecondOrderUnsteadySolvers, we just give back var
  unsigned int dot_var = var;

  if( !time_solver->is_steady() )
    {
      const UnsteadySolver & unsteady_solver =
        cast_ref<const UnsteadySolver &>(*(time_solver.get()));

      if( unsteady_solver.time_order() == 1 )
        dot_var = this->_second_order_dot_vars.find(var)->second;
    }

  return dot_var;
}

bool DifferentiableSystem::have_first_order_scalar_vars() const
{
  bool have_first_order_scalar_vars = false;

  if(this->have_first_order_vars())
    {
      for( std::set<unsigned int>::const_iterator var_it = this->get_first_order_vars().begin();
           var_it != this->get_first_order_vars().end();
           ++var_it )
        {
          if( this->variable(*var_it).type().family == FEFamily::SCALAR )
            have_first_order_scalar_vars = true;
        }
    }

  return have_first_order_scalar_vars;
}

bool DifferentiableSystem::have_second_order_scalar_vars() const
{
  bool have_second_order_scalar_vars = false;

  if(this->have_second_order_vars())
    {
      for( std::set<unsigned int>::const_iterator var_it = this->get_second_order_vars().begin();
           var_it != this->get_second_order_vars().end();
           ++var_it )
        {
          if( this->variable(*var_it).type().family == FEFamily::SCALAR )
            have_second_order_scalar_vars = true;
        }
    }

  return have_second_order_scalar_vars;
}

} // namespace libMesh
<commit_msg>Fix BC construction for velocity variables<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2017 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "libmesh/diff_solver.h"
#include "libmesh/diff_system.h"
#include "libmesh/time_solver.h"
#include "libmesh/unsteady_solver.h"
#include "libmesh/dirichlet_boundaries.h"
#include "libmesh/dof_map.h"
#include "libmesh/zero_function.h"

namespace libMesh
{

DifferentiableSystem::DifferentiableSystem(EquationSystems & es,
                                           const std::string & name_in,
                                           const unsigned int number_in) :
  Parent      (es, name_in, number_in),
  time_solver (),
  deltat(1.),
  print_solution_norms(false),
  print_solutions(false),
  print_residual_norms(false),
  print_residuals(false),
  print_jacobian_norms(false),
  print_jacobians(false),
  print_element_solutions(false),
  print_element_residuals(false),
  print_element_jacobians(false),
  _diff_physics(this),
  diff_qoi(this)
{
}

DifferentiableSystem::~DifferentiableSystem ()
{
  // If we had an attached Physics object, delete it.
  if (this->_diff_physics != this)
    delete this->_diff_physics;

  // If we had an attached QoI object, delete it.
  if (this->diff_qoi != this)
    delete this->diff_qoi;
}

void DifferentiableSystem::clear ()
{
  // If we had an attached Physics object, delete it.
  if (this->_diff_physics != this)
    {
      delete this->_diff_physics;
      this->_diff_physics = this;
    }
  // If we had no attached Physics object, clear our own Physics data
  else
    this->clear_physics();

  // If we had an attached QoI object, delete it.
  if (this->diff_qoi != this)
    {
      delete this->diff_qoi;
      this->diff_qoi = this;
    }
  // If we had no attached QoI object, clear our own QoI data
  else
    this->clear_qoi();

  use_fixed_solution = false;
}

void DifferentiableSystem::reinit ()
{
  Parent::reinit();

  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);

  time_solver->reinit();
}

void DifferentiableSystem::init_data ()
{
  // If it isn't a separate initialized-upon-attachment object, do any
  // initialization our physics needs.
  if (this->_diff_physics == this)
    this->init_physics(*this);

  // Do any initialization our solvers need
  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);

  // Now check for second order variables and add their velocities to the System.
  if( !time_solver->is_steady() )
    {
      const UnsteadySolver & unsteady_solver =
        cast_ref<const UnsteadySolver &>(*(time_solver.get()));

      if( unsteady_solver.time_order() == 1 )
        this->add_second_order_dot_vars();
    }

  time_solver->init();

  // Next initialize ImplicitSystem data
  Parent::init_data();

  time_solver->init_data();
}

UniquePtr<DiffContext> DifferentiableSystem::build_context ()
{
  DiffContext * context = new DiffContext(*this);
  context->set_deltat_pointer( &this->deltat );
  return UniquePtr<DiffContext>(context);
}

void DifferentiableSystem::assemble ()
{
  this->assembly(true, true);
}

void DifferentiableSystem::solve ()
{
  // Get the time solver object associated with the system, and tell it that
  // we are not solving the adjoint problem
  this->get_time_solver().set_is_adjoint(false);

  libmesh_assert_equal_to (&(time_solver->system()), this);
  time_solver->solve();
}

std::pair<unsigned int, Real> DifferentiableSystem::adjoint_solve (const QoISet & qoi_indices)
{
  // Get the time solver object associated with the system, and tell it that
  // we are solving the adjoint problem
  this->get_time_solver().set_is_adjoint(true);

  return this->ImplicitSystem::adjoint_solve(qoi_indices);
}

LinearSolver<Number> * DifferentiableSystem::get_linear_solver() const
{
  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);
  return this->time_solver->linear_solver().get();
}

std::pair<unsigned int, Real> DifferentiableSystem::get_linear_solve_parameters() const
{
  libmesh_assert(time_solver.get());
  libmesh_assert_equal_to (&(time_solver->system()), this);
  return std::make_pair(this->time_solver->diff_solver()->max_linear_iterations,
                        this->time_solver->diff_solver()->relative_residual_tolerance);
}

void DifferentiableSystem::release_linear_solver(LinearSolver<Number> *) const
{
}

void DifferentiableSystem::add_second_order_dot_vars()
{
  const std::set<unsigned int> & second_order_vars = this->get_second_order_vars();
  if( !second_order_vars.empty() )
    {
      for( std::set<unsigned int>::const_iterator var_it = second_order_vars.begin();
           var_it != second_order_vars.end(); ++var_it )
        {
          const Variable & var = this->variable(*var_it);
          std::string new_var_name = std::string("dot_")+var.name();

          unsigned int v_var_idx;

          if( var.active_subdomains().empty() )
            v_var_idx = this->add_variable( new_var_name, var.type() );
          else
            v_var_idx = this->add_variable( new_var_name, var.type(), &var.active_subdomains() );

          _second_order_dot_vars.insert( std::pair<unsigned int,unsigned int>(*var_it,v_var_idx) );

          // The new velocities are time evolving variables of first order
          this->time_evolving( v_var_idx, 1 );

          // And if there are any boundary conditions set on the second order
          // variable, we also need to set it on its velocity variable.
          this->add_dot_var_dirichlet_bcs( *var_it, v_var_idx );
        }
    }
}

void DifferentiableSystem::add_dot_var_dirichlet_bcs( unsigned int var_idx,
                                                      unsigned int dot_var_idx )
{
  // We're assuming that there could be a lot more variables than
  // boundary conditions, so we search each of the boundary conditions
  // for this variable rather than looping over boundary conditions
  // in a separate loop and searching through all the variables.
  const DirichletBoundaries * all_dbcs =
    this->get_dof_map().get_dirichlet_boundaries();

  if( all_dbcs )
    {
      // We need to cache the DBCs to be added so that we add them
      // after looping over the existing DBCs. Otherwise, we're polluting
      // the thing we're looping over.
      std::vector<DirichletBoundary*> new_dbcs;

      DirichletBoundaries::const_iterator dbc_it = all_dbcs->begin();
      for( ; dbc_it != all_dbcs->end(); ++dbc_it )
        {
          libmesh_assert(*dbc_it);
          DirichletBoundary & dbc = *(*dbc_it);

          // Look for second order variable in the current
          // DirichletBoundary object
          std::vector<unsigned int>::const_iterator dbc_var_it =
            std::find( dbc.variables.begin(), dbc.variables.end(), var_idx );

          // If we found it, then we also need to add it's corresponding
          // "dot" variable to a DirichletBoundary
          std::vector<unsigned int> vars_to_add;
          if( dbc_var_it != dbc.variables.end() )
            vars_to_add.push_back(dot_var_idx);

          if( !vars_to_add.empty() )
            {
              // We need to check if the boundary condition is time-dependent.
              // Currently, we cannot automatically differentiate w.r.t. time
              // so if the user supplies a time-dependent Dirichlet BC, then
              // we can't automatically support the Dirichlet BC for the
              // "velocity" boundary condition, so we error. Otherwise,
              // the "velocity boundary condition will just be zero.
              bool is_time_evolving_bc = false;
              if( dbc.f )
                is_time_evolving_bc = dbc.f->is_time_dependent();
              else if( dbc.f_fem )
                // We it's a FEMFunctionBase object, it will be implictly
                // time-dependent since it is assumed to depend on the solution.
                is_time_evolving_bc = true;
              else
                libmesh_error_msg("Could not find valid boundary function!");

              if( is_time_evolving_bc )
                libmesh_error_msg("Cannot currently support time-dependent Dirichlet BC for dot variables!");

              DirichletBoundary * new_dbc;

              if( dbc.f )
                {
                  ZeroFunction<Number> zf;

                  new_dbc = new DirichletBoundary(dbc.b, vars_to_add, zf);
                }
              else
                libmesh_error();

              new_dbcs.push_back(new_dbc);
            }
        }

      // Now add the new DBCs for the "dot" vars to the DofMap
      std::vector<DirichletBoundary*>::iterator new_dbc_it =
        new_dbcs.begin();

      for( ; new_dbc_it != new_dbcs.end(); ++new_dbc_it )
        {
          const DirichletBoundary & dbc = *(*new_dbc_it);
          this->get_dof_map().add_dirichlet_boundary(dbc);
          delete *new_dbc_it;
        }

    } // if(all_dbcs)
}

unsigned int DifferentiableSystem::get_second_order_dot_var( unsigned int var ) const
{
  // For SteadySolver or SecondOrderUnsteadySolvers, we just give back var
  unsigned int dot_var = var;

  if( !time_solver->is_steady() )
    {
      const UnsteadySolver & unsteady_solver =
        cast_ref<const UnsteadySolver &>(*(time_solver.get()));

      if( unsteady_solver.time_order() == 1 )
        dot_var = this->_second_order_dot_vars.find(var)->second;
    }

  return dot_var;
}

bool DifferentiableSystem::have_first_order_scalar_vars() const
{
  bool have_first_order_scalar_vars = false;

  if(this->have_first_order_vars())
    {
      for( std::set<unsigned int>::const_iterator var_it = this->get_first_order_vars().begin();
           var_it != this->get_first_order_vars().end();
           ++var_it )
        {
          if( this->variable(*var_it).type().family == FEFamily::SCALAR )
            have_first_order_scalar_vars = true;
        }
    }

  return have_first_order_scalar_vars;
}

bool DifferentiableSystem::have_second_order_scalar_vars() const
{
  bool have_second_order_scalar_vars = false;

  if(this->have_second_order_vars())
    {
      for( std::set<unsigned int>::const_iterator var_it = this->get_second_order_vars().begin();
           var_it != this->get_second_order_vars().end();
           ++var_it )
        {
          if( this->variable(*var_it).type().family == FEFamily::SCALAR )
            have_second_order_scalar_vars = true;
        }
    }

  return have_second_order_scalar_vars;
}

} // namespace libMesh
<|endoftext|>


<commit_before>//  File: whitelist_auth.cc
//  Author: Tom Roeder <tmroeder@google.com>
//
//  Description: An implementation of the whitelist manager that handles
//  whitelist files signed with the policy public key.
//
//  Copyright (c) 2013, Google Inc.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tao/whitelist_auth.h"

#include <arpa/inet.h>

#include <fstream>

#include <keyczar/base/base64w.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>

#include "tao/hosted_programs.pb.h"
#include "tao/attestation.pb.h"
#include "tao/keyczar_public_key.pb.h"
#include "tao/util.h"

using keyczar::Keyczar;
using keyczar::Keyset;
using keyczar::Verifier;

using std::ifstream;

typedef unsigned char BYTE;
typedef unsigned int UINT32;
typedef unsigned short UINT16;

namespace tao {
bool WhitelistAuth::Init() {
  // Load the public policy key
  policy_key_.reset(keyczar::Verifier::Read(policy_public_key_.c_str()));
  policy_key_->set_encoding(keyczar::Keyczar::NO_ENCODING);

  // load the whitelist file and check its signature
  ifstream whitelist(whitelist_path_);

  SignedWhitelist sw;
  sw.ParseFromIstream(&whitelist);
  if (!policy_key_->Verify(sw.serialized_whitelist(), sw.signature())) {
    LOG(ERROR) << "The signature did not verify on the signed whitelist";
    return false;
  }

  Whitelist w;
  const string &serialized_w = sw.serialized_whitelist();

  if (!w.ParseFromString(serialized_w)) {
    LOG(ERROR) << "Could not parse the serialized whitelist";
    return false;
  }

  for (int i = 0; i < w.programs_size(); i++) {
    const HostedProgram &hp = w.programs(i);
    if (whitelist_.find(hp.name()) != whitelist_.end()) {
      LOG(ERROR) << "Can't add " << hp.name() << " to the whitelist twice";
      return false;
    }

    whitelist_[hp.name()] = hp.hash();
    hash_whitelist_.insert(hp.hash());
  }

  return true;
}

bool WhitelistAuth::IsAuthorized(const string &program_hash) const {
  return hash_whitelist_.find(program_hash) != hash_whitelist_.end();
}

bool WhitelistAuth::IsAuthorized(const string &program_name,
                                 const string &program_hash) const {
  auto it = whitelist_.find(program_name);
  if (it == whitelist_.end()) {
    return false;
  }

  return (it->second.compare(program_hash) == 0);
}

bool WhitelistAuth::CheckAuthorization(const Attestation &attestation) const {
  Statement s;
  if (!s.ParseFromString(attestation.serialized_statement())) {
    LOG(ERROR) << "Could not parse the statement from an attestation";
    return false;
  }

  // check the time to make sure it hasn't expired
  time_t cur_time;
  time(&cur_time);
  if (cur_time > s.expiration()) {
    LOG(ERROR) << "This attestation has expired";
    return false;
  }

  if (s.hash_alg().compare("SHA256") == 0) {
    // This is a normal program-like hash, so check the whitelist directly
    return IsAuthorized(s.hash());
  }

  if (attestation.has_quote()) {
    // Extract the PCRs as a single string and look for them in the whitelist.
    string quote(attestation.quote().data(), attestation.quote().size());
    size_t quote_len = quote.size();
    if (quote_len < sizeof(UINT16)) {
      LOG(ERROR) << "The quote was not long enough to contain a mask length";
      return false;
    }

    const char *quote_bytes = quote.c_str();
    UINT32 index = 0;
    UINT16 mask_len = ntohs(*(UINT16 *)(quote_bytes + index));
    index += sizeof(UINT16);

    // skip the mask bytes
    if ((quote_len < index) || (quote_len - index < mask_len)) {
      LOG(ERROR) << "The quote was not long enough to contain the mask";
      return false;
    }

    index += mask_len;

    if ((quote_len < index) || (quote_len - index < sizeof(UINT32))) {
      LOG(ERROR) << "The quote was not long enough to contain the pcr length";
      return false;
    }

    UINT32 pcr_len = ntohl(*(UINT32 *)(quote_bytes + index));
    index += sizeof(UINT32);

    if ((quote_len < index) || (quote_len - index < pcr_len)) {
      LOG(ERROR) << "The quote was not long enough to contain the PCRs";
      return false;
    }

    string pcrs(quote_bytes + index, pcr_len);

    // The whitelist uses Base64W encoding for hashes
    string serialized;
    if (!keyczar::base::Base64WEncode(pcrs, &serialized)) {
      LOG(ERROR) << "Can't serialize the PCRs";
      return false;
    }

    return IsAuthorized(serialized);
  }

  return (attestation.type() == ROOT);
}

bool WhitelistAuth::VerifyAttestation(const string &attestation,
                                      string *data) const {
  Attestation a;
  if (!a.ParseFromString(attestation)) {
    LOG(ERROR) << "Could not deserialize an Attestation";
    return false;
  }

  // Choose the verifier to use based on the type of the attestation.
  bool verified = false;
  switch (a.type()) {
    case ROOT:
      verified = CheckRootSignature(a);
      break;
    case INTERMEDIATE:
      verified = CheckIntermediateSignature(a);
      break;
    case TPM_1_2_QUOTE:
      verified = CheckTPM12Quote(a);
      break;
    case LEGACY:
      LOG(ERROR) << "Legacy attestations are not currently supported";
      return false;
    case UNKNOWN:
    default:
      LOG(ERROR) << "Unknown attestation type";
      return false;
  }

  if (!verified) {
    LOG(ERROR) << "Could not verify the signature";
    return false;
  }

  // Check that this attestation is authorized.
  if (!CheckAuthorization(a)) {
    LOG(ERROR) << "The attested program was not authorized";
    return false;
  }

  Statement s;
  if (!s.ParseFromString(a.serialized_statement())) {
    LOG(ERROR) << "Could not parse the statement";
    return false;
  }

  data->assign(s.data().data(), s.data().size());

  VLOG(1) << "The attestation passed verification";

  return true;
}

bool WhitelistAuth::CheckRootSignature(const Attestation &a) const {
  if (a.type() != ROOT) {
    LOG(ERROR) << "This is not a ROOT attestation, but it claims to be "
                  "signed with the public key";
    return false;
  }

  VLOG(2) << "About to verify the signature against the policy key";
  VLOG(2) << "a.serialized_statement().size = "
          << (int)a.serialized_statement().size();
  VLOG(2) << "a.signature().size = " << (int)a.signature().size();

  // Verify against the policy key.
  if (!policy_key_->Verify(a.serialized_statement(), a.signature())) {
    LOG(ERROR) << "Verification failed with the policy key";
    return false;
  }

  return true;
}

bool WhitelistAuth::CheckIntermediateSignature(const Attestation &a) const {
  if (a.type() != INTERMEDIATE) {
    LOG(ERROR)
        << "Expected this Attestation to be INTERMEDIATE, but it was not";
    return false;
  }

  // Recurse on the attestation to get the key information from the cert.
  string key_data;
  if (!VerifyAttestation(a.cert(), &key_data)) {
    LOG(ERROR) << "Could not verify the public_key attestation";
    return false;
  }

  KeyczarPublicKey kpk;
  if (!kpk.ParseFromString(key_data)) {
    LOG(ERROR) << "Could not deserialize the public key for this attestation";
    return false;
  }

  // Get a Keyset corresponding to this public key
  Keyset *k = nullptr;
  if (!DeserializePublicKey(kpk, &k)) {
    LOG(ERROR) << "Could not deserialize the public key";
    return false;
  }

  scoped_ptr<Verifier> v(new Verifier(k));
  v->set_encoding(Keyczar::NO_ENCODING);
  if (!v->Verify(a.serialized_statement(), a.signature())) {
    LOG(ERROR) << "The statement in an attestation did not have a valid "
                  "signature from its public key";
    return false;
  }

  return true;
}

bool WhitelistAuth::CheckTPM12Quote(const Attestation &a) const {
  if (a.type() != TPM_1_2_QUOTE) {
    LOG(ERROR) << "This method can only verify TPM_1_2_QUOTE attestations";
    return false;
  }

  if (!a.has_cert()) {
    LOG(ERROR) << "A TPM 1.2 Quote attestation must have a certificate that "
                  "signs the AIK with the public policy key";
    return false;
  }

  // The data in the Statement in this Attestation should be the serialization
  // of a PEM OpenSSL public key that we can use to check the signature.
  string data;
  if (!VerifyAttestation(a.cert(), &data)) {
    LOG(ERROR) << "The attestation on the AIK did not pass verification";
    return false;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  int bio_bytes_written =
      BIO_write(mem, reinterpret_cast<const void *>(data.data()),
                static_cast<int>(data.size()));
  if (bio_bytes_written != static_cast<int>(data.size())) {
    LOG(ERROR) << "Could not write the data to the BIO";
    return false;
  }

  RSA *aik_rsa = nullptr;
  if (!PEM_read_bio_RSAPublicKey(mem, &aik_rsa, NULL, NULL)) {
    LOG(ERROR) << "Could not read the RSA public key from the attestation";
    return false;
  }

  ScopedRsa aik(aik_rsa);

  // Hash the statement with SHA1 for the external data part of the quote.
  BYTE statement_hash[20];
  SHA1(reinterpret_cast<const BYTE *>(a.serialized_statement().data()),
       a.serialized_statement().size(), statement_hash);

  // The quote can be verified in a qinfo, which has a header of 8 bytes, and
  // two hashes.  The first hash is the hash of the external data, and the
  // second is the hash of the quote itself (pcr_buf above with length in
  // index). This can be hashed and verified directly by OpenSSL.

  BYTE qinfo[8 + 2 * 20];
  qinfo[0] = 1;
  qinfo[1] = 1;
  qinfo[2] = 0;
  qinfo[3] = 0;
  qinfo[4] = 'Q';
  qinfo[5] = 'U';
  qinfo[6] = 'O';
  qinfo[7] = 'T';

  // The quote in a TPM_1_2_QUOTE is the quote data itself.
  if (!a.has_quote()) {
    LOG(ERROR) << "A TPM_1_2_QUOTE must have a quote value";
    return false;
  }

  SHA1(reinterpret_cast<const BYTE *>(a.quote().data()), a.quote().size(),
       qinfo + 8);
  memcpy(qinfo + 8 + 20, statement_hash, sizeof(statement_hash));

  BYTE quote_hash[20];
  SHA1(qinfo, sizeof(qinfo), quote_hash);
  if (RSA_verify(NID_sha1, quote_hash, sizeof(quote_hash),
                 reinterpret_cast<const BYTE *>(a.signature().data()),
                 a.signature().size(), aik.get()) !=
      1) {
    LOG(ERROR) << "The RSA signature did not pass verification";
    return false;
  }

  return true;
}
}  // namespace tao
<commit_msg>Added some more error messages for when a program/hash is not authorized<commit_after>//  File: whitelist_auth.cc
//  Author: Tom Roeder <tmroeder@google.com>
//
//  Description: An implementation of the whitelist manager that handles
//  whitelist files signed with the policy public key.
//
//  Copyright (c) 2013, Google Inc.  All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tao/whitelist_auth.h"

#include <arpa/inet.h>

#include <fstream>

#include <keyczar/base/base64w.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>

#include "tao/hosted_programs.pb.h"
#include "tao/attestation.pb.h"
#include "tao/keyczar_public_key.pb.h"
#include "tao/util.h"

using keyczar::Keyczar;
using keyczar::Keyset;
using keyczar::Verifier;

using std::ifstream;

typedef unsigned char BYTE;
typedef unsigned int UINT32;
typedef unsigned short UINT16;

namespace tao {
bool WhitelistAuth::Init() {
  // Load the public policy key
  policy_key_.reset(keyczar::Verifier::Read(policy_public_key_.c_str()));
  policy_key_->set_encoding(keyczar::Keyczar::NO_ENCODING);

  // load the whitelist file and check its signature
  ifstream whitelist(whitelist_path_);

  SignedWhitelist sw;
  sw.ParseFromIstream(&whitelist);
  if (!policy_key_->Verify(sw.serialized_whitelist(), sw.signature())) {
    LOG(ERROR) << "The signature did not verify on the signed whitelist";
    return false;
  }

  Whitelist w;
  const string &serialized_w = sw.serialized_whitelist();

  if (!w.ParseFromString(serialized_w)) {
    LOG(ERROR) << "Could not parse the serialized whitelist";
    return false;
  }

  for (int i = 0; i < w.programs_size(); i++) {
    const HostedProgram &hp = w.programs(i);
    if (whitelist_.find(hp.name()) != whitelist_.end()) {
      LOG(ERROR) << "Can't add " << hp.name() << " to the whitelist twice";
      return false;
    }

    whitelist_[hp.name()] = hp.hash();
    hash_whitelist_.insert(hp.hash());
  }

  return true;
}

bool WhitelistAuth::IsAuthorized(const string &program_hash) const {
  bool authorized = (hash_whitelist_.find(program_hash) != hash_whitelist_.end());
  if (!authorized) {
    LOG(ERROR) << "Could not find the hash " << program_hash
               << " on the whitelist";
  }

  return authorized;
}

bool WhitelistAuth::IsAuthorized(const string &program_name,
                                 const string &program_hash) const {
  auto it = whitelist_.find(program_name);
  if (it == whitelist_.end()) {
    LOG(ERROR) << "The program " << program_name << " with hash "
               << program_hash << " was not found on the whitelist";
    return false;
  }

  return (it->second.compare(program_hash) == 0);
}

bool WhitelistAuth::CheckAuthorization(const Attestation &attestation) const {
  Statement s;
  if (!s.ParseFromString(attestation.serialized_statement())) {
    LOG(ERROR) << "Could not parse the statement from an attestation";
    return false;
  }

  // check the time to make sure it hasn't expired
  time_t cur_time;
  time(&cur_time);
  if (cur_time > s.expiration()) {
    LOG(ERROR) << "This attestation has expired";
    return false;
  }

  if (s.hash_alg().compare("SHA256") == 0) {
    // This is a normal program-like hash, so check the whitelist directly
    return IsAuthorized(s.hash());
  }

  if (attestation.has_quote()) {
    // Extract the PCRs as a single string and look for them in the whitelist.
    string quote(attestation.quote().data(), attestation.quote().size());
    size_t quote_len = quote.size();
    if (quote_len < sizeof(UINT16)) {
      LOG(ERROR) << "The quote was not long enough to contain a mask length";
      return false;
    }

    const char *quote_bytes = quote.c_str();
    UINT32 index = 0;
    UINT16 mask_len = ntohs(*(UINT16 *)(quote_bytes + index));
    index += sizeof(UINT16);

    // skip the mask bytes
    if ((quote_len < index) || (quote_len - index < mask_len)) {
      LOG(ERROR) << "The quote was not long enough to contain the mask";
      return false;
    }

    index += mask_len;

    if ((quote_len < index) || (quote_len - index < sizeof(UINT32))) {
      LOG(ERROR) << "The quote was not long enough to contain the pcr length";
      return false;
    }

    UINT32 pcr_len = ntohl(*(UINT32 *)(quote_bytes + index));
    index += sizeof(UINT32);

    if ((quote_len < index) || (quote_len - index < pcr_len)) {
      LOG(ERROR) << "The quote was not long enough to contain the PCRs";
      return false;
    }

    string pcrs(quote_bytes + index, pcr_len);

    // The whitelist uses Base64W encoding for hashes
    string serialized;
    if (!keyczar::base::Base64WEncode(pcrs, &serialized)) {
      LOG(ERROR) << "Can't serialize the PCRs";
      return false;
    }

    return IsAuthorized(serialized);
  }

  return (attestation.type() == ROOT);
}

bool WhitelistAuth::VerifyAttestation(const string &attestation,
                                      string *data) const {
  Attestation a;
  if (!a.ParseFromString(attestation)) {
    LOG(ERROR) << "Could not deserialize an Attestation";
    return false;
  }

  // Choose the verifier to use based on the type of the attestation.
  bool verified = false;
  switch (a.type()) {
    case ROOT:
      verified = CheckRootSignature(a);
      break;
    case INTERMEDIATE:
      verified = CheckIntermediateSignature(a);
      break;
    case TPM_1_2_QUOTE:
      verified = CheckTPM12Quote(a);
      break;
    case LEGACY:
      LOG(ERROR) << "Legacy attestations are not currently supported";
      return false;
    case UNKNOWN:
    default:
      LOG(ERROR) << "Unknown attestation type";
      return false;
  }

  if (!verified) {
    LOG(ERROR) << "Could not verify the signature";
    return false;
  }

  // Check that this attestation is authorized.
  if (!CheckAuthorization(a)) {
    LOG(ERROR) << "The attested program was not authorized";
    return false;
  }

  Statement s;
  if (!s.ParseFromString(a.serialized_statement())) {
    LOG(ERROR) << "Could not parse the statement";
    return false;
  }

  data->assign(s.data().data(), s.data().size());

  VLOG(1) << "The attestation passed verification";

  return true;
}

bool WhitelistAuth::CheckRootSignature(const Attestation &a) const {
  if (a.type() != ROOT) {
    LOG(ERROR) << "This is not a ROOT attestation, but it claims to be "
                  "signed with the public key";
    return false;
  }

  VLOG(2) << "About to verify the signature against the policy key";
  VLOG(2) << "a.serialized_statement().size = "
          << (int)a.serialized_statement().size();
  VLOG(2) << "a.signature().size = " << (int)a.signature().size();

  // Verify against the policy key.
  if (!policy_key_->Verify(a.serialized_statement(), a.signature())) {
    LOG(ERROR) << "Verification failed with the policy key";
    return false;
  }

  return true;
}

bool WhitelistAuth::CheckIntermediateSignature(const Attestation &a) const {
  if (a.type() != INTERMEDIATE) {
    LOG(ERROR)
        << "Expected this Attestation to be INTERMEDIATE, but it was not";
    return false;
  }

  // Recurse on the attestation to get the key information from the cert.
  string key_data;
  if (!VerifyAttestation(a.cert(), &key_data)) {
    LOG(ERROR) << "Could not verify the public_key attestation";
    return false;
  }

  KeyczarPublicKey kpk;
  if (!kpk.ParseFromString(key_data)) {
    LOG(ERROR) << "Could not deserialize the public key for this attestation";
    return false;
  }

  // Get a Keyset corresponding to this public key
  Keyset *k = nullptr;
  if (!DeserializePublicKey(kpk, &k)) {
    LOG(ERROR) << "Could not deserialize the public key";
    return false;
  }

  scoped_ptr<Verifier> v(new Verifier(k));
  v->set_encoding(Keyczar::NO_ENCODING);
  if (!v->Verify(a.serialized_statement(), a.signature())) {
    LOG(ERROR) << "The statement in an attestation did not have a valid "
                  "signature from its public key";
    return false;
  }

  return true;
}

bool WhitelistAuth::CheckTPM12Quote(const Attestation &a) const {
  if (a.type() != TPM_1_2_QUOTE) {
    LOG(ERROR) << "This method can only verify TPM_1_2_QUOTE attestations";
    return false;
  }

  if (!a.has_cert()) {
    LOG(ERROR) << "A TPM 1.2 Quote attestation must have a certificate that "
                  "signs the AIK with the public policy key";
    return false;
  }

  // The data in the Statement in this Attestation should be the serialization
  // of a PEM OpenSSL public key that we can use to check the signature.
  string data;
  if (!VerifyAttestation(a.cert(), &data)) {
    LOG(ERROR) << "The attestation on the AIK did not pass verification";
    return false;
  }

  BIO *mem = BIO_new(BIO_s_mem());
  int bio_bytes_written =
      BIO_write(mem, reinterpret_cast<const void *>(data.data()),
                static_cast<int>(data.size()));
  if (bio_bytes_written != static_cast<int>(data.size())) {
    LOG(ERROR) << "Could not write the data to the BIO";
    return false;
  }

  RSA *aik_rsa = nullptr;
  if (!PEM_read_bio_RSAPublicKey(mem, &aik_rsa, NULL, NULL)) {
    LOG(ERROR) << "Could not read the RSA public key from the attestation";
    return false;
  }

  ScopedRsa aik(aik_rsa);

  // Hash the statement with SHA1 for the external data part of the quote.
  BYTE statement_hash[20];
  SHA1(reinterpret_cast<const BYTE *>(a.serialized_statement().data()),
       a.serialized_statement().size(), statement_hash);

  // The quote can be verified in a qinfo, which has a header of 8 bytes, and
  // two hashes.  The first hash is the hash of the external data, and the
  // second is the hash of the quote itself (pcr_buf above with length in
  // index). This can be hashed and verified directly by OpenSSL.

  BYTE qinfo[8 + 2 * 20];
  qinfo[0] = 1;
  qinfo[1] = 1;
  qinfo[2] = 0;
  qinfo[3] = 0;
  qinfo[4] = 'Q';
  qinfo[5] = 'U';
  qinfo[6] = 'O';
  qinfo[7] = 'T';

  // The quote in a TPM_1_2_QUOTE is the quote data itself.
  if (!a.has_quote()) {
    LOG(ERROR) << "A TPM_1_2_QUOTE must have a quote value";
    return false;
  }

  SHA1(reinterpret_cast<const BYTE *>(a.quote().data()), a.quote().size(),
       qinfo + 8);
  memcpy(qinfo + 8 + 20, statement_hash, sizeof(statement_hash));

  BYTE quote_hash[20];
  SHA1(qinfo, sizeof(qinfo), quote_hash);
  if (RSA_verify(NID_sha1, quote_hash, sizeof(quote_hash),
                 reinterpret_cast<const BYTE *>(a.signature().data()),
                 a.signature().size(), aik.get()) !=
      1) {
    LOG(ERROR) << "The RSA signature did not pass verification";
    return false;
  }

  return true;
}
}  // namespace tao
<|endoftext|>


<commit_before>#ifndef BOOK_FUNCIDS_HPP
#define BOOK_FUNCIDS_HPP

#include <string>
#include <SFML-Book/common/Configuration.hpp>

namespace book
{
    namespace FuncIds{
        enum FUNCIDS {
            //specials
            IdHandler = 0,
            IdDisconnected,
            IdLogOut,

            //main menu
            IdGetListGame, //client
            IdSetListGame, //server
            IdCreateGame, //client
            IdJoinGame, //client
            IdJoinGameConfirmation, //server
            IdJoinGameReject, //server

            //in game
            IdRequestCreateEntity, //client
            IdRequestDestroyEntity, //client
            IdDestroyEntity, //server
            IdCreateEntity, //server
            IdUpdateEntity, //server
            //// Entity Event
            IdOnHittedEntity, //server
            IdOnHitEntity, //server
            IdOnSpawnEntity, //server
            //// Team event
            IdUpdateTeam, //server
        };
    }

    namespace EntityType {
        enum TYPES {
            IdMain = 0,
            IdEye,
            IdWormEgg,
            IdWorm,
            IdCarnivor,
        };

        enum BuildEntities {
            EntityMain,
            EntityWormEgg,
            EntityCarnivor,
            SIZE
        };

        struct Info {
            int cost;
            std::string name;
            short int makeAs;
            int icon_id;
            int animation_id;
            std::string description;
        };

        static Info informations[SIZE] = {
            {5000, "GQ",IdMain, Configuration::TexBuildMain, Configuration::AnimMainStand,"Main building.\nGenerates gold.\nYou loose the game\nif you don't control\nany one of them."},
            {250, "Worm Egg",IdWormEgg,Configuration::TexBuildWormEgg, Configuration::AnimWormEggStand, "Spawn some worms"},
            {300, "Carnivore",IdCarnivor, Configuration::TexBuildCarnivor, Configuration::AnimCarnivorStand, "Make hight damage"}
        };
    }

}

#endif
<commit_msg>remove useless datas<commit_after>#ifndef BOOK_FUNCIDS_HPP
#define BOOK_FUNCIDS_HPP

#include <string>
#include <SFML-Book/common/Configuration.hpp>

namespace book
{
    namespace FuncIds{
        enum FUNCIDS {
            //specials
            IdHandler = 0,
            IdDisconnected,
            IdLogOut,

            //main menu
            IdGetListGame, //client
            IdSetListGame, //server
            IdCreateGame, //client
            IdJoinGame, //client
            IdJoinGameConfirmation, //server
            IdJoinGameReject, //server

            //in game
            IdRequestCreateEntity, //client
            IdRequestDestroyEntity, //client
            IdDestroyEntity, //server
            IdCreateEntity, //server
            IdUpdateEntity, //server
            //// Entity Event
            IdOnHittedEntity, //server
            IdOnHitEntity, //server
            IdOnSpawnEntity, //server
            //// Team event
            IdUpdateTeam, //server
        };
    }

    namespace EntityType {
        enum TYPES {
            IdMain = 0,
            IdEye,
            IdWormEgg,
            IdWorm,
            IdCarnivor,
        };

        /*enum BuildEntities {
            EntityMain,
            EntityWormEgg,
            EntityCarnivor,
            SIZE
        };*/

        struct Info {
            int cost;
            std::string name;
            short int makeAs;
            int icon_id;
            int animation_id;
            std::string description;
        };

        static Info informations[] = {
            {5000, "GQ",IdMain, Configuration::TexBuildMain, Configuration::AnimMainStand,"Main building.\nGenerates gold.\nYou loose the game\nif you don't control\nany one of them."},
            {250, "Worm Egg",IdWormEgg,Configuration::TexBuildWormEgg, Configuration::AnimWormEggStand, "Spawn some worms"},
            {300, "Carnivore",IdCarnivor, Configuration::TexBuildCarnivor, Configuration::AnimCarnivorStand, "Make hight damage"}
        };
    }

}

#endif
<|endoftext|>


<commit_before>#pragma once

#include "conv2d_dot.hpp"
#include "conv2d_mad.hpp"

namespace tensor
{
        ///
        /// \brief 2D convolution: odata += idata @ kdata (decode at runtime the best operator to use)
        ///
        struct conv2d_dyn_t
        {
                template
                <
                        typename tmatrixi,
                        typename tmatrixk,
                        typename tmatrixo
                >
                void operator()(const tmatrixi& idata, const tmatrixk& kdata, tmatrixo&& odata) const
                {
                        conv2d_assert(idata, kdata, odata);

                        if (kdata.rows() == 1 && kdata.cols() == 1)
                        {
                                odata.noalias() += idata * kdata(0, 0);
                        }
                        else if (odata.rows() == 1 && odata.cols() == 1)
                        {
                                odata(0, 0) += (idata.array() * kdata.array()).sum();
                        }
                        else
                        {
                                conv2d_dot_dyn_t()(idata, kdata, odata);
                        }
                }
        };
}

<commit_msg>slightly faster 3x3 & 5x5 convolutions<commit_after>#pragma once

#include "conv2d_dot.hpp"
#include "conv2d_mad.hpp"

namespace tensor
{
        ///
        /// \brief 2D convolution: odata += idata @ kdata (decode at runtime the best operator to use)
        ///
        struct conv2d_dyn_t
        {
                template
                <
                        typename tmatrixi,
                        typename tmatrixk,
                        typename tmatrixo
                >
                void conv3x3(const tmatrixi& idata, const tmatrixk& kdata, tmatrixo&& odata) const
                {
                        conv2d_assert(idata, kdata, odata);
                        assert(kdata.rows() == 3);
                        assert(kdata.cols() == 3);

                        const auto orows = odata.rows();
                        const auto ocols = odata.cols();

                        for (auto r = 0; r < orows; r ++)
                        {
                                for (auto c = 0; c < ocols; c ++)
                                {
                                        odata(r, c) +=
                                        idata.row(r + 0).template segment<3>(c).dot(kdata.row(0)) +
                                        idata.row(r + 1).template segment<3>(c).dot(kdata.row(1)) +
                                        idata.row(r + 2).template segment<3>(c).dot(kdata.row(2));
                                }
                        }
                }

                template
                <
                        typename tmatrixi,
                        typename tmatrixk,
                        typename tmatrixo
                >
                void conv5x5(const tmatrixi& idata, const tmatrixk& kdata, tmatrixo&& odata) const
                {
                        conv2d_assert(idata, kdata, odata);
                        assert(kdata.rows() == 5);
                        assert(kdata.cols() == 5);

                        const auto orows = odata.rows();
                        const auto ocols = odata.cols();

                        const auto krow0 = kdata.row(0);
                        const auto krow1 = kdata.row(1);
                        const auto krow2 = kdata.row(2);
                        const auto krow3 = kdata.row(3);
                        const auto krow4 = kdata.row(4);

                        for (auto r = 0; r < orows; r ++)
                        {
                                const auto irow0 = idata.row(r + 0);
                                const auto irow1 = idata.row(r + 1);
                                const auto irow2 = idata.row(r + 2);
                                const auto irow3 = idata.row(r + 3);
                                const auto irow4 = idata.row(r + 4);

                                for (auto c = 0; c < ocols; c ++)
                                {
                                        odata(r, c) +=
                                        irow0.template segment<5>(c).dot(krow0) +
                                        irow1.template segment<5>(c).dot(krow1) +
                                        irow2.template segment<5>(c).dot(krow2) +
                                        irow3.template segment<5>(c).dot(krow3) +
                                        irow4.template segment<5>(c).dot(krow4);
                                }
                        }
                }

                template
                <
                        typename tmatrixi,
                        typename tmatrixk,
                        typename tmatrixo
                >
                void operator()(const tmatrixi& idata, const tmatrixk& kdata, tmatrixo&& odata) const
                {
                        conv2d_assert(idata, kdata, odata);

                        if (kdata.rows() == 1 && kdata.cols() == 1)
                        {
                                odata.noalias() += idata * kdata(0, 0);
                        }
                        else if (odata.rows() == 1 && odata.cols() == 1)
                        {
                                odata(0, 0) += (idata.array() * kdata.array()).sum();
                        }
                        else if (kdata.rows() == 3 && kdata.cols() == 3)
                        {
                                conv3x3(idata, kdata, odata);
                        }
                        else if (kdata.rows() == 5 && kdata.cols() == 5)
                        {
                                conv5x5(idata, kdata, odata);
                        }
                        else
                        {
                                conv2d_dot_dyn_t()(idata, kdata, odata);
                        }
                }
        };
}

<|endoftext|>


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

#include <deepstream/core/buffer.hpp>
#include <deepstream/core/client.hpp>
#include <deepstream/core/error_handler.hpp>
#include <deepstream/core/event.hpp>
#include <deepstream/core/presence.hpp>
#include <deepstream/core/version.hpp>
#include <deepstream/lib/poco-ws.hpp>
#include <deepstream/lib/basic-error-handler.hpp>
#include <deepstream/lib/json.hpp>
#include <deepstream/lib/type-serializer.hpp>

#include <string>
#include <exception>

namespace deepstream {

    using json = nlohmann::json;

    struct Deepstream {

        typedef std::function<void(const json &&)> LoginCallback;

        Deepstream() = delete;

        Deepstream(const Deepstream &) = delete;

        Deepstream &operator=(const Deepstream &) = delete;

        Deepstream(const std::string &uri)
            : wsh_()
            , error_handler_()
            , client_(uri, wsh_, error_handler_)
            , type_serializer_(error_handler_)
            , event(client_, error_handler_, type_serializer_)
            , presence(client_, error_handler_)
        {
        }

        /**
         * This function reads all incoming messages from the websocket and
         * executes the appropriate callbacks; it returns when there are no
         * messages left.
         */
        void process_messages()
        {
            wsh_.process_messages();
        }

        void login()
        {
            const json::object_t auth({});
            login(auth);
        }

        void login(const json::object_t &auth)
        {
            const LoginCallback callback;
            login(auth, callback);
        }

        void login(const LoginCallback &callback)
        {
            login(json({}), callback);
        }

        /**
         * Given a client in `AWAIT_CONNECTION` state, this function attempts to
         * log in with the given authentication data.
         *
         * The format of the user authentication data depends on the authentication
         * method used by the server.
         *
         * @param[in] auth User authentication data
         * @param[in] callback A LoginCallback that will be invoked with the
         * user data on successful login.
         * in `p_user_data` if the reference is not `NULL`.
         */
        void login(const json::object_t &auth, const LoginCallback &callback)
        {
            const std::string auth_str(json(auth).dump());
            const Buffer auth_buff(auth_str);

            const Client::LoginCallback core_callback([callback, this](const Buffer &&login_data) {
                const json data = type_serializer_.prefixed_to_json(login_data);
                callback(std::move(data));
            });

            client_.login(auth_buff, core_callback);
        }

        void close();

        ConnectionState get_connection_state() const
        {
            return client_.get_connection_state();
        }

        struct EventWrapper {
            typedef std::function<void(const json &)> SubscribeFn;
            typedef std::function<bool(const std::string &, bool)> ListenFn;

            EventWrapper() = delete;

            EventWrapper(const EventWrapper &) = delete;

            EventWrapper &operator=(const EventWrapper &) = delete;

            EventWrapper(Client &client, ErrorHandler &error_handler, TypeSerializer &type_serializer)
                : client_(client)
                , error_handler_(error_handler)
                , type_serializer_(type_serializer)
            {
            }

            void emit(const std::string &name, json data)
            {
                const Buffer &data_buff = type_serializer_.to_prefixed_buffer(data);
                const Buffer name_buff(name);
                client_.event.emit(name_buff, data_buff);
            }

            SubscriptionId subscribe(const std::string &name, SubscribeFn callback)
            {
                Buffer name_buff(name);
                Event::SubscribeFn core_callback([callback, this](const Buffer &prefixed_buff) {
                    const json &data = type_serializer_.prefixed_to_json(prefixed_buff);
                    callback(data);
                });
                SubscriptionId subscription_id = client_.event.subscribe(name_buff, core_callback);
                return subscription_id;
            }

            void unsubscribe(const std::string &name, SubscriptionId subscription_id)
            {
                Buffer name_buff(name);
                client_.event.unsubscribe(name_buff, subscription_id);
            }

            void listen(const std::string &pattern, const ListenFn callback)
            {
                Event::ListenFn core_callback([callback](const Event::Name &match, bool is_subscribed) -> bool {
                    const std::string pattern_str(match.data(), match.size());
                    return callback(pattern_str, is_subscribed);
                });
                Event::Name pattern_buff(pattern);
                client_.event.listen(pattern_buff, core_callback);
            }

            void unlisten(const std::string &pattern)
            {
                Buffer pattern_buff(pattern);
                client_.event.unlisten(pattern_buff);
            }

        private:
            Client &client_;
            ErrorHandler &error_handler_;
            TypeSerializer &type_serializer_;
        };

        struct PresenceWrapper {
            typedef std::function<void(const std::string &name, bool online)> SubscribeFn;

            typedef std::vector<std::string> UserList;
            typedef std::function<void(const UserList&)> QueryFn;

            PresenceWrapper() = delete;

            PresenceWrapper(const PresenceWrapper &) = delete;

            PresenceWrapper &operator=(const PresenceWrapper &) = delete;

            PresenceWrapper(Client &client, ErrorHandler &error_handler)
                : client_(client)
                , error_handler_(error_handler)
            {
            }

            SubscriptionId subscribe(SubscribeFn callback)
            {
                Presence::SubscribeFn core_callback([callback, this](const Buffer &name, bool online) {
                    callback(std::string(name.data(), name.size()), online);
                });
                return client_.presence.subscribe(core_callback);
            }

            void unsubscribe(SubscriptionId id)
            {
                client_.presence.unsubscribe(id);
            }

            void get_all(QueryFn callback)
            {
                Presence::QueryFn core_callback([callback, this](const std::vector<Buffer> users) {
                    std::vector<std::string> users_str(users.size());
                    for (std::size_t i = 0; i < users.size(); ++i) {
                        const Buffer &user = users[i];
                        users_str[i] = std::string(user.data(), user.size());
                    }
                    callback(users_str);
                });
                client_.presence.get_all(core_callback);
            }

        private:
            Client &client_;
            ErrorHandler &error_handler_;
        };

    private:
        PocoWSHandler wsh_;
        BasicErrorHandler error_handler_;
        Client client_;
        TypeSerializer type_serializer_;

    public:
        EventWrapper event;
        PresenceWrapper presence;
    };
    }

#endif // DEEPSTREAM_HPP
<commit_msg>refactor: struct Deepstream -> class Deepstream<commit_after>/*
 * Copyright 2017 deepstreamHub GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef DEEPSTREAM_HPP
#define DEEPSTREAM_HPP

#include <deepstream/core/buffer.hpp>
#include <deepstream/core/client.hpp>
#include <deepstream/core/error_handler.hpp>
#include <deepstream/core/event.hpp>
#include <deepstream/core/presence.hpp>
#include <deepstream/core/version.hpp>
#include <deepstream/lib/poco-ws.hpp>
#include <deepstream/lib/basic-error-handler.hpp>
#include <deepstream/lib/json.hpp>
#include <deepstream/lib/type-serializer.hpp>

#include <string>
#include <exception>

namespace deepstream {

    using json = nlohmann::json;

    class Deepstream {

    public:
        typedef std::function<void(const json &&client_data)> LoginCallback;

        Deepstream() = delete;

        Deepstream(const Deepstream &) = delete;

        Deepstream &operator=(const Deepstream &) = delete;

        Deepstream(const std::string &uri)
            : wsh_()
            , error_handler_()
            , client_(uri, wsh_, error_handler_)
            , type_serializer_(error_handler_)
            , event(client_, error_handler_, type_serializer_)
            , presence(client_, error_handler_)
        {
        }

        /**
         * This function reads all incoming messages from the websocket and
         * executes the appropriate callbacks; it returns when there are no
         * messages left.
         */
        void process_messages()
        {
            wsh_.process_messages();
        }

        void login()
        {
            const json::object_t auth({});
            login(auth);
        }

        void login(const json::object_t &auth)
        {
            const LoginCallback callback;
            login(auth, callback);
        }

        void login(const LoginCallback &callback)
        {
            login(json({}), callback);
        }

        /**
         * Given a client in `AWAIT_CONNECTION` state, this function attempts to
         * log in with the given authentication data.
         *
         * The format of the user authentication data depends on the authentication
         * method used by the server.
         *
         * @param[in] auth User authentication data
         * @param[in] callback A LoginCallback that will be invoked with the
         * user data on successful login.
         * in `p_user_data` if the reference is not `NULL`.
         */
        void login(const json::object_t &auth, const LoginCallback &callback)
        {
            const std::string auth_str(json(auth).dump());
            const Buffer auth_buff(auth_str);

            const Client::LoginCallback core_callback([callback, this](const Buffer &&login_data) {
                const json data = type_serializer_.prefixed_to_json(login_data);
                callback(std::move(data));
            });

            client_.login(auth_buff, core_callback);
        }

        void close();

        ConnectionState get_connection_state() const
        {
            return client_.get_connection_state();
        }

        struct EventWrapper {
            typedef std::function<void(const json &)> SubscribeFn;
            typedef std::function<bool(const std::string &, bool)> ListenFn;

            EventWrapper() = delete;

            EventWrapper(const EventWrapper &) = delete;

            EventWrapper &operator=(const EventWrapper &) = delete;

            EventWrapper(Client &client, ErrorHandler &error_handler, TypeSerializer &type_serializer)
                : client_(client)
                , error_handler_(error_handler)
                , type_serializer_(type_serializer)
            {
            }

            void emit(const std::string &name, json data)
            {
                const Buffer &data_buff = type_serializer_.to_prefixed_buffer(data);
                const Buffer name_buff(name);
                client_.event.emit(name_buff, data_buff);
            }

            SubscriptionId subscribe(const std::string &name, SubscribeFn callback)
            {
                Buffer name_buff(name);
                Event::SubscribeFn core_callback([callback, this](const Buffer &prefixed_buff) {
                    const json &data = type_serializer_.prefixed_to_json(prefixed_buff);
                    callback(data);
                });
                SubscriptionId subscription_id = client_.event.subscribe(name_buff, core_callback);
                return subscription_id;
            }

            void unsubscribe(const std::string &name, SubscriptionId subscription_id)
            {
                Buffer name_buff(name);
                client_.event.unsubscribe(name_buff, subscription_id);
            }

            void listen(const std::string &pattern, const ListenFn callback)
            {
                Event::ListenFn core_callback([callback](const Event::Name &match, bool is_subscribed) -> bool {
                    const std::string pattern_str(match.data(), match.size());
                    return callback(pattern_str, is_subscribed);
                });
                Event::Name pattern_buff(pattern);
                client_.event.listen(pattern_buff, core_callback);
            }

            void unlisten(const std::string &pattern)
            {
                Buffer pattern_buff(pattern);
                client_.event.unlisten(pattern_buff);
            }

        private:
            Client &client_;
            ErrorHandler &error_handler_;
            TypeSerializer &type_serializer_;
        };

        struct PresenceWrapper {
            typedef std::function<void(const std::string &name, bool online)> SubscribeFn;

            typedef std::vector<std::string> UserList;
            typedef std::function<void(const UserList&)> QueryFn;

            PresenceWrapper() = delete;

            PresenceWrapper(const PresenceWrapper &) = delete;

            PresenceWrapper &operator=(const PresenceWrapper &) = delete;

            PresenceWrapper(Client &client, ErrorHandler &error_handler)
                : client_(client)
                , error_handler_(error_handler)
            {
            }

            SubscriptionId subscribe(SubscribeFn callback)
            {
                Presence::SubscribeFn core_callback([callback, this](const Buffer &name, bool online) {
                    callback(std::string(name.data(), name.size()), online);
                });
                return client_.presence.subscribe(core_callback);
            }

            void unsubscribe(SubscriptionId id)
            {
                client_.presence.unsubscribe(id);
            }

            void get_all(QueryFn callback)
            {
                Presence::QueryFn core_callback([callback, this](const std::vector<Buffer> users) {
                    std::vector<std::string> users_str(users.size());
                    for (std::size_t i = 0; i < users.size(); ++i) {
                        const Buffer &user = users[i];
                        users_str[i] = std::string(user.data(), user.size());
                    }
                    callback(users_str);
                });
                client_.presence.get_all(core_callback);
            }

        private:
            Client &client_;
            ErrorHandler &error_handler_;
        };

    private:
        PocoWSHandler wsh_;
        BasicErrorHandler error_handler_;
        Client client_;
        TypeSerializer type_serializer_;

    public:
        EventWrapper event;
        PresenceWrapper presence;
    };
    }

#endif // DEEPSTREAM_HPP
<|endoftext|>


<commit_before>/*
 * ImageHasher - C++ version of the Hashing module from SimilarImage
 * Copyright (C) 2014  Nicholas Wright
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <gtest/gtest.h>
#include "../include/Database.hpp"
#include <boost/filesystem.hpp>
#include <iostream>

class DatabaseTest : public :: testing::Test {
protected:

	Database* db;
	boost::filesystem::path* dbPath;

	boost::filesystem::path tempfile() {
		return boost::filesystem::temp_directory_path() /= boost::filesystem::unique_path();
	}

	DatabaseTest() {
		dbPath = new boost::filesystem::path(tempfile());
		db = new Database(dbPath->c_str());
	}

	~DatabaseTest() {
		db->shutdown();
		delete(db);
		delete(dbPath);
	}
};

TEST_F(DatabaseTest, dbCreationCustom) {
	ASSERT_TRUE(boost::filesystem::exists(*dbPath));
}

TEST_F(DatabaseTest, writeRecords) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("bar", "bar",0);

	db->add(dbd1);
	db->add(dbd2);

	db->shutdown();

	ASSERT_EQ(2, db->getRecordsWritten());
}

TEST_F(DatabaseTest, writeRecordsWithInvalid) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("bar", "bar",0);
	Database::db_data dbd3("notValid", "",0);

	dbd3.status = Database::INVALID;

	db->add(dbd1);
	db->add(dbd2);
	db->add(dbd3);

	db->shutdown();

	ASSERT_EQ(2, db->getRecordsWritten());
}

TEST_F(DatabaseTest, writeDuplicateRecords) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("foo","foo",0);

	db->add(dbd1);
	db->add(dbd2);

	db->shutdown();

	ASSERT_EQ(1, db->getRecordsWritten());
}

TEST_F(DatabaseTest, writeDuplicateRecordsDifferentPath) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("bar","foo",0);

	db->add(dbd1);
	db->add(dbd2);

	db->shutdown();

	ASSERT_EQ(2, db->getRecordsWritten());
}

TEST_F(DatabaseTest, entryExistsNonExistant) {
	Database::db_data dbd1("foo");

	ASSERT_FALSE(db->entryExists(dbd1));
}

TEST_F(DatabaseTest, entryExists) {
	Database::db_data dbd1("foo","foo",0);
	db->add(dbd1);
	db->flush();
	ASSERT_TRUE(db->entryExists(dbd1));
	db->shutdown();
}

TEST_F(DatabaseTest, getSHAvalid) {
	Database::db_data data("foobar", "ABCD", 1);

	db->add(data);
	db->flush();

	std::string shaHash = db->getSHA(fs::path("foobar"));

	ASSERT_EQ("ABCD", shaHash);
	db->shutdown();
}

TEST_F(DatabaseTest, getSHANotExisting) {
	std::string shaHash = db->getSHA(fs::path("unknown"));

	ASSERT_TRUE(shaHash.empty());
	db->shutdown();
}

TEST_F(DatabaseTest, add_path_placeholder) {
	int id = db->add_path_placeholder("placeholder");
	db->shutdown();

	ASSERT_EQ(1, id);
}

TEST_F(DatabaseTest, get_files_with_path) {
	Database::db_data data0("/foo/bar", "ABCD", 1);
	Database::db_data data1("/foo/bar/bar", "ABCD", 1);
	Database::db_data data2("/foo/baz", "ABCD", 1);
	Database::db_data data3("/bar/foo", "ABCD", 1);
	Database::db_data data4("/red/fox", "ABCD", 1);

	db->add(data0);
	db->add(data1);
	db->add(data2);
	db->add(data3);
	db->add(data4);

	db->flush();

	fs::path search_path("/foo/");

	std::list<fs::path> paths = db->getFilesWithPath(search_path);
	ASSERT_EQ(3,paths.size());

	paths.sort();

	ASSERT_STREQ("/foo/bar", paths.front().string().c_str());
	ASSERT_STREQ("/foo/baz", paths.back().string().c_str());
}

TEST_F(DatabaseTest, prunePath) {
	Database::db_data data0("/foo/bar", "ABCD", 1);
	Database::db_data data1("/foo/bar/bar", "ABCD", 1);
	Database::db_data data2("/foo/baz", "ABCD", 1);
	Database::db_data data3("/bar/foo", "ABCD", 1);
	Database::db_data data4("/red/fox", "ABCD", 1);

	db->add(data0);
	db->add(data1);
	db->add(data2);
	db->add(data3);
	db->add(data4);

	db->flush();

	std::list<fs::path> to_delete;

	to_delete.push_back(fs::path("/foo/bar"));
	to_delete.push_back(fs::path("/foo/baz"));

	// guard
	ASSERT_TRUE(db->entryExists(to_delete.front()));
	ASSERT_TRUE(db->entryExists(to_delete.back()));

	db->prunePath(to_delete);

	ASSERT_FALSE(db->entryExists(to_delete.front()));
	ASSERT_FALSE(db->entryExists(to_delete.back()));
}

TEST_F(DatabaseTest, getPhash) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	int64_t pHash = db->getPhash("/foo/bar");

	ASSERT_EQ(42, pHash);
}

TEST_F(DatabaseTest, getPhash_invalid_entry) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	int64_t pHash = db->getPhash("/foo/baz");

	ASSERT_EQ(-1, pHash);
}

TEST_F(DatabaseTest, get_hash_phash) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	imageHasher::db::table::Hash hash = db->get_hash(42);

	ASSERT_STREQ("ABCD", hash.get_sha256().c_str());
}

TEST_F(DatabaseTest, get_hash_phash_not_valid) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	imageHasher::db::table::Hash hash = db->get_hash(12);

	ASSERT_FALSE(hash.is_valid());
}
<commit_msg>Added tests for hash table pruning<commit_after>/*
 * ImageHasher - C++ version of the Hashing module from SimilarImage
 * Copyright (C) 2014  Nicholas Wright
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <gtest/gtest.h>
#include "../include/Database.hpp"
#include <boost/filesystem.hpp>
#include <iostream>

class DatabaseTest : public :: testing::Test {
protected:

	Database* db;
	boost::filesystem::path* dbPath;

	boost::filesystem::path tempfile() {
		return boost::filesystem::temp_directory_path() /= boost::filesystem::unique_path();
	}

	DatabaseTest() {
		dbPath = new boost::filesystem::path(tempfile());
		db = new Database(dbPath->c_str());
	}

	~DatabaseTest() {
		db->shutdown();
		delete(db);
		delete(dbPath);
	}
};

TEST_F(DatabaseTest, dbCreationCustom) {
	ASSERT_TRUE(boost::filesystem::exists(*dbPath));
}

TEST_F(DatabaseTest, writeRecords) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("bar", "bar",0);

	db->add(dbd1);
	db->add(dbd2);

	db->shutdown();

	ASSERT_EQ(2, db->getRecordsWritten());
}

TEST_F(DatabaseTest, writeRecordsWithInvalid) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("bar", "bar",0);
	Database::db_data dbd3("notValid", "",0);

	dbd3.status = Database::INVALID;

	db->add(dbd1);
	db->add(dbd2);
	db->add(dbd3);

	db->shutdown();

	ASSERT_EQ(2, db->getRecordsWritten());
}

TEST_F(DatabaseTest, writeDuplicateRecords) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("foo","foo",0);

	db->add(dbd1);
	db->add(dbd2);

	db->shutdown();

	ASSERT_EQ(1, db->getRecordsWritten());
}

TEST_F(DatabaseTest, writeDuplicateRecordsDifferentPath) {
	Database::db_data dbd1("foo","foo",0);
	Database::db_data dbd2("bar","foo",0);

	db->add(dbd1);
	db->add(dbd2);

	db->shutdown();

	ASSERT_EQ(2, db->getRecordsWritten());
}

TEST_F(DatabaseTest, entryExistsNonExistant) {
	Database::db_data dbd1("foo");

	ASSERT_FALSE(db->entryExists(dbd1));
}

TEST_F(DatabaseTest, entryExists) {
	Database::db_data dbd1("foo","foo",0);
	db->add(dbd1);
	db->flush();
	ASSERT_TRUE(db->entryExists(dbd1));
	db->shutdown();
}

TEST_F(DatabaseTest, getSHAvalid) {
	Database::db_data data("foobar", "ABCD", 1);

	db->add(data);
	db->flush();

	std::string shaHash = db->getSHA(fs::path("foobar"));

	ASSERT_EQ("ABCD", shaHash);
	db->shutdown();
}

TEST_F(DatabaseTest, getSHANotExisting) {
	std::string shaHash = db->getSHA(fs::path("unknown"));

	ASSERT_TRUE(shaHash.empty());
	db->shutdown();
}

TEST_F(DatabaseTest, add_path_placeholder) {
	int id = db->add_path_placeholder("placeholder");
	db->shutdown();

	ASSERT_EQ(1, id);
}

TEST_F(DatabaseTest, get_files_with_path) {
	Database::db_data data0("/foo/bar", "ABCD", 1);
	Database::db_data data1("/foo/bar/bar", "ABCD", 1);
	Database::db_data data2("/foo/baz", "ABCD", 1);
	Database::db_data data3("/bar/foo", "ABCD", 1);
	Database::db_data data4("/red/fox", "ABCD", 1);

	db->add(data0);
	db->add(data1);
	db->add(data2);
	db->add(data3);
	db->add(data4);

	db->flush();

	fs::path search_path("/foo/");

	std::list<fs::path> paths = db->getFilesWithPath(search_path);
	ASSERT_EQ(3,paths.size());

	paths.sort();

	ASSERT_STREQ("/foo/bar", paths.front().string().c_str());
	ASSERT_STREQ("/foo/baz", paths.back().string().c_str());
}

TEST_F(DatabaseTest, prunePath) {
	Database::db_data data0("/foo/bar", "ABCD", 1);
	Database::db_data data1("/foo/bar/bar", "ABCD", 1);
	Database::db_data data2("/foo/baz", "ABCD", 1);
	Database::db_data data3("/bar/foo", "ABCD", 1);
	Database::db_data data4("/red/fox", "ABCD", 1);

	db->add(data0);
	db->add(data1);
	db->add(data2);
	db->add(data3);
	db->add(data4);

	db->flush();

	std::list<fs::path> to_delete;

	to_delete.push_back(fs::path("/foo/bar"));
	to_delete.push_back(fs::path("/foo/baz"));

	// guard
	ASSERT_TRUE(db->entryExists(to_delete.front()));
	ASSERT_TRUE(db->entryExists(to_delete.back()));

	db->prunePath(to_delete);

	ASSERT_FALSE(db->entryExists(to_delete.front()));
	ASSERT_FALSE(db->entryExists(to_delete.back()));
}

TEST_F(DatabaseTest, getPhash) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	int64_t pHash = db->getPhash("/foo/bar");

	ASSERT_EQ(42, pHash);
}

TEST_F(DatabaseTest, getPhash_invalid_entry) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	int64_t pHash = db->getPhash("/foo/baz");

	ASSERT_EQ(-1, pHash);
}

TEST_F(DatabaseTest, get_hash_phash) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	imageHasher::db::table::Hash hash = db->get_hash(42);

	ASSERT_STREQ("ABCD", hash.get_sha256().c_str());
}

TEST_F(DatabaseTest, get_hash_phash_not_valid) {
	Database::db_data data("/foo/bar", "ABCD", 42);
	db->add(data);
	db->flush();

	imageHasher::db::table::Hash hash = db->get_hash(12);

	ASSERT_FALSE(hash.is_valid());
}

TEST_F(DatabaseTest, prune_hash_table_prune_count) {
	db->add(Database::db_data ("/foo/bar", "1", 41));
	db->add(Database::db_data ("/foo/bar2", "2", 42));
	db->add(Database::db_data ("/foo/bar3", "3", 43));
	db->add(Database::db_data ("/baz/bar", "4", 44));

	db->flush();

	std::list<boost::filesystem::path> paths;
	paths.push_back(boost::filesystem::path("/foo/"));

	db->prunePath(paths);

	int pruned = db->prune_hash_table();

	ASSERT_EQ(3, pruned);
}

TEST_F(DatabaseTest, prune_hash_table_hash_exists) {
	db->add(Database::db_data ("/foo/bar", "1", 41));
	db->add(Database::db_data ("/foo/bar2", "2", 42));
	db->add(Database::db_data ("/foo/bar3", "3", 43));
	db->add(Database::db_data ("/baz/bar", "4", 44));

	db->flush();

	ASSERT_TRUE(db->sha_exists("1"));

	std::list<boost::filesystem::path> paths;
	paths.push_back(boost::filesystem::path("/foo/"));

	db->prunePath(paths);

	ASSERT_FALSE(db->sha_exists("1"));
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

/*!
 * \brief Compute the single-precision of the given vector
 * \param x The vector to compute the sum from (GPU pointer)
 * \param n The size of the vector
 * \param s The stride of the vector
 * \return the sum of the elements of the vector
 */
float egblas_ssum(float* x, size_t n, size_t s);

/*!
 * \brief Compute the single-precision of the given vector
 * \param x The vector to compute the sum from (GPU pointer)
 * \param n The size of the vector
 * \param s The stride of the vector
 * \return the sum of the elements of the vector
 */
double egblas_dsum(double* x, size_t n, size_t s);

#define EGBLAS_HAS_SSUM true
#define EGBLAS_HAS_DSUM true
<commit_msg>Fix doc<commit_after>//=======================================================================
// Copyright (c) 2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#pragma once

/*!
 * \brief Compute the single-precision sum of the given vector
 * \param x The vector to compute the sum from (GPU pointer)
 * \param n The size of the vector
 * \param s The stride of the vector
 * \return the sum of the elements of the vector
 */
float egblas_ssum(float* x, size_t n, size_t s);

/*!
 * \brief Compute the single-precision sum of the given vector
 * \param x The vector to compute the sum from (GPU pointer)
 * \param n The size of the vector
 * \param s The stride of the vector
 * \return the sum of the elements of the vector
 */
double egblas_dsum(double* x, size_t n, size_t s);

#define EGBLAS_HAS_SSUM true
#define EGBLAS_HAS_DSUM true
<|endoftext|>


<commit_before>/*
 * Listener for shutdown signals (SIGTERM, SIGINT, SIGQUIT).
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "ShutdownListener.hxx"

#include <inline/compiler.h>
#include <daemon/log.h>

#include <signal.h>
#include <unistd.h>

inline void
ShutdownListener::SignalCallback(int signo)
{
    daemon_log(2, "caught signal %d, shutting down (pid=%d)\n",
               signo, (int)getpid());

    Disable();
    callback();
}

ShutdownListener::ShutdownListener(EventLoop &loop, Callback _callback)
    :event(loop, BIND_THIS_METHOD(SignalCallback)),
     callback(_callback)
{
    event.Add(SIGTERM);
    event.Add(SIGINT);
    event.Add(SIGQUIT);
}
<commit_msg>event/ShutdownListener: include cleanup<commit_after>/*
 * Listener for shutdown signals (SIGTERM, SIGINT, SIGQUIT).
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "ShutdownListener.hxx"

#include <daemon/log.h>

#include <signal.h>

inline void
ShutdownListener::SignalCallback(int signo)
{
    daemon_log(2, "caught signal %d, shutting down (pid=%d)\n",
               signo, (int)getpid());

    Disable();
    callback();
}

ShutdownListener::ShutdownListener(EventLoop &loop, Callback _callback)
    :event(loop, BIND_THIS_METHOD(SignalCallback)),
     callback(_callback)
{
    event.Add(SIGTERM);
    event.Add(SIGINT);
    event.Add(SIGQUIT);
}
<|endoftext|>


<commit_before>// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <test/util/setup_common.h>
#include <util/system.h>
#include <univalue.h>

#ifdef ENABLE_EXTERNAL_SIGNER
#if defined(WIN32) && !defined(__kernel_entry)
// A workaround for boost 1.71 incompatibility with mingw-w64 compiler.
// For details see https://github.com/bitcoin/bitcoin/pull/22348.
#define __kernel_entry
#endif
#include <boost/process.hpp>
#endif // ENABLE_EXTERNAL_SIGNER

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(system_tests, BasicTestingSetup)

// At least one test is required (in case ENABLE_EXTERNAL_SIGNER is not defined).
// Workaround for https://github.com/bitcoin/bitcoin/issues/19128
BOOST_AUTO_TEST_CASE(dummy)
{
    BOOST_CHECK(true);
}

#ifdef ENABLE_EXTERNAL_SIGNER

bool checkMessage(const std::runtime_error& ex)
{
    // On Linux & Mac: "No such file or directory"
    // On Windows: "The system cannot find the file specified."
    const std::string what(ex.what());
    BOOST_CHECK(what.find("file") != std::string::npos);
    return true;
}

bool checkMessageFalse(const std::runtime_error& ex)
{
    BOOST_CHECK_EQUAL(ex.what(), std::string("RunCommandParseJSON error: process(false) returned 1: \n"));
    return true;
}

bool checkMessageStdErr(const std::runtime_error& ex)
{
    const std::string what(ex.what());
    BOOST_CHECK(what.find("RunCommandParseJSON error:") != std::string::npos);
    return checkMessage(ex);
}

BOOST_AUTO_TEST_CASE(run_command)
{
    {
        const UniValue result = RunCommandParseJSON("");
        BOOST_CHECK(result.isNull());
    }
    {
#ifdef WIN32
        const UniValue result = RunCommandParseJSON("cmd.exe /c echo {\"success\": true}");
#else
        const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
#endif
        BOOST_CHECK(result.isObject());
        const UniValue& success = find_value(result, "success");
        BOOST_CHECK(!success.isNull());
        BOOST_CHECK_EQUAL(success.getBool(), true);
    }
    {
        // An invalid command is handled by Boost
        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), boost::process::process_error, checkMessage); // Command failed
    }
    {
        // Return non-zero exit code, no output to stderr
        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("false"), std::runtime_error, checkMessageFalse);
    }
    {
        // Return non-zero exit code, with error message for stderr
        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("ls nosuchfile"), std::runtime_error, checkMessageStdErr);
    }
    {
        BOOST_REQUIRE_THROW(RunCommandParseJSON("echo \"{\""), std::runtime_error); // Unable to parse JSON
    }
    // Test std::in, except for Windows
#ifndef WIN32
    {
        const UniValue result = RunCommandParseJSON("cat", "{\"success\": true}");
        BOOST_CHECK(result.isObject());
        const UniValue& success = find_value(result, "success");
        BOOST_CHECK(!success.isNull());
        BOOST_CHECK_EQUAL(success.getBool(), true);
    }
#endif
}
#endif // ENABLE_EXTERNAL_SIGNER

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>test: Fix "false" subtest in system_tests for Windows<commit_after>// Copyright (c) 2019-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <test/util/setup_common.h>
#include <util/system.h>
#include <univalue.h>

#ifdef ENABLE_EXTERNAL_SIGNER
#if defined(WIN32) && !defined(__kernel_entry)
// A workaround for boost 1.71 incompatibility with mingw-w64 compiler.
// For details see https://github.com/bitcoin/bitcoin/pull/22348.
#define __kernel_entry
#endif
#include <boost/process.hpp>
#endif // ENABLE_EXTERNAL_SIGNER

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(system_tests, BasicTestingSetup)

// At least one test is required (in case ENABLE_EXTERNAL_SIGNER is not defined).
// Workaround for https://github.com/bitcoin/bitcoin/issues/19128
BOOST_AUTO_TEST_CASE(dummy)
{
    BOOST_CHECK(true);
}

#ifdef ENABLE_EXTERNAL_SIGNER

bool checkMessage(const std::runtime_error& ex)
{
    // On Linux & Mac: "No such file or directory"
    // On Windows: "The system cannot find the file specified."
    const std::string what(ex.what());
    BOOST_CHECK(what.find("file") != std::string::npos);
    return true;
}

bool checkMessageStdErr(const std::runtime_error& ex)
{
    const std::string what(ex.what());
    BOOST_CHECK(what.find("RunCommandParseJSON error:") != std::string::npos);
    return checkMessage(ex);
}

BOOST_AUTO_TEST_CASE(run_command)
{
    {
        const UniValue result = RunCommandParseJSON("");
        BOOST_CHECK(result.isNull());
    }
    {
#ifdef WIN32
        const UniValue result = RunCommandParseJSON("cmd.exe /c echo {\"success\": true}");
#else
        const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
#endif
        BOOST_CHECK(result.isObject());
        const UniValue& success = find_value(result, "success");
        BOOST_CHECK(!success.isNull());
        BOOST_CHECK_EQUAL(success.getBool(), true);
    }
    {
        // An invalid command is handled by Boost
        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("invalid_command"), boost::process::process_error, checkMessage); // Command failed
    }
    {
        // Return non-zero exit code, no output to stderr
#ifdef WIN32
        const std::string command{"cmd.exe /c call"};
#else
        const std::string command{"false"};
#endif
        BOOST_CHECK_EXCEPTION(RunCommandParseJSON(command), std::runtime_error, [&](const std::runtime_error& e) {
            BOOST_CHECK(std::string(e.what()).find(strprintf("RunCommandParseJSON error: process(%s) returned 1: \n", command)) != std::string::npos);
            return true;
        });
    }
    {
        // Return non-zero exit code, with error message for stderr
        BOOST_CHECK_EXCEPTION(RunCommandParseJSON("ls nosuchfile"), std::runtime_error, checkMessageStdErr);
    }
    {
        BOOST_REQUIRE_THROW(RunCommandParseJSON("echo \"{\""), std::runtime_error); // Unable to parse JSON
    }
    // Test std::in, except for Windows
#ifndef WIN32
    {
        const UniValue result = RunCommandParseJSON("cat", "{\"success\": true}");
        BOOST_CHECK(result.isObject());
        const UniValue& success = find_value(result, "success");
        BOOST_CHECK(!success.isNull());
        BOOST_CHECK_EQUAL(success.getBool(), true);
    }
#endif
}
#endif // ENABLE_EXTERNAL_SIGNER

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>